python使用threading.Thread和Queue通过urllib2.urlopen抓取数据

有个抓取数据的需求 大概2000多个url 

需要用到线程和队列线程和队列代码如下

线程主体函数

class ThreadWeather(threading.Thread):
    def __init__(self, queue):
        threading.Thread.__init__(self)
        self.queue = queue
    
    def run(self):
        while True:
            wcode = self.queue.get()# 获取队列
            try:
                content = urllib2.urlopen("url信息略%s" % wcode,timeout=10).read()
            except urllib2.URLError,urllib2.HTTPError:# 抓取相应异常
                self.queue.task_done()
                continue
            except socket.error:# 主要难点
                time.sleep(2)# 如果超时 重新加入队列处理
                self.queue.put(wcode) # 重新加入队列
                self.queue.task_done()
                continue
            # 后续对数据处理 略
            self.queue.task_done()

执行代码

queue = Queue.Queue() # 生成队列
    # 生成10个线程
    for i in range(10):
        t = ThreadWeather(queue)
        t.setDaemon(True) # 加入守护线程
        t.start() # 启动线程 启动后因为队列get会被阻塞等待数据
    
    for wcode in wcode_list:# 加入
        queue.put(weathercode)# 加入任务到队列
    queue.join()# 阻塞 等待队列清空

队列讲解 主要用于线程间通信

queue.put("1" ) 讲数据1放入队列

queue.get() 从队列的一端获取并删除数据 如果获取不到会阻塞等待

queue.task_done() 向已经处理完的队列 发送一个信号

queue.join() 阻塞 等待队列清空

线程部分略 继承以后就那么写 没什么可讲 当然还有其他的线程写法

urllib2.urlopen

难点在这 如果仅仅是线程和队列 不会影响到代码执行 而且也很好测试

但是如果仅仅用urllib2.urlopen("url") 代码有可能执行不完 会一直阻塞

urllib2在抓取资源的时候会受到多种原因影响 例如url错误等所以处理了URLError和HTTPError

但是脚本执行后仍然会被阻塞 后来发现是timeout的原因 属于线程阻塞

处理socket超时 讲未处理的数据 重新加入队列 暂停两秒(因为超时)

最后脚本执行后成功退出 数据仍然少了几个 可能是被URLError处理略过了



          
Python中,使用`threading.Thread`是为了创建可以并发执行的线程,而不是进程。一个进程通常包含多个线程,而Python的全局解释器锁(GIL)会限制同一时刻只有一个线程执行Python字节码。因此,如果你要控制多个线程在特定时间内完成任务,你需要确保你的任务是可以并发执行的,并且没有过多的锁竞争。 要在400ms内控制100个线程完成运行,首先需要明确任务的性质。如果任务主要是计算密集型的,那么你可能无法通过简单增加线程数量来加快执行速度,因为GIL的存在。但如果任务是I/O密集型的,你可以通过增加线程数量来提高并发度,从而在400ms内完成。 这里有一个简单的例子,展示如何启动100个线程,并不保证它们在400ms内完成,但会启动它们: ```python import threading import time def task(): # 这里放置你的任务代码 pass # 创建并启动线程 threads = [] for i in range(100): t = threading.Thread(target=task) threads.append(t) t.start() # 等待所有线程完成 for t in threads: t.join() print("所有线程已执行完毕") ``` 如果你需要确保这些线程在400ms内完成,你可能需要考虑以下几点: 1. **任务类型**:确保任务是I/O密集型的或者可以利用多进程模块(multiprocessing)来绕过GIL。 2. **线程池**:使用`concurrent.futures.ThreadPoolExecutor`可以管理线程池,并且可以设置超时时间,但要注意,超时时间不能保证所有线程都能在400ms内完成。 3. **硬件限制**:实际上,执行速度还受限于你的CPU核心数量和I/O响应速度。 请记住,根据任务的特性和你的硬件限制,可能无法确保所有线程都完全在400ms内完成。而且,如果线程需要等待某些同步操作,它们可能不会同时结束。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值