From a7201686a584f4aeb28e265a3ece50ca55907e36 Mon Sep 17 00:00:00 2001
From: kaola-blog-bot <32167555+kaola-blog-bot@users.noreply.github.com>
Date: Wed, 28 Mar 2018 09:35:13 -0500
Subject: [PATCH] auto-archiving for issue #252
---
...54\350\231\253\345\256\236\347\216\260.md" | 98 +++++++++++++++++++
1 file changed, 98 insertions(+)
create mode 100644 "source/_posts/\344\270\200\344\270\252\347\256\200\345\215\225\347\232\204node\347\210\254\350\231\253\345\256\236\347\216\260.md"
diff --git "a/source/_posts/\344\270\200\344\270\252\347\256\200\345\215\225\347\232\204node\347\210\254\350\231\253\345\256\236\347\216\260.md" "b/source/_posts/\344\270\200\344\270\252\347\256\200\345\215\225\347\232\204node\347\210\254\350\231\253\345\256\236\347\216\260.md"
new file mode 100644
index 0000000..209e3f4
--- /dev/null
+++ "b/source/_posts/\344\270\200\344\270\252\347\256\200\345\215\225\347\232\204node\347\210\254\350\231\253\345\256\236\347\216\260.md"
@@ -0,0 +1,98 @@
+
+
+### 前言
+之前有接触到一些做node爬虫的工程师,在获取淘宝卖家授权后,通过nodejs爬取该卖家的淘宝店各项信息,获得每月销售额、好评率等各项信息,对此较感兴趣,自己实现了一个简单的爬虫,爬取计量一新闻库,将文章内容、图片保存至本地。
+
+### 实现方式
+实现这样的效果其实很简单,通过request模块请求某一个新闻页的html,然后通过cheerio实现类似于JQuery操作dom的效果,将你所需要的信息从dom中获取出来。
+
+### 主要实现步骤
+1. 通过分析http://www.cjlu.edu.cn/do.jsp?dotype=newsmm&columnsid=13¤tPage=1 该新闻库可以发现,该类目下新闻共有64页,每页30条新闻,url参数currentPage对应分页页码。
+2. 使用request发送get请求,获取第一分页的html,然后用cheerio分析html,获取当前页内每一条新闻的链接,存入数组urlList。通过network可以发现,该http请求Response Header内Transfer-Encoding: chunked,代表服务端是一边产生数据,一边发给客户端,所以监听data事件,将获取到的data拼接成完整的html。
+
+```
+let html = '';
+request
+ .get(url) //http://www.cjlu.edu.cn/do.jsp?dotype=newsmm&columnsid=13¤tPage=1
+ .on('data',chunk =>{
+ html += chunk;
+ })
+ .on('end',() =>{
+ let $ = cheerio.load(html);
+ let urlList = [];
+ let length = $('.new-main-list li').length;
+ $('.new-main-list li').each((index) =>{
+ let link = 'http://www.cjlu.edu.cn'+$('.new-main-list li a').eq(index).attr('href');
+ urlList.push(link);
+ })
+ resolve(urlList);
+ })
+```
+
+3. 然后依次通过request请求每一条新闻,获取其中的新闻内容和图片,新闻内容使用fs.createWriteStream在本地创建txt文件,并使用fs.appendFileSync写入,图片下载保存到本地。
+
+```
+//将新闻文本内容一段一段添加到/data文件夹下,并用新闻的标题来命名文件
+let fileName = `data/${i}_${news_title}.txt`;
+fs.createWriteStream(fileName);
+$('.main_box').next().find('p').each(function (index, item) {
+ let x = $(this).text();
+ if (x != '') {
+ x = x + '\n';
+ fs.appendFileSync(fileName, x, { encoding: 'utf8'});
+ }
+})
+```
+
+```
+//将新闻内使用图片下载到本地
+request
+ .get(url)
+ .on('error', err => {
+ error_url.push(url);
+ })
+ .pipe(fs.createWriteStream('image/'+img_title));
+```
+
+4. 期间使用async.mapLimit限制并发请求的数量,防止服务器封IP,当然这样的方式是比较简陋的,可以使用动态IP的方式请求。
+
+```
+async.mapLimit(urlLists, 5, function (url, callback) {
+ fetchPage(url, callback);
+}, function (err,result) {
+ console.log('final:');
+ console.log(error_url);
+ console.log(result)
+});
+```
+
+### Nightmare介绍
+nightmare号称爬虫的终极形态,它是一个基于electron的自动化库(自带浏览器),常用于实现爬虫或自动化测试。
+#### 那么它能实现什么功能?
+它可以通过获取dom的方式,模拟用户的操作,比如点击链接、输入账号密码自动登录等,可以通过wait底部元素得到页面dom加载完毕的事件。
+
+在爬豆瓣电影排行榜时,担心被反爬虫机制封IP,就使用了nightmare模拟用户操作,查看排行榜,点击翻页等操作。
+
+```
+nightmare
+ .goto('https://movie.douban.com/')
+ .click('#db-nav-movie > div.nav-secondary > div > ul > li:nth-child(4) > a')
+ .click('.douban-top250-hd a')
+ .wait('#footer')
+ .evaluate(function () {
+ let i = 1;
+ let urlList = [];
+ while(i<26){
+ urlList.push(document.querySelector('#content > div > div.article > ol > li:nth-child('+i+') > div > div.info > div.hd > a').getAttribute('href'))
+ i++;
+ }
+ return urlList;
+ })
+```
+