背景
说到爬虫,大家想到的大多都是python
。其实使用NodeJS
也很适合写爬虫。针对一些简单,高效的小爬虫,Javascript
比python
更加合适。因为Javascript
自带异步,能同时爬取多张网页内容比python
更高效。但是python
生态更加完整(主要是我还不会python😭)
咋爬?
- 确定爬取对象(选一个种子URL) 就近取材就掘金的推荐页面,思路大概就是通过推荐页面的前面20篇博客,然后去详情获取数据。
//1. 推荐API
//URL
https://apinew.juejin.im/recommend_api/v1/article/recommend_all_feed
//参数
{
id_type: 2,
client_type: 2608,
sort_type: 200,
cursor: '0',
limit: 20
}
// 2. 详情API
https://juejin.im/post/【article_id】
- 安装环境
我此处是
KOA
框架的环境,并且安装了babel
支持了ES6
语法。 - 编码,爬取页面数据并分析
思路很简单,把页面当作一个个的get请求,加载之后,使用cheerio
获取页面内的数据,然后使用fs
方法写入到txt文件内。
cheerio
是为服务器特别定制的,快速、灵活、实施的jQuery核心实现。中文文档地址附上,具体API自行查看。
(function() {
const fs = require('fs');
const axios = require('axios');
const cheerio = require('cheerio');
// 使用AXIOS获取推荐LIST数据
axios
.post(
'https://apinew.juejin.im/recommend_api/v1/article/recommend_all_feed',
{
id_type: 2,
client_type: 2608,
sort_type: 200,
cursor: '0',
limit: 20
}
)
.then(async({ data: { data } }) => {
if (data.length === 0) {
console.log('没数据' + data);
return false;
}
for (let i = 0; i < data.length; i++) {
//阻塞一个个的获取每个详情内容
//主要是因为我想按列表顺序排列数据
const res = await axios.get(
//文章ID是我自行查看API分析所得
data[i].item_info.url ||
('https://juejin.im/post/' +
(data[i].item_info.article_id || data[i].item_info.advert_id))
);
//cheerio上场
const $ = cheerio.load(res.data, {
normalizeWhitespace: false,
xmlMode: false,
decodeEntities: false
});
fs.appendFile(
'./spider/result.txt',
//获取article标签内的html内容
//自己可以先观察页面具体情况,在做数据收集
$('article').html(),
'utf8',
err => {
if (err) throw err;
console.log('数据已被追加到文件');
}
);
}
})
.catch(error => {
console.log(error);
});
})();
爬了又爬
想到双12,我就想去爬一下淘宝数据,结果过程有点复杂。还是按照老的方法取分析
(function() {
const fs = require('fs');
const axios = require('axios');
const cheerio = require('cheerio');
//处理中文乱码
const iconv = require('iconv-lite');
const util = require('util');
axios({
methods: 'get',
url:
'https://list.tmall.com/search_product.htm?spm=a221t.1476805.cat.19.52006769d615Pr&cat=54290107&q=%E4%BC%91%E9%97%B2%E5%A5%97%E8%A3%85',
headers: {
'content-type': 'text/html;charset=GBK'
}
})
.then(res => {
if (!res.data) {
console.log('数据为空,无法追加');
return false;
}
const contentBinary = iconv.decode(
Buffer.from(util.inspect(res.data), 'binary'),
'GBK'
);
const $ = cheerio.load(contentBinary, {
normalizeWhitespace: true,
decodeEntities: false
});
console.log($('.productTitle a').attr('title'));
console.log($('em').attr('title'));
fs.appendFile(
'./spider/taobao.txt',
$('.productTitle a').attr('title'),
'utf8',
err => {
if (err) throw err;
console.log('数据已被追加到文件');
}
);
})
.catch(err => {
if (err) throw err;
});
})();
结果打印出来的中文全是乱码,各种百度搜索,然后大多都是推荐
iconv-lite
来处理。但是我这里不生效,不知道为啥。有大佬懂的指点一下
放弃?那是不可能
上面的方法,爬取淘宝网站的内容都是中文乱码。后面我又发现了一个很厉害的工具Puppeteer
,附上gitHub地址。
Puppeteer
是一个控制 headless Chrome
的 Node.js API
。它是一个 Node.js
库,通过 DevTools
协议提供了一个高级的 API 来控制 headless Chrome
。在浏览器中手动完成的大多数事情都可以通过使用 Puppeteer
完成。
Headless Chrome
是啥?其实是在无界面的环境中运行 Chrome。并且能通过命令行或者程序语言操作,无需人的干预,运行更稳定
;(async function() {
const cheerio = require('cheerio');
const puppeteer = require('puppeteer');
const fs = require('fs');
const browser = await puppeteer.launch({
headless: false, // 有浏览器界面启动
slowMo: 100, // 放慢浏览器执行速度,方便测试观察
args: [ // 启动 Chrome 的参数
'–no-sandbox',
'--window-size=1280,960'
]
});
const page = await browser.newPage();
//打开新页面 淘宝需要抓去数据的页面URL
await page.goto(
'https://list.tmall.com/search_product.htm?spm=a221t.1476805.cat.19.52006769d615Pr&cat=54290107&q=%E4%BC%91%E9%97%B2%E5%A5%97%E8%A3%85'
);
//也可以用page.evaluate然后使用document去获取dom数据
//获取页面的html
const html = await page.content();
//使用cheerio分析页面数据
const $ = cheerio.load(html, {
normalizeWhitespace: true,
decodeEntities: false
});
const goods = [];
const price = [];
const saleNum = [];
$('.productTitle a').each((i, elem) => {
goods.push($(elem).attr('title'));
});
$('.productPrice em').each((i, elem) => {
price.push($(elem).attr('title'));
});
$('.productStatus em').each((i, elem) => {
saleNum.push($(elem).text());
});
//将商品名称,价格和月成交量拼接,并且写入CSV文件
const result = goods.reduce((current, item, i) => {
return `${current}\n${item},¥${price[i]},${saleNum[i]}`;
}, '');
fs.appendFile(
'./spider/tmall.csv',
'商品,价格,月成交' + result,
'utf8',
err => {
if (err) throw err;
console.log('数据已被追加到文件');
}
);
await page.close();
await browser.close();
})();
由于这是使用chrome浏览器去获取页面数据,就不存在中文乱码问题。🎉 🎉 🎉 🎉
最后
到这里,基本的小爬虫已经就会咯。但是在淘宝网站里面,搜索只提供第一页数据,分页就需要登录。但是只能用js自行去登录了,然后再去爬数据了。
// 思路大致如下,输入用户和密码,点击登录
await page.type("#username",config.username);
await page.type("#password",config.password);
await page.click('#login');
console.log("Login Secuessed...");
喜欢的大佬,点个赞👆👆👆
喜欢的大佬,点个赞👆👆👆
喜欢的大佬,点个赞👆👆👆