多线程糗事百科案例

案例要求参考上一个糗事百科单进程案例:http://www.cnblogs.com/miqi1992/p/8081929.html

Queue(队列对象)

Queue是python中的标准库,可以直接import Queue引用;队列时线程间最常用的交互数据的形式。

python下多线程的思考

对于资源,加锁是个重要的环节。因为python原生的list,dict等,都是not thread safe的。而Queue,是线程安全的,因此在满足使用条件下,建议使用队列

  1. 初始化:class Queue.Queue(maxsize)FIFO先进先出

  2. 包中的常用方法:

    • Queue.qszie()返回队列的大小
    • Queue.empty()如果队列为空,返回True,否则返回False
    • Queue.full()如果队列满了,返回True,反之False
    • Queue.full 与 maxsize大小对应
    • Queue.get([block[, timeout]])获取队列,timeout等待事件
  3. 创建一个"队列"对象

    • import Queue
    • myqueue = Queue.Queue(maxsize=10)
  4. 将一个值放入队列中

    • myqueue.put(10)
  5. 将一个值从队列中取出

    • myqueue.get()

多线程示意图

#-*- coding:utf-8 -*-

import requests
from lxml import etree
from Queue import Queue
import threading
import time
import json class Thread_crawl(threading.Thread):
"""
抓取线程类
"""
def __init__(self, threadID, q):
threading.Thread.__init__(self)
self.threadID = threadID
self.q = q def run(self):
print("String: "+self.threadID)
self.qiushi_spider()
print("Exiting: "+self.threadID) def qiushi_spider(self):
while True:
if self.q.empty():
break
else:
page = self.q.get()
print('qiushi_spider=', self.threadID, 'page=', str(page))
url = 'http://www.qiushibaike.com/8hr/page/' + str(page)+"/"
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
'Accept-Language':'zh-CN,zh;q=0.8'
} #多次尝试失败结束,防止死循环
timeout = 4
while timeout > 0:
timeout -= 1
try:
content = requests.get(url, headers = headers)
data_queue.put(content.text)
break
except Exception, e:
print "qiushi_spider", e
if timeout < 0:
print 'timeout', url class Thread_Parser(threading.Thread):
"""
页面解析类
"""
def __init__(self, threadID, queue, lock, f):
threading.Thread.__init__(self)
self.threadID = threadID
self.queue = queue
self.lock = lock
self.f = f def run(self):
print("starting ", self.threadID)
global total, exitFlag_Parser
while not exitFlag_Parser:
try:
"""
调用队列对象的get()方法从队头删除并返回一个项目。可选参数为block, 默认为True
如果队列为空且block为True,get()就使调用线程暂停,直至有项目可用
如果队列为空且block为False,队列将引发Empty异常
"""
item = self.queue.get(False)
if not item:
pass
self.parse_data(item)
self.queue.task_done()
print("Thread_Parser=", self.threadID, 'total=', total)
except:
pass
print "Exiting ", self.threadID def parse_data(self, item):
"""
解析网页函数
:param item:网页内容
:return
"""
global total
try:
html = etree.HTML(item)
result = html.xpath('//div[contains(@id,"qiushi_tag")]')
for site in result:
try:
imgUrl = site.xpath('.//img/@src')[0]
title = site.xpath('.//h2')[0].text
content = site.xpath('.//div[@class="content"]/span')[0].text.strip()
vote = None
comments = None
try:
# 投票次数
vote = site.xpath('.//i')[0].text
# print(vote)
#print site.xpath('.//*[@class="number"]')[0].text
# 评论信息
comments = site.xpath('.//i')[1].text
except:
pass
result = {
'imageUrl' : imgUrl,
'title' : title,
'content' : content,
'vote' : vote,
'comments' : comments } with self.lock:
self.f.write(json.dumps(result, ensure_ascii=False).encode('utf-8') + '\n')
except Exception, e:
print("site in result ", e)
except Exception, e:
print("parse_data", e)
with self.lock:
total += 1 data_queue = Queue()
exitFlag_Parser = False
lock = threading.Lock()
total = 0 def main():
output = open('qiushibaike.json', 'a')
#初始化网页页码page从1-10个页面
pageQueue = Queue(10)
for page in range(1, 11):
pageQueue.put(page) #初始化采集线程
crawlthreads = []
crawllist = ["crawl-1", "crawl-2", "crawl-3"] for threadID in crawllist:
thread = Thread_crawl(threadID, pageQueue)
thread.start()
crawlthreads.append(thread) # #初始化解析线程parseList
parserthreads = []
parserList = ["parser-1", "parser-2", "parser-3"] #分别启动parserList
for threadID in parserList:
thread = Thread_Parser(threadID, data_queue, lock, output)
thread.start()
parserthreads.append(thread) # 等待队列情况
while not pageQueue.empty():
pass #等待所有线程完成
for t in crawlthreads:
t.join()
while not data_queue.empty():
pass #通知线程退出
global exitFlag_Parser
exitFlag_Parser = True for t in parserthreads:
t.join()
print 'Exiting Main Thread'
with lock:
output.close() if __name__ == '__main__':
main()

