很多人问写爬虫用什么语言比较好,其实就和谈恋爱一样,没有最好的,只有最合适的,选择你最熟悉最顺手的语言就好。今年各种需求不断,写了几个爬虫,都是用的 nodejs。
这里总结一些用 nodejs 写爬虫的常用手段,学会了,就能爬取大部分网页了。开发爬虫的技巧很多也是复用的,记录下来,日后能省不少事。
基本请求网页方法
用 got 发送 Get 和 Post 请求,返回值均为 Promise,可以使用 async/await 和 Promise.all 来控制流程。
// 习惯使用 got
const got = require('got');
// get
client.get(url);
// post formdata
const FormData = require('form-data');
const form = new FormData();
form.append('name', 'admin');
got.post(url, {
body: form
});
// post json
got.post(url, {
json: {
page: 2
},
responseType: 'json'
});
伪装浏览器
通过设置 User-Agent 来模拟浏览器行为。现在很多服务器都会检查 User-Agent 来进行初步的反爬,设置 User-Agent 是很重要的一步。
got.get(url, {
headers: {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36'
}
})
也可以通过下面的方式,来为每个请求带上 User-Agent,当然其他参数也是一样的。
// 所有通过 client 发起的请求均会带上 extend 里传入的参数
const client = got.extend({
headers: {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36'
}
});
client.get(url);
取消自动重定向
这里要说明一点,got 默认会自动进行重定向,并返回重定向后的返回值,而部分网站需要处理动态的 Cookie 才能得到正确的结果,自动重定向可能会使用不正确的 Cookie 导致结果永远不对,因此还是老老实实手动重定向吧。
client.get(url, {
followRedirect: false // 取消自动重定向
});
获取特定 Cookie 的值
Cookie 通常用于用户的身份鉴别,偶尔也用于加密反爬。写爬虫经常需要和它打交道,但是读取 Cookie 的值不是很方便,这里提供一个方法来简单的获取所需要的 Cookie 值,该方法同样适用于获取 Set-Cookie 的值。
// 来自 stackoverflow: https://stackoverflow.com/questions/5142337/read-a-javascript-cookie-by-name
// 稍微做了点修改
function getCookie(cookiename, cookies) {
// Get name followed by anything except a semicolon
let cookiestring = RegExp(cookiename+"=[^;]+").exec(cookies);
// Return everything after the equal sign, or an empty string if the cookie name not found
return decodeURIComponent(!!cookiestring ? cookiestring.toString().replace(/^[^=]+./,"") : "");
}
Sleep
做爬虫也要讲文明,要在不影响对方服务的前提下进行,所以要控制爬虫的速率。但是 nodejs 本身并没有像 python 那样的 time.sleep() 方法,因此要自己实现一个。
function sleep(time = 0) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, time);
});
}
页面解析
可以使用正则表达式来解析页面,比任何解析器都要强大。
想学习和在线测试正则表达式,强烈推荐到 RegExr,全是简单的英文,很好懂。
除了正则,npm 上有很多做 HTML 解析的包,最常用也最多人用的就是 cheerio。
用法很简单,和 jquery 一摸一样。
const cheerio = require('cheerio');
// 设置 decodeEntities 为 false,为了防止中文被解码。
const $ = cheerio.load(html, { decodeEntities: false });
// 然后就把 $ 当作 jquery 用就好了
$('body').text();
当然,你也可以用 jquery,只不过需要 mock window 和 document 对象,所以需要配合 jsdom 来食用。
const { JSDOM } = require( "jsdom" );
const { window } = new JSDOM( "" );
const $ = require( "jquery" )( window );
多进程并行爬取
javascript 是单线程的,nodejs 因此也一样,但是现在普遍多核的大背景下,nodejs 早就意识到了这点,为了能够充分的“压榨”机器的性能,nodejs 推出一个内置模块 – cluster。没错,单机集群,由一个父进程管理一群子进程。
这样就可以通过多个子进程的方式来实现并行爬取。
const cluster = require('cluster');
const numCPUs = require('os').cpus().length; // cpu 核心数
if (cluster.isMaster) {
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
} else {
// 爬虫逻辑
}
内容不多,但是非常实用,至少我自己在日常开发爬虫的过程中经常使用,希望对各位有帮助吧。