应邀写一点使用Node.js爬点资料的实例,对于大家建站爬一些初始资料或者做分析研究的小伙伴们应该有些帮助。
目标地址: http://wcatproject.com/charSearch/
抓取内容:抓取所有4星角色的数值数据。如果我们采用手工采集的步骤,需要先进入目标地址,然后选择4星角色的选项,页面下方出现所有4星角色的头像,依次点击每个4星角色头像后会出现角色的详细页面,记录下详细页面中数据。显然这样的做法如果角色一多,手工处理是非常吃力的,所以我们就需要一个自动的脚本去完成这样的动作。大家不妨先手工试试这样的访问步骤,有助于后面的分析和实践。
页面分析:
Request URL
我们需要调用的请求地址: http://wcatproject.com/charSearch/function/getData.php Request Method
该请求的类型:POST Request Header
请求的头信息 Form Data
请求的表单信息 Response
和 Preview
中可以看到返回的内容和格式化内容,可以看到返回的是一个角色ID和角色名称的数组内容 char/角色id
Request Method
为GET,因此没有Form Data信息。 最后在理一下思路,我们的脚本过程如下:
char/角色id
规则访问各个角色的详细页面,并解析其中需要的数据并按我们想要的方式存储起来 npm init
,根据提示,逐步输入工程信息,具体示例如下 $ npm init This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sensible defaults. See `npm help json` for definitive documentation on these fields and exactly what they do. Use `npm install <pkg> --save` afterwards to install a package and save it as a dependency in the package.json file. Press ^C at any time to quit. name: (workspace) demo version: (1.0.0) description: 爬虫案例 entry point: (index.js) test command: git repository: keywords: author: 程序猿DD license: (ISC) About to write to /Users/diyongchao/Documents/workspace/package.json: { "name": "demo", "version": "1.0.0", "description": "爬虫案例", "main": "index.js", "scripts": { "test": "echo /"Error: no test specified/" && exit 1" }, "author": "程序猿DD", "license": "ISC" } Is this ok? (yes) yes $
package.json
文件,其中包含了工程的基本信息以及引用的框架等信息 安装命令 npm install --save PACKAGE_NAME
,执行以下三条命令后,工程目录下多了一个 node_modules
目录,该目录就是引入的框架内容。
$npm install --save superagent $npm install --save cheerio $npm install --save async
工程目录下,创建index.js
var superagent = require('superagent'); var cheerio = require('cheerio'); var async = require('async'); console.log('爬虫程序开始运行......'); // 第一步,发起getData请求,获取所有4星角色的列表 superagent .post('http://wcatproject.com/charSearch/function/getData.php') .send({ info: 'isempty', star : [0,0,0,1,0], job : [0,0,0,0,0,0,0,0], type : [0,0,0,0,0,0,0], phase : [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], cate : [0,0,0,0,0,0,0,0,0,0], phases : ['初代', '第一期','第二期','第三期','第四期','第五期','第六期', '第七期','第八期','第九期','第十期','第十一期','第十二期','第十三期','第十四期', '第十五期', '第十六期'], cates : ['活動限定','限定角色','聖誕限定','正月限定','黑貓限定','中川限定','茶熊限定','夏日限定'] }) .set('Accept', 'application/json, text/javascript, */*; q=0.01') .set('Content-Type','application/x-www-form-urlencoded; charset=UTF-8') .end(function(err, res){ // 请求返回后的处理 // 将response中返回的结果转换成JSON对象 var heroes = JSON.parse(res.text); // 并发遍历heroes对象 async.mapLimit(heroes, 1, function (hero, callback) { // 对每个角色对象的处理逻辑 var heroId = hero[0]; // 获取角色数据第一位的数据,即:角色id fetchInfo(heroId, callback); }, function (err, result) { console.log('抓取的角色数:' + heroes.length); } ); }); // 获取角色信息 var concurrencyCount = 0; // 当前并发数记录 var fetchInfo = function(heroId, callback){ concurrencyCount++; // console.log("...正在抓取"+ heroId + "...当前并发数记录:" + concurrencyCount); // 根据角色ID,进行详细页面的爬取和解析 superagent .get('http://wcatproject.com/char/' + heroId) .end(function(err, res){ // 获取爬到的角色详细页面内容 var $ = cheerio.load(res.text,{decodeEntities: false}); // 对页面内容进行解析,以收集队长技能为例,此处可根据自己的需要进行写数据等操作来记录收集的信息 console.log(heroId + '/t' + $('.leader-skill span').last().text()) concurrencyCount--; callback(null, heroId); }); };
工程目录下执行命令, node index.js
,抓取程序开始执行
$ node index.js 爬虫程序开始运行...... SS0441 平衡型傷害增加 (20%) NS1641 防禦型的移速增加 (20%) SS1141 技術型的技能傷害增加 (20%) SS1041 攻擊型的SP增加 (15%) SS0941 攻擊型傷害增加 (20%) SS0841 劍士減傷 (10%) / 技術型減傷 (15%) LS0941 全員傷害增加 (15%) LS1441 劍士傷害增加 (10%) / 技術型傷害增加 (15%) SS0741 劍士雷屬性傷害增加 (50%) SS0641 攻擊型傷害增加 (20%) NS1741 技能型的SP消費減少 (15%) NS1141 全員傷害增加 (15%) NS0031-A 獲得的魂增加 (20%) SS0501 技術型傷害增加 (20%) SS0141 劍士傷害增加 (20%) SS0241 全員傷害增加 (15%)
如果觉得爬的慢,可以通过修改 async.mapLimit(heroes, 1, function (hero, callback)
中的1来调整并发数量,同时也可以去掉// console.log("...正在抓取"+ heroId + "...当前并发数记录:" + concurrencyCount);的注释,用来观察执行过程中并发数。
如果对示例有疑问,欢迎留言交流^_^