#author:huangtao
# coding=utf-8
#多线程库
from threading import Thread
#队列库
from queue import Queue
#请求库
from fake_useragent import UserAgent
#访问库
import requests
#etree库,lxml解析
from lxml import etree
#爬虫类
class CrawlInfo(Thread):
# 定义init传递参数url_queue,html_queue
def __init__(self,url_queue,html_queue):
#通过主程序中存放容器调取参数
Thread.__init__(self)
self.url_queue = url_queue
self.html_queue = html_queue
#定义线程启动
def run(self):
#随机请求头
headers= {'User-Agent':UserAgent().random}
#判断url队列中是否为空,不为空继续访问
while self.url_queue.empty() == False:
#访问网页
res =requests.get(self.url_queue.get(),headers=headers)
#判断访问返回的状态码是否为200
if res.status_code ==200:
#判断为200的话,把返回的网页text放到html_queue队列中
self.html_queue.put(res.text)
#解析类
class ParseInfo(Thread):
# 定义init传递参数html_queue
def __init__(self,html_queue):
# 通过主程序中存放容器调取参数
Thread.__init__(self)
self.html_queue = html_queue
# 定义线程启动
def run(self):
# 判断html队列中是否为空,不为空继续访问
while self.html_queue.empty() == False:
#把html的返回的信息解析定义为e
e = etree.HTML(self.html_queue.get())
#使用lxml解析content
content = e.xpath('//div[@class="content"]/span[1]')
#但是content结构有问题,循环一下content
for span in content:
#转化字符串
info = span.xpath('string(.)')
#打印内容
print(info)
if __name__ == '__main__':
#存储url的容器
url_queue = Queue()
#存储内容
html_queue = Queue()
#起始的url,通过下面的循环遍历构造new_url
base_url = 'https://www.qiushibaike.com/text/page/{}/'
for i in range(1,14):
new_url = base_url.format(i)
#url_queue队列中放入构造的新的new_url
url_queue.put(new_url)
#创建爬虫
#定义一个craw1_list列表
craw1_list = []
#创建3个爬取网页的线程
for i in range(0,3):
#3个线程
craw1 = CrawlInfo(url_queue,html_queue)
craw1_list.append(craw1)
#线程开始
craw1.start()
#craw1_list列表,不加的话,爬取网页的线程只能走一遍就关闭了,所以要加个Join等待线程
for craw1 in craw1_list:
craw1.join()
#定义一个parse_list的列表
parse_list = []
#创建解析的线程
for i in range(0, 3):
parse = ParseInfo(html_queue)
parse_list.append(parse)
parse.start()
# parse_list列表,不加的话,解析的线程只能走一遍就关闭了,所以要加个Join等待线程
for parse in parse_list:
parse.join()