2024年Python最全使用爬虫技术实现 Web 页面资源可用性检测_系统可用性爬虫

在早些年,基本上绝大多数网站都是通过后端渲染的,即在服务器端组装形成完整的 HTML 页面,然后再将完整页面返回给前端进行展现。而近年来,随着 AJAX 技术的不断普及,以及 AngularJS 这类 SPA 框架的广泛应用,前端渲染的页面越来越多。

不知大家有没有听说过,前端渲染相比于后端渲染,是不利于进行 SEO 的,因为对爬虫不友好。究其原因,就是因为前端渲染的页面是需要在浏览器端执行 JavaScript 代码(即 AJAX 请求)才能获取后端数据,然后才能拼装成完整的 HTML 页面。

针对这类情况,当前也已经有很多解决方案,最常用的就是借助 PhantomJS、puppeteer 这类 Headless 浏览器工具,相当于在爬虫中内置一个浏览器内核,对抓取的页面先渲染(执行 Javascript 脚本),然后再对页面内容进行抓取。

不过,要使用这类技术,通常都是需要使用 Javascript 来开发爬虫工具,对于我这种写惯了 Python 的人来说的确有些痛苦。

直到某一天,kennethreitz 大神发布了开源项目 requests-html,看到项目介绍中的那句 Full JavaScript support! 时不禁热泪盈眶,就是它了!该项目在 GitHub 上发布后不到三天,star 数就达到 5000 以上,足见其影响力。

requests-html 为啥会这么火?

写过 Python 的人,基本上都会使用 requests 这么一个 HTTP 库,说它是最好的 HTTP 库一点也不夸张(不限编程语言),对于其介绍语 HTTP Requests for Humans 也当之无愧。也是因为这个原因,Locust 和 HttpRunner 都是基于 requests 来进行开发的。

而 requests-html,则是 kennethreitz 在 requests 的基础上开发的另一个开源项目,除了可以复用 requests 的全部功能外,还实现了对 HTML 页面的解析,即支持对 Javascript 的执行,以及通过 CSS 和 XPath 对 HTML 页面元素进行提取的功能,这些都是编写爬虫工具非常需要的功能。

在实现 Javascript 执行方面,requests-html 也并没有自己造轮子,而是借助了 pyppeteer 这个开源项目。还记得前面提到的 puppeteer 项目么,这是 GoogleChrome 官方实现的 Node API;而 pyppeteer 这个项目,则相当于是使用 Python 语言对 puppeteer 的非官方实现,基本具有 puppeteer 的所有功能。

理清了以上关系后,相信大家对 requests-html 也就有了更好的理解。

在使用方面,requests-html 也十分简单,用法与 requests 基本相同,只是多了 render 功能。

from requests_html import HTMLSession

session = HTMLSession()
r = session.get('http://python-requests.org')
r.html.render()

在执行 render() 之后,返回的就是经过渲染后的页面内容。

爬虫实现访问频率控制

为了防止流量攻击,很多网站都有访问频率限制,即限制单个 IP 在一定时间段内的访问次数。若超过这个设定的限制,服务器端就会拒绝访问请求,即响应状态码为 403(Forbidden)。

这用来应对外部的流量攻击或者爬虫是可以的,但在这个限定策略下,公司内部的爬虫测试工具同样也无法正常使用了。针对这个问题,常用的做法就是在应用系统中开设白名单,将公司内部的爬虫测试服务器 IP 加到白名单中,然后针对白名单中的 IP 不做限制,或者提升限额。但这同样可能会出现问题。因为应用服务器的性能不是无限的,假如爬虫的访问频率超过了应用服务器的处理极限,那么就会造成应用服务器不可用的情况,即响应状态码为 503(Service Unavailable Error)。

基于以上原因,爬虫的访问频率应该是要与项目组的开发和运维进行统一评估后确定的;而对于爬虫工具而言,实现对访问频率的控制也就很有必要了。

那要怎样实现访问频率的控制呢?

我们可以先回到爬虫本身的实现机制。对于爬虫来说,不管采用什么实现形式,应该都可以概括为生产者和消费者模型,即:

  • 消费者:爬取新的页面
  • 生产者:对爬取的页面进行解析,得到需要爬取的页面链接