Python爬虫(十八)_多线程糗事百科案例的更多相关文章

  1. [Python]网络爬虫(八):糗事百科的网络爬虫(v0.2)源码及解析

    转自:http://blog.csdn.net/pleasecallmewhy/article/details/8932310 项目内容: 用Python写的糗事百科的网络爬虫. 使用方法: 新建一个 ...

  2. python 多线程糗事百科案例

    案例要求参考上一个糗事百科单进程案例 Queue(队列对象) Queue是python中的标准库,可以直接import Queue引用;队列是线程间最常用的交换数据的形式 python下多线程的思考 ...

  3. 芝麻HTTP:Python爬虫实战之爬取糗事百科段子

    首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把,这次我们尝试一下用爬虫把他们抓取下来. 友情提示 糗事百科在前一段时间进行了改版,导致之前的代码没法用了,会导致无法输出和CPU占用过高的 ...

  4. python 爬虫实战1 爬取糗事百科段子

    首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把,这次我们尝试一下用爬虫把他们抓取下来. 本篇目标 抓取糗事百科热门段子 过滤带有图片的段子 实现每按一次回车显示一个段子的发布时间,发布人 ...

  5. Python爬虫实战之爬取糗事百科段子

    首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把,这次我们尝试一下用爬虫把他们抓取下来. 友情提示 糗事百科在前一段时间进行了改版,导致之前的代码没法用了,会导致无法输出和CPU占用过高的 ...

  6. Python爬虫实战之爬取糗事百科段子【华为云技术分享】

    首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把,这次我们尝试一下用爬虫把他们抓取下来. 友情提示 糗事百科在前一段时间进行了改版,导致之前的代码没法用了,会导致无法输出和CPU占用过高的 ...

  7. [python]爬虫学习(三)糗事百科

    import requestsimport osfrom bs4 import BeautifulSoupimport timepage=2url='http://www.qiushibaike.co ...

  8. python爬虫——利用BeautifulSoup4爬取糗事百科的段子

    import requests from bs4 import BeautifulSoup as bs #获取单个页面的源代码网页 def gethtml(pagenum): url = 'http: ...

  9. Python爬虫(十七)_糗事百科案例

    糗事百科实例 爬取糗事百科段子,假设页面的URL是: http://www.qiushibaike.com/8hr/page/1 要求: 使用requests获取页面信息,用XPath/re做数据提取 ...

随机推荐

  1. C#对注册表的操作

    C#中提供的与注册表相关的最主要的是两个类: Registry 和 RegistryKey,这两个类属于Microsoft.Win32命名空间 Registry类包含5个公共的静态域,分别代表5个基本 ...

  2. 【python】内置函数总结(一)

    1.判断真假的函数:bool()2.Python中所谓的迭代协议就是next方法的对象会前进到下一个结果,在一系列结果的末尾会引发StopIteration异常.在Python中,任何类型的对象都被认 ...

  3. SICK激光雷达LMS511测量数据说明

    帧结构说明 LMS511的官方手册存在几个版本,在<Laser Measurement Systems of the LMS500 Product Family>的英文手册中,对单次(连续 ...

  4. mybatis逆向工程使用步骤详解

    使用mybatis生成逆向工程的详细步骤,我个人感觉这个是最简单的一个了,虽然网上有很多种的方法来生成逆向工程,可是这个方法最简单.在这里我是使用maven搭建的环境,但是在正常的环境下也是一样的.步 ...

  5. iOS 远程推送消息解析及逻辑处理

    关于远程推送的相关配置网上已经有足够多的教程,这里就不复述了.这里讲述当客户端收到推送消息后,应怎样对其进行相应的逻辑处理. 工程的AppDelegate.m文件里提供了如下方法: //当应用程序启动 ...

  6. Python 函数相关概念

    高阶函数  数学概念 y=g(f(x))  在数学和计算机科学中,高阶函数应当至少满足下面一个条件的函数   条件1. 接受一个或多个函数作为参数  条件2. 输出一个函数 举例: def count ...

  7. Java学习笔记12---向上转型-父类的对象引用指向子类对象

    当父类的对象引用没有指向父类的对象,而是指向了子类的对象时,调用方法或访问变量时会怎样呢? 假设父类为Person,子类为Student,有下面的两行定义: Student sTest = new S ...

  8. HTML5到底将给企业带来什么?

    HTML5 是近年来互联网行业的热门词汇,火的很.有人高调宣称"APP 将在几年内灭亡,HTML5 取而代之" 改变企业网络广告的模式与分布 广告是企业网络营销的主要方式之一 十几 ...

  9. 异常:Unknown lifecycle phase "mvn". You must specify a valid lifecycle

    这是在使用maven打包方式启动springboot项目时出现的异常, 我的异常原因属于下面的情况: 此时maven指令行为:mvn spring-boot:run. 如果写成这样会导致最终的mave ...

  10. javaScript(JS)强制保留两位小数的输入数校验和小数保留

    参考来源于网络,如有侵权,请联系作者删除: 输入input 的格式校验: $(function(){ var data = $.trim($("#inputId").val()); ...