Python爬虫实例-多线程爬虫糗事百科搞笑内涵段子
2021-03-31 18:27
标签:join global src false lxml exce info exiting 队列 学习爬虫,其乐无穷! 参考代码: 演示效果: Queue(队列对象): 多线程示意图: 如需要python爬虫全套完整的入门到项目实战视频教程,请点:爬虫视频教程。 参考代码: 1、爬取笔趣?某部?说的所有页面。 Python爬虫实例-多线程爬虫糗事百科搞笑内涵段子 标签:join global src false lxml exce info exiting 队列 原文地址:https://www.cnblogs.com/shsxt/p/13560682.html
今天给大家带来一个爬虫案例,爬取糗事百科搞笑内涵段子。
爬取糗事百科段?,假设??的 URL 是:http://www.qiushibaike.com/8hr/page/1一、爬取要求:
二、先来看看单线程案例
#qiushibaike.py
#import urllib
#import re
#import chardet
import requests
from lxml import etree
page = 1
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‘}
try:
response = requests.get(url, headers=headers)
167
resHtml = response.text
html = etree.HTML(resHtml)
result = html.xpath(‘//div[contains(@id,"qiushi_tag")]‘)
for site in result:
item = {}
imgUrl = site.xpath(‘./div/a/img/@src‘)[0].encode(‘utf-8‘)
username = site.xpath(‘./div/a/@title‘)[0].encode(‘utf-8‘)
#username = site.xpath(‘.//h2‘)[0].text
content = site.xpath(‘.//div[@class="content"]/span‘)[0].te
xt.strip().encode(‘utf-8‘) # 投票次数
vote = site.xpath(‘.//i‘)[0].text
#print site.xpath(‘.//*[@class="number"]‘)[0].text
# 评论信息
comments = site.xpath(‘.//i‘)[1].text
print imgUrl, username, content, vote, comments
except Exception, e:
print e
三、多线程案例
Queue 是 python 中的标准库,可以直接 import Queue 引?;队列是线程间最常?的交换数据的形式python 下多线程的思考 对于资源,加锁是个重要的环节。因为 python 原?的list,dict 等,都是 not thread safe 的。?Queue,是线程安全的,因此在满?使?条件下,建议使?队列。
Queue.qsize() 返回队列的??
Queue.empty() 如果队列为空,返回 True,反之 False
Queue.full() 如果队列满了,返回 True,反之 False
Queue.full 与 maxsize ??对应
Queue.get([block[, timeout]])获取队列,timeout 等待时间
# -*- 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 "Starting " + self.threadID
self.qiushi_spider()
print "Exiting ", self.threadID
def qiushi_spider(self): # page = 1
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/hot/page/‘ + str(
page) + ‘/‘
headers = {
‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; WO
W64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Sa
fari/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()就使调?线程暂停,直?
有项?可?。
otal
如果队列为空且 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=‘, t
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
comments = site.xpath(‘.//i‘)[1].text
except:
pass
result = {
‘imgUrl‘: imgUrl,
‘title‘: title,
‘content‘: content,
‘vote‘: vote,
‘comments‘: comments,
}
with self.lock:
# print ‘write %s‘ % json.dumps(result)
self.f.write(json.dumps(result, ensure_asci
i=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(50)
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)
#初始化解析线程 parserList
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()
四、课后作业
2、国家?品药品监督管理总局:http://app1.sfda.gov.cn 采集分类 国产药品商品名(6994) 下的所有的商品信息。
这个大家可以试着做一做,如需爬虫视频详解,请点爬虫视频。