有没有易懂的 Python 多线程爬虫代码?

2016-07-17 12:14:14 +08:00
 MyFaith

看了很多范例,但是还是没有理解,比如要爬取 10 页内容,每页有 30 条数据,那么开启 5 个线程的话,我自己尝试写过,不过这 5 个线程都单独爬取 300 条数据,如何才能做到一个线程爬取两页这样?

7570 次点击
所在节点    Python
26 条回复
hard2reg
2016-07-17 12:15:38 +08:00
一个线程爬取两页循环啊
lecher
2016-07-17 12:27:35 +08:00
需要一个任务队列,抓取线程从任务队列里面取任务抓取。

又或者把抓取功能封装成一个独立的任务,主线程通过直接调用的形式直接分配任务。
bigtan
2016-07-17 13:02:39 +08:00
wenyu1001
2016-07-17 14:10:05 +08:00
deadEgg
2016-07-17 15:17:32 +08:00
python 单解释器 无多线程,只有多进程和协程
deadEgg
2016-07-17 15:18:10 +08:00
推荐用 celery,比较适合你的需求
neoblackcap
2016-07-17 15:23:02 +08:00
@deadEgg 爬虫明显是 IO 密集型应用,用线程是合适的,推荐协程的,你知道协程就是一种特殊的线程么?怎么就没有线程呢?
beordle
2016-07-17 15:33:53 +08:00
@deadEgg =.= 这个....其实严格来说 python2 是没有协程的,只有多线程和多进程。你正好讲反了。
deadEgg
2016-07-17 15:45:07 +08:00
@neoblackcap


因为 Python 有 GIL,当 CPU 密集,多个线程的代码很有可能是线性执行的。不能任意的切换 context ,所以一般用协程或者进程代替,linux 进程开销是非常小的效率某种程度肯定比线程高

“无线程”,只是想说线程比较鸡肋


@beordle
py2 有 gevent,3 中有 asyncio 。 不知道你说的没有协程依据在哪?
InkStone
2016-07-17 15:49:06 +08:00
就是当你获得一个 url 的时候,不要直接爬取,而是把它加入一个任务队列。
然后每个线程从任务队列获取要下载的 url
deadEgg
2016-07-17 15:55:00 +08:00
@neoblackcap
还有就是 “程就是一种特殊的线程” , 我认为这不是不对的,因为协程和线程概念上可能等同,但是实现上是差异非常大的
协程应该来说是 用户空间的线程
MyFaith
2016-07-17 15:56:27 +08:00
@bigtan 这个在使用参数的时候要如何处理呢?
MyFaith
2016-07-17 15:56:48 +08:00
@InkStone 感谢,你这么说我大概理解了。
neoblackcap
2016-07-17 16:16:56 +08:00
@deadEgg 爬虫这种东西我真看不出有什么需要线性执行,而且线性执行的话,你用进程不上锁,不同步?
Linux 的进程是轻量化,但线程的创建成本更低。实在搞不懂你所说的进程成本更低在何处。
在 90%都是网络 IO 的情况下,搞不懂为什么不用线程?这里又不需要大量的计算,进行一次上下文切换会比动不动就上百毫秒的网络请求成本更高?
neoblackcap
2016-07-17 16:25:47 +08:00
@deadEgg 我承认协程更应该是用户态线程,但 Python 的实现真的是用户态线程么?目前各类实现中大多还是用 1:1 模型,你说的协程在这里比线程优秀多少我还是很怀疑的
jugelizi
2016-07-17 16:31:54 +08:00
多进程吧
可以四核一起跑
deadEgg
2016-07-17 16:38:47 +08:00
@neoblackcap 你讲的是悖论,非用户态线程就不存在 GIL 问题
neoblackcap
2016-07-17 16:47:31 +08:00
@deadEgg 你为什么这么执着 GIL ?你在网络请求的时候不等待吗?等待的时候上下文切换,有没有 GIL 又有什么问题?
em70
2016-07-17 16:56:38 +08:00
要做多线程,先把任务分成多个子任务啊,让每个线程负责一个,你不分配子任务,线程又不是智慧生物,它又不会自己协作
justou
2016-07-17 17:01:36 +08:00
windows 下 IO 密集型任务(不单只网络 IO)优先考虑线程, 用进程太浪费, 每个进程都是一个单独的解释器(1000 个线程跟 1000 个进程区别应该还是较大的, 内存方面)

用队列传输消息, 设计好程序结构, Process 跟 Thread 的切换也就改改几个 import, 具体问题 profile 看下, 谁的效率高(内存使用, 执行时间)就用谁

协程是在一个线程中切换的, 协程切换比线程切换更流畅, 花销也更小, 这是听来的, 没在实际中用过(错了请纠正我), 习惯了队列传输模式, 也方便线程改进程

Unix 下不清楚, 不乱说

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/292999

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX