您的位置:首页 > 其它

(嗅事百科)多线程爬虫

2019-07-11 19:32 92 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/weixin_44220464/article/details/95509139
首先来说,pyton的多线程是假的多线程。
由于Python代码的执行由Python虚拟机(解释器)来控制,同时只有一个线程在执行。
如何使用真的多线程呢?提供了一下方法:
1、重写python编译器
2、调用C语言的链接库
在这里我们用了第一种方法,重写了线程的run方法
这篇爬取的嗅事百科,解析的数据是标题,分类和评论数。取到数据后存入mongodb
思路:
两个类:一个负责采集数据,一个负责解析数据,main函数里创建的同样两个队列,供解析和采集使用。
遇到的问题:
1. 用xpath解析的数据有可能是空值,需要做些处理(这里我们用了try,except)(注意break要在for或while True中使用)
2. 写入数据时加锁得到的结果好一些
3. super().__init__()  # 继承父类实例属性的同时  拓展父类属性
import requests
import threading
from queue import Queue
from threading import Lock
from lxml import etree
import pymongo

class PageThread(threading.Thread):
def __init__(self,threadName,pageQueue,parseQueue):
super().__init__()
self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.16 Safari/537.36',}
self.threadName = threadName
self.pageQueue = pageQueue
self.parseQueue = parseQueue
def run(self):
url = "https://www.qiushibaike.com/text/page/%s/"
while True:
try:
# 如果队列为空  block 为 True 那么进入阻塞状态
# 如果队列为空  block 为 False 那么会抛出异常
page = self.pageQueue.get(block=False)
print("%s开始工作..."%self.threadName)
response = requests.get(url=url%page,headers=self.headers)
content = response.text
# print(response.status_code)
self.parseQueue.put(content)
print("%s工作结束..."%self.threadName)
except:
break

class ParseThread(threading.Thread):
def __init__(self,threadName,parseQueue,lock):
super().__init__()
self.threadName = threadName
self.parseQueue = parseQueue
self.lock=lock
def run(self):
while True:
try:
html = html = self.parseQueue.get(block=False)
print("%s开始处理数据.........."%self.threadName)
self.parse(html)
print("%s数据处理完毕.........."%self.threadName)
except:
break
def parse(self,html):
html = etree.HTML(html)
div_list = html.xpath('//div[@id="content-left"]/div')
# xpath解析
for div in div_list:
try:
name = div.xpath('.//div[@class="author clearfix"]/a/h2/text()')[0]
joke = div.xpath('.//span[@class="stats-vote"]/i/text()')[0]
con = div.xpath('.//span[@class="stats-comments"]//i/text()')[0]
item = {"作者": name, "搞笑": joke, "评论": con}
with self.lock:
self.save(item)
except:
pass
def save(self,item):
# 连接mongodb并写入数据
conn = pymongo.MongoClient("localhost",27017)
db = conn.teacher
table = db.qiubai
table.insert(item)
def main():
pageQueue = Queue()
parseQueue = Queue()
lock = Lock()
for i in range(1,14):
pageQueue.put(i)
pagelist = []
for var in ['采集线程1','采集线程2','采集线程3',]:
c = PageThread(var,pageQueue,parseQueue)
c.start()
pagelist.append(c)
for var in pagelist:
var.join()
parselist = []
for var in ['解析线程1','解析线程2','解析线程3',]:
c = ParseThread(var,parseQueue,lock)
c.start()
parselist.append(c)
for var in parselist:
var.join()

if __name__ == "__main__":
main()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: