投稿    登录
  您好,欢迎光临崔庆才的博客,祝大家新年快乐,鸡年大吉!

小白爬虫第四弹之爬虫快跑(多进程+多线程)

Python 哎哟卧槽 6102浏览 19评论

PS:使用多线程时好像在目录切换的问题上存在问题,可以给线程加个锁试试

Hello 大家好!我又来了。

QQ图片20161102215153

你是不是发现下载图片速度特别慢、难以忍受啊!对于这种问题 一般解决办法就是多进程了!一个进程速度慢!我就用十个进程,相当于十个人一起干。速度就会快很多啦!(为什么不说多线程?懂点Python的小伙伴都知道、GIL的存在 导致Python的多线程有点坑啊!)今天就教大家来做一个多进程的爬虫(其实吧、可以用来做一个超简化版的分布式爬虫)

其实吧!还有一种加速的方法叫做“异步”!不过这玩意儿我没怎么整明白就不出来误人子弟了!(因为爬虫大部分时间都是在等待response中!‘异步’则能让程序在等待response的时间去做的其他事情。)

QQ图片20161022193315

学过Python基础的同学都知道、在多进程中,进程之间是不能相互通信的,这就有一个很坑爹的问题的出现了!多个进程怎么知道那那些需要爬取、哪些已经被爬取了!

这就涉及到一个东西!这玩意儿叫做队列!!队列!!队列!!其实吧正常来说应该给大家用队列来完成这个教程的, 比如 Tornado 的queue模块。(如果需要更为稳定健壮的队列,则请考虑使用Celery这一类的专用消息传递工具)

不过为了简化技术种类啊!(才不会告诉你们是我懒,嫌麻烦呢!)这次我们继续使用MongoDB。

好了!先来理一下思路:

每个进程需要知道那些URL爬取过了、哪些URL需要爬取!我们来给每个URL设置两种状态:

outstanding:等待爬取的URL

complete:爬取完成的URL

诶!等等我们好像忘了啥? 失败的URL的怎么办啊?我们在增加一种状态:

processing:正在进行的URL。

嗯!当一个所有初始的URL状态都为outstanding;当开始爬取的时候状态改为:processing;爬取完成状态改为:complete;失败的URL重置状态为:outstanding。为了能够处理URL进程被终止的情况、我们设置一个计时参数,当超过这个值时;我们则将状态重置为outstanding。

下面开整Go Go Go!

首先我们需要一个模块:datetime(这个模块比内置time模块要好使一点)不会装??不是吧!  pip install datetime

还有上一篇博文我们已经使用过的pymongo

下面是队列的代码:

好了,队列我们做好了,下面是获取所有页面的代码:

下面就是多进程+多线程的下载代码了:

好啦!一个多进程多线的爬虫就完成了,(其实你可以设置一下MongoDB,然后调整一下连接配置,在多台机器上跑哦!!嗯,就是超级简化版的分布式爬虫了,虽然很是简陋。)

本来还想下载图片那一块儿加上异步(毕竟下载图片是I\O等待最久的时间了,),可惜异步我也没怎么整明白,就不拿出来贻笑大方了。

另外,各位小哥儿可以参考上面代码,单独处理图片地址试试(就是多个进程直接下载图片)?

 

我测试了一下八分钟下载100套图

PS:请务必使用 第二篇博文中的下载模块,或者自己写一个自动更换代理的下载模块!!!不然寸步难行,分分钟被服务器BAN掉!

QQ图片20161102215153小白教程就到此结束了,后面我教大家玩玩Scrapy;目标 顶点小说网, 爬完全站的小说。

再后面带大家玩玩 抓新浪  汤不热、模拟登录 之类的。或许维护一个公共代理IP池之类的。

这个所有代码我放在这个位置了:https://github.com/thsheep/mzitu/

转载请注明:静觅 » 小白爬虫第四弹之爬虫快跑(多进程+多线程)

喜欢 (52)or分享 (0)

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请狠狠点击下面的

      • 先给卧槽哥敬茶,昨天看了一天的进程和线程问题,然后今天晚上试了下local = threading.local()来让线程的属性局部,把path放到local.path的属性里面就可以了,暂时运行稳定6分钟700+MB文件150+,谢谢卧槽哥。

  1. 66行: while len(threads) < max_threads or crawl_queue.peek(): ##线程池中的线程少于max_threads 或者 crawl_qeue意思是说: 在线程数小于10 或者 URL 队列中还有OUTSTANDING 状态的记录时都会增加线程数, 若线程数为10且URL队列中还有OUTSTANDING 状态的记录时, 线程数会继续增加, 直到URL队列中不存在OUTSTANDING 状态的记录目测此处的 or 应为 and

  2. 不知道博主看不看评论,小站长一枚,试着用scrapy抓取内容,目前卡在scrapy抓取文章分页那里,很多新闻网站一篇新闻要分个几页,抓下来是分开的,不知道怎么在抓的过程中把分页内容连接起来成一篇完整内容?