一个前端小白的"爬虫"初试

前言

八月。透蓝的天空,悬着火球般的太阳,云彩好似被太阳烧化了,也消失得无影无踪。没有一丝风,大地活像一个蒸笼。

好热,好烦躁,好无聊。无意间又打开知乎😋,首页冒出一个问题给好看的女生拍照是种怎样的体验?,齐刷刷一大摞好看的小姐姐,看的人好生陶醉。作为一个曾经的理工屌丝男,我相信此刻你的想法和我一样,要是可以把她们装进那《学习教程》文件夹就好了。

怎么办?一张张图片右键保存吗?不不不,效率低,鼠标按多了“右手”还疼😈。差点忘了,我特么是个程序员啊!程序员啊!程序员啊!这种事难道不应该交给程序去干嘛。

"说干就干"

原文地址
源码地址

需求

需求很简单:希望知乎APP自适应用户手机壳颜色。

啊呸呸呸,应该是

需求很简单:实现自动下载知乎某个帖子下所有回答的图片到本地

分析

需求很明确,所以我想只要知道了以下两点基本就能够完成了。

  1. 图片链接
    > 能够获取帖子下面答题者上传的图片链接,至于所有图片,那就是所有回答者上传的图片链接了
  2. 下载图片
    > 这个暂时猜想是使用成熟的库,我只需要传入图片链接地址,以及图片下载到哪个目录就可以完成。如果没找着这样的库,就只能研究原生的nodejs如何做了。

针对1,我们打开chrome浏览器的控制台,发现页面一打开的时候会有很多个请求发出,但是有一个带"answers"请求很可疑,是不是它负责返回答题者的答案呢?

在验证这个想法之前,我们先不去看这个请求的具体响应内容。我们先点击一下页面上的查看全部 948 个回答按钮,如果猜的对,"answers"请求应该会再次发出,并且返回答题者的答案。

点击按钮之后发现,“answers”确实再次发出了,并且查看其响应内容大体如下

从响应中我们拿到总的回答数量,以及当前请求返回的答题者的内容也就是content字段,我们要的图片地址就在noscript标签下的img标签的data-original属性中。所以针对要求1,我们似乎已经拿到了50%的信息,还有另一半的信息是,我们如何获取所有答题者的内容?,别忘了刚才的响应中还有paging字段,其中。

再结合"answers"这个请求的路径

https://www.zhihu.com/api/v4/questions/49364343/answers?include=data[*].is_normal,admin_closed_comment,reward_info,is_collapsed,annotation_action,annotation_detail,collapse_reason,is_sticky,collapsed_by,suggest_edit,comment_count,can_comment,content,editable_content,voteup_count,reshipment_settings,comment_permission,created_time,updated_time,review_info,relevant_info,question,excerpt,relationship.is_authorized,is_author,voting,is_thanked,is_nothelp;data[*].mark_infos[*].url;data[*].author.follower_count,badge[?(type=best_answerer)].topics&offset=3&limit=5&sort_by=default

其中路径部分
https://www.zhihu.com/api/v4/questions/49364343/answers,49364343应该就是帖子的id

query请求部分总共有三个参数

所以看起来,咱们把offset设置为0,limit设置为totals的值,是不是就可以拿到所有数据了呢?尝试之后发现,最多只能拿到20个答题者的数据,所以我们还是根据is_end以及next两个响应值,多次请求,逐步获取所有数据吧。

针对2. 最后一顿google搜索发现还真有这么一个库request,比如要下载一张在线的图片到本地只需要些如下代码

到这里1和2两个条件都具备了,接下来要做的就是撸起来,写代码实现了。

预览

在说代码实现之前,我们先看一个录制的gif,以及如何使用crawler.js

点击查看gif

使用

proxyUrl先不关注,后面会仔细说明这个字段的作用

源码实现

点击查看crawler.js

源码实现基本上很简单,大家看注释就可以很快明白。

ip被封

正当我用写好的crawler.js下载多个帖子下面的图片的时候,程序报了一个这个提示。

系统检测到您的帐号或IP存在异常流量,请进行验证用于确认这些请求不是自动程序发出的"

完蛋了,知乎不让我请求了😭😭😭。

完蛋了,知乎不让我请求了😭😭😭。

完蛋了,知乎不让我请求了😭😭😭。

折腾了半天,最后被当做爬虫给封了。网上找了一些解决方法,例如爬虫怎么解决封IP?

基本上是两个思路

1、放慢抓取速度,减小对于目标网站造成的压力。但是这样会减少单位时间类的抓取量。

2、第二种方法是通过设置代理IP等手段,突破反爬虫机制继续高频率抓取。但是这样需要多个稳定的代理IP。

继续用本机并且在ip没有发生变化的情况下,直接请求知乎是不可能了,不过我们可以尝试一下2.使用代理服务器。突然想起自己去年在搬瓦工买了一个服务器,😀。平时除了用它作为vpn存在访问一些被墙的网站外,就只放了一个resume-native程序。虽然没法做到像上面两张图一样,哪个代理服务被封,及时再切换另一个代理服务器。但是至少可以通过代理服务器再次下载图片,撸起来。。。

另找出路

代理程序proxy.js运行在服务器上,会监测路径为/proxy*的请求,请求到来的时候通过自己以前写的请求转发httpProxy中间件去知乎拉取数据,再返回响应给我们本地。用一张图表示如下

所以我们原来的请求路径是(为了简化把include这个很长的query参数去除了)
https://www.zhihu.com/api/v4/questions/49364343/answers?offset=3&limit=5&sort_by=default

经过代理服务器后变成了(其中xxx.yyy.zzz可以是你自己的代理服务器的域名或者ip加端口)
https://xxx.yyy.zzz/proxy/api/v4/questions/49364343/answers?offset=3&limit=5&sort_by=default

点击查看代理模式gif图左侧是服务器上打印的信息,右侧是本地打印的信息

这样我们间接地绕过了知乎封ip的尴尬,不过这只是临时方案,终究代理服务器也会被封ip。

结尾

好快,一眨眼就下午5点了。这个简单的"爬虫"初试,或者根本就算不上什么爬虫,也有许多不完善的地方,就先放一放啦。天气稍微凉爽了些,该出去走走了。

如果你喜欢,请点一颗星星噢😯

如果你喜欢,请点一颗星星噢😯

如果你喜欢,请点一颗星星噢😯

原文地址
源码地址

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复