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)