python3爬虫多线程_python3 多线程爬虫模板

1 import threading #多线程模块

2 import queue #队列模块

3 importrequests4 from lxml importetree5 importtime6 importrandom7 importjson8

9 concurrent = 3 #采集线程数

10 conparse = 3 #解析线程

11

12

13 class Parse(threading.Thread): #解析线程类

14 #初始化属性

15 def __init__(self, number, data_list, req_thread, f):16 super(Parse, self).__init__()17 self.number = number #线程编号

18 self.data_list = data_list #数据队列

19 self.req_thread = req_thread #请求队列,为了判断采集线程存活状态

20 self.f = f #获取文件对象

21 self.is_parse = True #判断是否从数据队列里提取数据

22

23

24 defrun(self):25 print('启动%d号解析线程' %self.number)26 #无限循环,

27 whileTrue:28 #如何判断解析线程的结束条件

29 for t in self.req_thread: #循环所有采集线程

30 if t.is_alive(): #判断线程是否存活

31 break

32 else: #如果循环完毕,没有执行break语句,则进入else

33 if self.data_list.qsize() == 0: #判断数据队列是否为空

34 self.is_parse = False #设置解析为False

35 #判断是否继续解析

36 if self.is_parse: #解析

37 try:38 data = self.data_list.get(timeout=3) #从数据队列里提取一个数据

39 except Exception as e: #超时以后进入异常

40 data =None41 #如果成功拿到数据,则调用解析方法

42 if data is notNone:43 self.parse(data) #调用解析方法

44 else:45 break #结束while 无限循环

46 print('退出%d号解析线程' %self.number)47

48

49 #页面解析函数

50 defparse(self, data):51 html =etree.HTML(data)52 #获取所有段子div

53 duanzi_div = html.xpath('//div[@id="content-left"]/div')54 for duanzi induanzi_div:55 #获取昵称

56 nick = duanzi.xpath('./div//h2/text()')[0]57 nick = nick.replace('\n', '')58 #获取年龄

59 age = duanzi.xpath('.//div[@class="author clearfix"]/div/text()')60 if len(age) >0:61 age =age[0]62 else:63 age =064 #获取性别

65 gender = duanzi.xpath('.//div[@class="author clearfix"]/div/@class')66 if len(gender) >0:67 if 'women' ingender[0]:68 gender = '女'

69 else:70 gender = '男'

71 else:72 gender = '中'

73 #获取段子内容

74 content = duanzi.xpath('.//div[@class="content"]/span[1]/text()')[0].strip()75 #获取好笑数

76 good_num = duanzi.xpath('./div//span[@class="stats-vote"]/i/text()')[0]77 #获取评论

78 common_num = duanzi.xpath('./div//span[@class="stats-comments"]//i/text()')[0]79 item ={80 'nick': nick,81 'age': age,82 'gender': gender,83 'content': content,84 'good_num': good_num,85 'common_num': common_num,86 }87 self.f.write(json.dumps(item, ensure_ascii=False) + '\n')88

89

90 class Crawl(threading.Thread): #采集线程类

91 #初始化

92 def __init__(self, number, req_list, data_list):93 #调用Thread 父类方法

94 super(Crawl, self).__init__()95 #初始化子类属性

96 self.number =number97 self.req_list =req_list98 self.data_list =data_list99 self.headers ={100 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36'

101 }102 #线程启动的时候调用

103

104 defrun(self):105 #输出启动线程信息

106 print('启动采集线程%d号' %self.number)107 #如果请求队列不为空,则无限循环,从请求队列里拿请求url

108 while self.req_list.qsize() >0:109 #从请求队列里提取url

110 url =self.req_list.get()111 print('%d号线程采集:%s' %(self.number, url))112 #防止请求频率过快,随机设置阻塞时间

113 time.sleep(random.randint(1, 3))114 #发起http请求,获取响应内容,追加到数据队列里,等待解析

115 response = requests.get(url, headers=self.headers)116 if response.status_code == 200:117 self.data_list.put(response.text) #向数据队列里追加

118

119

120 defmain():121 #生成请求队列

122 req_list =queue.Queue()123 #生成数据队列 ,请求以后,响应内容放到数据队列里

124 data_list =queue.Queue()125 #创建文件对象

126 f = open('duanzi.json', 'w', encoding='utf-8')127 #循环生成多个请求url

128 for i in range(1, 13 + 1):129 base_url = 'https://www.qiushibaike.com/8hr/page/%d/' %i130 #加入请求队列

131 req_list.put(base_url)132 #生成N个采集线程

133 req_thread =[]134 for i inrange(concurrent):135 t = Crawl(i + 1, req_list, data_list) #创造线程

136 t.start()137 req_thread.append(t)138 #生成N个解析线程

139 parse_thread =[]140 for i inrange(conparse):141 t = Parse(i + 1, data_list, req_thread, f) #创造解析线程

142 t.start()143 parse_thread.append(t)144 for t inreq_thread:145 t.join()146 for t inparse_thread:147 t.join()148 #关闭文件对象

149 f.close()150

151 if __name__ == '__main__':152 main()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值