用Python Requests抓取知乎用户信息(二)

来源:互联网 发布:windows 后缀名 编辑:程序博客网 时间:2024/05/04 06:02

转自:http://zihaolucky.github.io/mutilthread-crawler/

你可以先读一下用Python Requests抓取知乎用户信息了解文章的背景和细节;这篇文章主要关注对爬虫性能的改造。

这部分的知识是从麦兜兜的博客中搬过来的,例子非常棒!

为什么要提出多线程呢?我们首先看一个单线程的例子。

  1. from time import sleep,ctime
  2. def loop0():
  3. print 'start loop 0 at:',ctime()
  4. sleep(4)
  5. print 'loop 0 done at:',ctime()
  6. def loop1():
  7. print 'start loop 1 at:',ctime()
  8. sleep(2)
  9. print 'loop 1 done at:',ctime()
  10. def main():
  11. print 'starting at:',ctime()
  12. loop0()
  13. loop1()
  14. print 'all DONE at:',ctime()
  15. if __name__=='__main__':
  16. main()

运行结果:

  1. >>>
  2. starting at: Mon Aug 31 10:27:23 2009
  3. start loop 0 at: Mon Aug 31 10:27:23 2009
  4. loop 0 done at: Mon Aug 31 10:27:27 2009
  5. start loop 1 at: Mon Aug 31 10:27:27 2009
  6. loop 1 done at: Mon Aug 31 10:27:29 2009
  7. all DONE at: Mon Aug 31 10:27:29 2009
  8. >>>

可以看到单线程中的两个循环,只有一个循环结束后另一个才开始。总共用了6秒多的时间。假设两个loop中执行的不是sleep,而是一个别的运算的话,如果我们能让这些运算并行执行的话,是不是可以减少总的运行时间呢,这就是我们提出多线程的前提。

根据文章,我们使用threading包进行多线程改造。改造的思路很简单,针对post数据中参数offset的奇偶性分成两个线程thread1thread2即可。

  1. import threading
  2. from time import ctime
  3. def main():
  4. # login
  5. s.post('http://www.zhihu.com/login', login_data)
  6. for user in user_list:
  7. print 'crawling ' + user + '\'s followers...\n'
  8. # 写文件
  9. global fp
  10. fp = codecs.open(user + '.txt', 'w', 'utf-8')
  11. url = 'http://www.zhihu.com/people/' + user + '/followers'
  12. # 转跳到用户followers页
  13. r = s.get(url)
  14. data = r.text
  15. # 多线程
  16. print 'starting at:',ctime()
  17. threads = []
  18. t = threading.Thread(target=load_more_thread1,args=(user,data))
  19. threads.append(t)
  20. t = threading.Thread(target=load_more_thread2,args=(user,data))
  21. threads.append(t)
  22. for i in range(2):
  23. threads[i].start()
  24. for i in range(2):
  25. threads[i].join()
  26. print 'all DONE at:',ctime()

改造的关键都在多线程这里。我们首先创建了threading对象t,并添加(append)到threads中。使用threading对象的一个原因是,我在是用thread的时候输入参数时可能是因为不规范而总是出错,不过这里threading便可以很好地支持。

随后的start和join语句便会让进行开始直到全部进程结束。因此在一个for循环中我们便同时运行了thread1thread2两个抓取程序。性能自然是提升了~

下面我们通过程序运行时间来感受一下改进前后的情况: 多(双)线程mutil-thread-crawler

单线程single-thread-crawler

做事情就是这样,遇到效果不满意、或是需要改进的时候,如果对项目本身,或是技术原理有认识,那么操作起来就会事半功倍;这也是我为什么想读博的原因吧!


0 0
原创粉丝点击