目前爬取方案:获取html页面后用正则表达式匹配。在把匹配后的插入数据库中。我开了3个线程,分别从 0 , 1/3 ,2/3 出开始爬取。开多线程虽然有常数的优化,但是本身基数就很大,优化很不明显。
现在想学习解决的问题:
1,能否通过学习一些新的技术获得一个较大的优化?
2,在前期爬取的过程中速度明显比现在快,随着数据库里内容的增加,插入一条数据花费的时间边的更多了。(ps:数据库用的 sqlite3)(程序在新建数据库时运行速度会有较大提升,但数据库一旦到达 300 M 左右时耗时会明显增加)。数据库方面能有什么样的优化。
3,最近在学《计算机网络》,老师在课上讲到了分布式应用。想学着写个分布式的爬虫,就算是自己的练习。知友有哪些好的项目可以推荐一下学习?
回复内容:
针对题目,我有两个建议:1. 使用xpath或者css selector替代正则。
2. 使用gevent来提升爬取速度。
感谢 @松鼠奥利奥 提到我,发现当初回答这道题是用手机随手一答,并没有说清楚具体原因,抱歉。
为什么建议使用xpath代替正则?
对于固定场景,合适的正则表达式解析的效率是会高于xpath的,之所以提倡使用xpath,是因为程序可维护性,xpath的可读性远高于正则表达式,开发调试和维护效率会大大提高。
为什么建议使用gevent?
爬虫程序明显是IO密集型的程序,使用gevent可以使得阻塞的IO操作变成非阻塞,减少无谓的等待时间,从而提高效率。
所有性能问题都能通过堆硬件的方式来解决,我们现在讨论的是如何最大效率地利用硬件。
利用消息队列来进行调度是个很聪明的方案,但是如果我们发现消息队列中的消息是有堆积的,那么说明这个系统真正的瓶颈并不在于消息队列,而在于爬取端。
我们可以通过简单地启动多个爬取实例消费同一个消息队列的任务来提升爬取速度,但是要注意,在一个系统中启动过多的爬取实例,进程切换的开销反而会使得效率下降,实例个数一般推荐为cpu的核数。
我的观点是,爬取实例尽可能高效,而爬取频率应该是调度方来控制,同时多机同时爬取也是很好的。 那些给你安利什么gevent/xpath什么的人,一定没有写过爬千万级或者亿级以上数据量的爬虫。
按照你的需求,你有1500万条数据需要抓取,这1500万条数据分布在100万页网页中。那么,从以下几个方面给题主一点建议。
首先,存储的问题,爬虫的数据,尤其到了一个比较大的两极,sqlite3这种文件型的数据库最好不要用了,建议使用MongoDB做存储,简单实用,方便拓展爬虫的数据。
其次,如果可以,将这100万页页码分解成100万个任务,放到一个MessageQueue中。
接着,在写程序的时候,不要考虑任何多线程多进程gevent或者任何会让你的程序“提速”的东西,你的爬虫只要完成一个简单的功能:接受一个输入,这里就是某一页的页码,得到的输出是这一页的15条数据,最好直接存储到数据库中。
最后一步,将上两步具体实现,建议使用RabbitMQ或者ActiveMQ,然后在上一步的接受输入变成从Queue中取一条任务。如果源网站不会因为访问频率过高而封你的IP,那么你可以在一台机器上多部几个爬虫实例,否则的话,你可以将你的代码部署到多台机器上。阿里云按时间付费的机器很便宜,你可以开多点机器以加快速度。
这样的好处是,你可以随时新增或减少一个爬虫实例,而不会影响之前已经部署的任何爬虫,也可以随时将抓取失败的页码数再次放入Queue中,而不影响正在抓取任务的爬虫。
最后,如果你按照这样的思路完成,你只需要写爬虫和搭建MessageQueue,它们之间的交互已经有了现成的库xtls可以帮你:
pypi: https://pypi.python.org/pypi/xtls/
文档:xtls: awesome tools by xlzd
github:xlzd/xtls · GitHub
任务入MessageQueue:
from xtls.activemqwraps import producer
# mq_uri 是你的MQ的连接地址
# queue_name 是queue的名字
@producer(mq_uri, queue_name)
def insert_task():
# 你有一百万个页码的任务
# 如果你的任务是其它复杂的内容,也可以yield出去
# 会自动加入到MessageQueue中
for page in xrange(1, 1000001):
yield page
爬虫看看scrapy即可,都帮你想好了。性能问题不用想太多,主要是看你有多少台机器和你的带宽。数据库有很多方法。例如可以先写文件或key-value型数据库,再弄个脚本存入做数据分析用的数据库。 安利scrapy
这个框架比你自己撸快太多了
300mb卡了…
sqlite开一次关一次延迟挺大的
你有啥变量没清空?
还是你往sqlite里面存了奇怪的东西…
我瞎猜的
哦小心被ban 假期爬tripadvisor 爬到第八个小时被block… 当时想掀桌… 你说的轮子scrapy都帮你做好了
scrapy/scrapy · GitHub
存储搞个NoSQL吧 xlzd说的是对的。
爬虫首先要做成分布式。用queque来做。
程序的大部分时间都花在下载上,你用同步还是异步写完全没区别。
别用多线程爬,分分钟被封掉。必要的时候还要加时延。
每个子任务爬之前,url过一遍bloom filter,数据库查一遍,确保不做重复下载。
数据库用mongo,index做好,不然到几百万后会很慢。
还有就是不要迷信scrapy,很多时候自己写的更好用。 如果用十几台爬虫机抓数据,应该两三天就可以爬完了,一台机器的话,时间会长一点。几点建议:
1,线程开的多一些,比如50个线程或者一百个线程,具体可以top一下看看负载怎么样来决定线程数。
2,如果是分布式,一台master多台slave,master用来调度爬虫任务,消息队列可以用redis,每台slave机器使用多线程。
3,建立一个ip池,每个ip隔一段时间爬取,这样防止被封,ip池可以上网去找,然后做一下验证,看是否可用。
4,如果需要,学一下模拟登陆。
5,不建议用sqlite,甚至可以不用数据库,可以直接写到txt里面存下来,等到计算的时候也很方便处理。
6,xpath解析用lxml,不规则的网页用正则匹配。 Scrapy,mongdb,如果要用搞个分布式的话再加个redis
![VIP课程(WEB全栈开发)](http://m.sbmmt.com/img/upload/course/000/000/071/628e00599d7e4913.png)
相关文章推荐
• 【腾讯云】年中优惠,「专享618元」优惠券!• Python数据分析之concat与merge函数(实例详解)• 实例详解Python面向对象的四大特征• 图文详解怎么用Python绘制动态可视化图表• 简单学习Python字符和列表(实例详解)• 介绍六个超好用的Python内置函数独孤九贱(3)_JavaScript视频教程
javascript是运行在浏览器上的脚本语言,连续多年,被评为全球最受欢迎的编程语言。是前端开发必备三大法器中,最具杀伤力。如果前端开发是降龙十八掌,好么javascript就是第18掌:亢龙有悔。没有它,你的前端生涯是不完整的。《php.cn独孤九贱(3)-JavaScript视频教程》课程特色:php中文网原创幽默段子系列课程,以恶搞,段子为主题风格的php视频教程!轻松的教学风格,简短的教学模式,让同学们在不知不觉中,学会了javascript知识。
JavaScript教程125238次播放
独孤九贱(6)_jQuery视频教程
jQuery是一个快速、简洁的JavaScript框架。设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。 核心特性可以总结为:具有独特的链式语法和短小清晰的多功能接口;具有高效灵活的css选择器,并且可对CSS选择器进行扩展;拥有便捷的插件扩展机制和丰富的插件。兼容各种主流浏览器,如IE 6.0+、FF 1.5+、Safari 2.0+、Opera 9.0+等,是全球最流行的前端开发框架之一。PHP中文网根据最新版本,独家录制jQuery最新视频教程,回馈PHP中文网的新老用户。
jQuery教程103611次播放
jQuery与Ajax基础与实战
jQuery是最流行的JS函数库,封装了许多实用的功能,其中最引人入胜的就是Ajax。 jQuery中的Ajax操作,语法简单,操作方便,使Ajax从未如此轻松,前端人员从此不再为与服务器异步交互而发愁,本套课程,精选了最常用的几个方法,从基本的语法到每个参数,再到具体实例进行了全面的讲解。
AJAX教程4743次播放
Git教程(60分钟全程无废话版)
Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。 Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。 Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持
JavaScript教程4067次播放