htmlunit抓取动态网页( 爬虫适应国内爬虫架构的解决方案架构解决方案摘要 )
优采云 发布时间: 2021-10-15 08:22htmlunit抓取动态网页(
爬虫适应国内爬虫架构的解决方案架构解决方案摘要
)
如何制作最好的定向爬虫架构
姓名:郭忠
目前职位:在一家创业公司做爬虫工程师
概括
随着互联网信息的不断发展,信息和数据的挖掘技术也在不断发展。网络爬虫技术也得到了很大的发展。对于内容驱动的网站来说,反抄袭是必不可少的东西。很多网站使用Jquery脱壳,登录验证,限制每IP每秒请求数,防止爬虫窃取数据。因此,爬虫的智能化也越来越受到挑战。这就产生了一个适应目前国内爬虫架构的解决方案。
介绍
内容
1、—————重新优化URL深度优先策略
2、——————模拟浏览器内核,让爬行更强大
3、——————适配无效代理ip的管理优化
4、——————URL 上下文使开发业务逻辑更容易
5、—————— 多线程控制
6、——————任务的时间安排
7、——————转储错误页面会让调试更方便
8、—————— 爬取日志解决中断抓包
9、————— 爬虫JVM参数优化
10、————————基于hadoop分布式
1、重新优化URL深度优先策略
深度优先搜索策略。这个策略的主要思想是从根节点开始寻找叶子节点,以此类推。在网页中,选择一个超链接,链接的网页将进行深度优先搜索,形成一个单一的搜索链。当没有其他超链接时,搜索结束。但是,这种自动化的URL深度定制并不能达到业务需求的最佳优先状态。
让我们看看传统的 URL 队列模型。图中有一个入口网址“A”,解析得到三个后续网址“B”。传统的抓取顺序由飞机图标标记。每个子条目 URL 被顺序捕获到“C”。问题出来了。如果需要捕获的信息在C中,那么可以使用第一个C1来捕获C1的信息。为什么要等到 B 爬完才开始爬 C?而如果依赖于 URL 的深度,则较低的 URL 会累积。这是对内存的巨大浪费,所以爬虫很容易出现内存溢出,这也反映了一个方面。
最好的优化效果是获取一组“B”的URL,然后递归地获取每个B及其下面的子URL“C”。这样就不会出现当前无法处理但占用大量内存的后续URL堆积问题。优化后,如图。
2、模拟浏览器内核,让爬虫更强大
网页需要的内容由JS动态加载。有的甚至在jquery加载html源码后根本看不到信息数据。解决这个问题的唯一办法就是让爬虫本身变成一个没有界面的浏览器。现在java有现成的浏览器驱动库htmlunit,可以模拟浏览器,也可以调用现成的火狐和谷歌内核。Python 有 pyv8 JS 引擎、QtWebKit 等组件。有了这些组件,我们用js调用封装一个爬虫,模拟登录就很简单了。
模拟浏览器架构:
1、由于浏览器内核消耗大量内存,所以需要封装一个内核池WebDriberPool来管理所有内核,统一创建和关闭。
2、下载器必须提供外部接口用于设置JS代码
3、下载网页时需要执行JS自动执行之前设置的JS代码
4、爬取模式为代理IP模式时,自动从IP管理获取IP
3、适应无效代理ip的管理优化。对于普通的网站,只要设置了请求头User-Agent,我们就可以轻松绕过网站服务器的anti-pick机制。但对于大型 网站 来说,事情没那么简单。他们会通过网站流量统计系统和日志分析来识别爬虫或限制每秒IP请求数。但是他们无法阻止代理IP的自动轮换。目前国内基本没有所谓的“高隐蔽代理IP”。一些代理IP提供商的失败率也非常高。几乎找不到永久有效的代理IP。如果没有,为什么还要找它。为什么不适应这种代理IP失败是常态的情况。
假设我们购买了某个代理IP,供应商改进了API提取方式。
1 需要代理IP的网络缓冲池
2需要代理本地缓存池来缓存有效IP
3 爬虫提取代理IP时,判断缓存是否足够使用,如果有则取缓存IP。
4 如果没有缓存,网络会提取一批代理IP加入网络缓冲池。
5、 爬取过程也是一个验证过程。有效的代理IP被缓存到缓存池中以供其他请求使用。
6、请求失败时,如果IP来自缓存,设备IP会被踢出缓存队列。
7、 可以设置代理IP失败超时时间。驻留在内存中超过时间的IP被踢出队列
实现框架图如下:
4、URL 上下文使开发业务逻辑更容易
在开发爬虫的时候,发现数据库设计的数据往往单页不完整。通常需要几个页面或者需要查询一些业务相关的ID。所以对于这些情况,一般都是去数据库查询更新后的数据,所以在写DAO层的时候方法就多了很多。业务逻辑的复杂度越来越高。案例如图:
上下文类架构:
1、为每个初始 URL 创建包 startRequest
2、提供支持线程并发安全的全局缓存key-value表
3、每个Request的实例化传递到上下文类
4、 爬虫爬取时可以把属性放到key-value表中
5、 子页面需要时,可以通过Requst获取上下文实例,获取对应的属性
6、爬虫任务完成。自动清除所有上下文缓存信息。
5、多线程控制
爬虫线程工作周期长。如果在程序的某个阶段出现异常,那么你认为之前程序所做的工作就会丢失。所有爬虫多线程应该分为两部分。一个是专门请求 URL 以下载 html 页面的线程。这部分线程需要很长时间并且独立工作。不需要多用synchronized,容易出现异常。另一部分是“离线处理”线程,对下载的数据进行提取、清理、封装和存储。这部分线程与业务密切相关,处理速度快,耗时长。有时需要协调工作,需要使用更多同步和线程安全的缓冲队列。
最后,还有一个线程,其生命周期与爬虫任务相同。它不断轮询 URL 队列以获取最新的 URL,并将该 URL 分配给下载线程。
6、任务计时问题
爬虫任务周期长短。或者业务需要爬虫反复抓取一些动态数据。这时候就需要一个定时机制。其实Java的Timer已经提供了计时功能。我们只需要给定时器启动爬虫的程序即可。爬虫任务完成后,定时器设置下一次启动时间。然后它会休眠并等待它再次启动。
结合多线程控制和任务时序管理,得到如下架构图: