前言,此文章仅做教学用途,若是有人拿去干别的事情,我概不负责,若是该文章侵害到了掘金社区的利益,请膜法小编马上联系我删除.node
这是我在掘金的第一篇文章,遂想写个爬虫教程吧,目标就是掘金,嘿嘿git
所有代码见githubgithub
开始我是尝试直接请求掘金首页,而后用cheerio解析,而后拿到网页继续干活的。。但是事情并无这么简单,经过这个方法爬取的网页跟咱们正常浏览的首页不同(有多是我哪姿式不对) 没办法,只能从接口出发了web
首先打开网页版掘金, 而后打开chrome的network,查看相关请求chrome
这可怎么办?我没有登录 查看完全部请求响应都没看到跟suid有关的,这可咋整?数据库
直接进入请求网址,再更改suid,发现随便更改均可以获得相应 可是。。。这并无什么用啊!就10条信息还须要爬吗?json
没办法了,只能老套路了。先登录再说promise
为了防止页面跳转后登录请求消失,须要先勾选Preserve log,使页面跳转后前面的请求不会消失浏览器
差点忘打码了,qwqbash
let data = await request.create({
url: 'https://juejin.im/auth/type/email',
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({email: '155com', password: 'cfdsd.'}) //帐号密码
});
复制代码
直接一个请求搞定,获得以下相应,问题的关键就在于cookie
好了,接下来该找接口了,点击最新,发现network多了下面这个请求,其响应数据就是最新板块的文章
当你看到token的时候,你会发现,哪都找不到这个数据
可是你仔细看第5张图的时候,你会发现这auth后面这串字符很像base64编码
打开相关网站,尝试解码
答案呼之欲出啊,最重要的三个参数全在这了,那么问题来了,node如何解析base64编码呢?
一行代码解决,buffer对象自己提供了base64的解码功能,最后调用toString方法,转成字符串,最后parse获得对象
const cookie = data.headers['set-cookie'];
const encodeToken = cookie[0]
.split(';')[0]
.split('=')[1];
const decodeToken = JSON.parse(new Buffer(encodeToken, 'base64').toString())
复制代码
有了token,你就能够为所欲为的爬了,爬图片?主题?标题?文章内容?彻底o98k
async function getPictureUrl(request, url) {
let data = await request.get({ url });
console.log(data.body.match(/(https:\/\/user-gold-cdn).+?\/ignore-error\/1/g)); //匹配出图片url,这里掘金使用了cdn来存储图片
}
复制代码
async function getTopics(request, typeKey) {
const { token, clientId, userId } = require('./user.json');
const querystring = qs.stringify({
src: 'web',
uid: userId,
device_id: clientId,
token: token,
limit: 20,
category: 'all',
recomment: 1
});
const types = {
timeline: 'get_entry_by_timeline', //最新
comment: 'get_entry_by_comment', //评论
rank: 'get_entry_by_rank' //热门
};
const data = await request.get({
url: `https://timeline-merger-ms.juejin.im/v1/${types[typeKey]}?${querystring}`,
headers: {
host: 'timeline-merger-ms.juejin.im',
referer: 'https://juejin.im/timeline?sort=comment'
}
});
const body = data.body;
if (body.s !== 1) { //出错时清空信息
fs.writeFileSync('./user.json', JSON.stringify({}));
throw { type: 'token', message: body.m };
} else {
return body.d.entrylist;
}
}
复制代码
try {
(async function() {
const request = new Riven();
request.setDefaultOptions({
headers: {
Cookie:
'gr_user_id=44868117-2a80-49e8-ba2b-2acd2a77a887; ab={}; _ga=GA1.2.1234597644.150' +
'6904166; MEIQIA_EXTRA_TRACK_ID=0uMtBISQ3EoiMICJMjpaZedfTBz; _gid=GA1.2.100579701' +
'2.1523672771; Hm_lvt_93bbd335a208870aa1f296bcd6842e5e=1521573516,1521573752,1522' +
'270605,1523672771; gr_session_id_89669d96c88aefbc=d54a635e-cece-4f16-aca4-808ae9' +
'2ee559; gr_cs1_d54a635e-cece-4f16-aca4-808ae92ee559=objectId%3A5a974f6ef265da4e8' +
'53d8d52; auth=; auth.sig=25Jg_aucc6SpX1VH8RlCoh6azLU; Hm_lpvt_93bbd335a208870aa1' +
'f296bcd6842e5e=1523675329; QINGCLOUDELB=165e4274d6090771b096025ed82d52a1ab7e48fb' +
'3972913efd95d72fe838c4fb|WtFwy|WtFwr'
}
}); //设不设置cookie都OK的
if (!isLogin()) {
login(request);
}
const topics = await getTopics(request, 'commnet');
for (let i = 0; i < topics.length; ++i) {
//await getDetailData(request, topics[i].objectId);
getPictureUrl(request, topics[i].originalUrl);
await sleep(2000); //伪线程挂起
}
})();
process.on('unhandledRejection', error => {
if (error.type === 'token') {
login();
}
console.log(error.message);
});
} catch (error) {
console.log(error.message);
}
复制代码
固然,我没有使用数据库来保存数据,这只是教你们爬取原理,到这里,一个超级简单的爬虫就完成了
到最后好像也没用到cheerio了 ◔ ‸◔?
以上代码或言论若有错误,还望你们指出
最后,我要吐槽一句编辑器,竟然不支持粘贴图片???