对于这种模型,最简单的做法是使用一个 FIFO 的队列,用于存储未爬取的链接队列(unvisited_urls_queue)。不管是采用何种并发机制,这个队列都可以在各个 worker 中共享。对于每一个 worker 来说,都可以按照如下做法:

  • 从 unvisited_urls_queue 队首中取出一个链接进行访问;
  • 解析出页面中的链接,遍历所有的链接,找出未访问过的链接;
  • 将未访问过的链接加入到 unvisited_urls_queue 队尾
  • 直到 unvisited_urls_queue 为空时终止任务

然后回到我们的问题,要限制访问频率,即单位时间内请求的链接数目。显然,worker 之间相互独立,要在执行端层面协同实现整体的频率控制并不容易。但从上面的步骤中可以看出,unvisited_urls_queue 被所有 worker 共享,并且作为源头供给的角色。那么只要我们可以实现对 unvisited_urls_queue 补充的数量控制,就实现了爬虫整体的访问频率控制。

以上思路是正确的,但在具体实现的时候会存在几个问题:

  • 需要一个用于存储已经访问链接的集合(visited_urls_set),该集合需要在各个 worker 中实现共享;
  • 需要一个全局的计数器,统计到达设定时间间隔(rps即1秒,rpm即1分钟)时已访问的总链接数;

并且在当前的实际场景中,最佳的并发机制是选择多进程(下文会详细说明原因),每个 worker 在不同的进程中,那要实现对集合的共享就不大容易了。同时,如果每个 worker 都要负责对总请求数进行判断,即将访问频率的控制逻辑放到 worker 中实现,那对于 worker 来说会是一个负担,逻辑上也会比较复杂。

因此比较好的方式是,除了未访问链接队列(unvisited_urls_queue),另外再新增一个爬取结果的存储队列(fetched_urls_queue),这两个队列都在各个 worker 中共享。那么,接下来逻辑就变得简单了:

  • 在各个 worker 中,只需要从 unvisited_urls_queue 中取数据,解析出结果后统统存储到 fetched_urls_queue,无需关注访问频率的问题;
  • 在主进程中,不断地从 fetched_urls_queue 取数据,将未访问过的链接添加到 unvisited_urls_queue,在添加之前进行访问频率控制。

具体的控制方法也很简单,假设我们是要实现 RPS 的控制,那么就可以使用如下方式(只截取关键片段):

start_timer = time.time()
requests_queued = 0

while True:
    try:
        url = self.fetched_urls_queue.get(timeout=5)
    except queue.Empty:
        break

    # visited url will not be crawled twice
    if url in self.visited_urls_set:
        continue

    # limit rps or rpm
    if requests_queued >= self.requests_limit:
        runtime_secs = time.time() - start_timer
学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!



### 一、Python所有方向的学习路线



Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。



![](https://img-blog.csdnimg.cn/img_convert/9f49b566129f47b8a67243c1008edf79.png)



### 二、学习软件

工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。



![](https://img-blog.csdnimg.cn/img_convert/8c4513c1a906b72cbf93031e6781512b.png)



### 三、全套PDF电子书



书籍的好处就在于权威和体系健全,刚开始学习的时候你可以只看视频或者听某个人讲课,但等你学完之后,你觉得你掌握了,这时候建议还是得去看一下书籍,看权威技术书籍也是每个程序员必经之路。

![](https://img-blog.csdnimg.cn/img_convert/46506ae54be168b93cf63939786134ca.png)



### 四、入门学习视频

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。



![](https://img-blog.csdnimg.cn/afc935d834c5452090670f48eda180e0.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56iL5bqP5aqb56eD56eD,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)



### 五、实战案例



光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。



![](https://img-blog.csdnimg.cn/img_convert/252731a671c1fb70aad5355a2c5eeff0.png)



### 六、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。



![](https://img-blog.csdnimg.cn/img_convert/6c361282296f86381401c05e862fe4e9.png)  

![](https://img-blog.csdnimg.cn/img_convert/d2d978bb523c810abca3abe69e09bc1a.png)




**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化学习资料的朋友,可以戳这里无偿获取](https://bbs.csdn.net/topics/618317507)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
  • 20
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值