如何编写简单爬虫
2019-09-27
nodejs
4569
说到爬虫,很多人可能觉得很高端,很厉害。但其实是单间的,它的原理就一条:
请求数据数据,解析数据
请求数据:发送一个http请求,获得数据字符串
解析数据:通过一定的手段把需要的数据从刚才的字符串中选出来
来看一个简单的例子:
目标: 爬取简书文档,上传到掘金上
step1: 获取文章数据
以 https://www.jianshu.com/p/47f1fb7fc842
为例
通过request库请求页面,打印出来应该是一个html页面
const request = require('request');
request.get('https://www.jianshu.com/p/47f1fb7fc842', function (error, response, body) {
console.log(body);
});
step2: 解析数据
解析html数据,需要用到另一个模块cheerio
,它能在node环境中像jquery一样操作html数据。
const request = require('request');
const cheerio = require('cheerio');
request.get('https://www.jianshu.com/p/47f1fb7fc842', function (err, response, body) {
const $ = cheerio.load(body);
const pageTitle = $('title').text();
console.log(pageTitle) // 页面title Nodejs入门实践第一讲Nodejs基础 - 简书
// 解析content
const article = $('article').html();
console.log(article);
});
到这里,我们想要的html数据已经有了。
但是,html的冗余数据比较多,比如css,冗余结构,不方便我们扩展。这里我们再加工一下,将html转换成markdown文件。
将html转化为md需要用到turndown模块,具体如下:
const TurndownService = require('turndown');
const turndownService = new TurndownService({ codeBlockStyle: 'fenced' });
function jianshuHtml2Md(htmlStr) {
const md = turndownService.turndown(htmlStr);
console.log(md);
return md
}
到这里,html已经转换为md了。
但是,问题还没完,打开这个md,发现没有图片。
找了一下,图片用了另一种样式
<div class="image-package">
<div class="image-container" style="max-width: 700px; max-height: 288px;">
<div class="image-container-fill" style="padding-bottom: 36.83%;"></div>
<div class="image-view" data-width="782" data-height="288"><img data-original-src="//upload-images.jianshu.io/upload_images/3735524-222980d6394acd09.png" data-original-width="782" data-original-height="288" data-original-format="image/png" data-original-filesize="20082"></div>
</div>
这里不要怕,继续加解析就行。例子可以参考:这里>
// 给turndownService解析器加一个自定义规则,用来解析图片
turndownService.addRule('rules1', {
filter: function (node, options) {
return node.nodeName === 'IMG'
},
replacement: function (content, node, options) {
return `![](http:${node.getAttribute('data-original-src')})`
}
});
现在就ok拉。
还有就是图片转存,上传等下次再讲。
完整代码:
const request = require('request');
const cheerio = require('cheerio');
const TurndownService = require('turndown');
const turndownService = new TurndownService({codeBlockStyle: 'fenced'});
const fs = require('fs');
turndownService.addRule('rules1', {
filter: function (node, options) {
return node.nodeName === 'IMG'
},
replacement: async function (content, node, options) {
return `![](http:${node.getAttribute('data-original-src')})`
}
});
request.get({
url: 'https://www.jianshu.com/p/47f1fb7fc842',
headers: {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36',
'referer': 'https://www.jianshu.com/search?q=nodejs&page=1&type=note',
}
}, function (err, response, body) {
const $ = cheerio.load(body);
const pageTitle = $('title').text();
console.log(pageTitle); // Nodejs入门实践第一讲Nodejs基础 - 简书
// 解析content
const article = $('article').html();
jianshuHtml2Md(article)
});
function jianshuHtml2Md (htmlStr) {
const md = turndownService.turndown(htmlStr);
fs.writeFile(`./test.md`, md, (err) => {
if (err) {
console.log(err)
}
});
return md
}