多线程爬取糗事百科热门段子 (改写前天的博客)

利用多线程爬取,除了先前用到的几个模块之外,还需用到threading模块和queue模块:

  • 为每一件事情开启一个线程:构造url_list、发送请求、提取数据、保存数据
  • __init__方法添加三个实例属性队列分别存放:url、响应内容、处理后的数据
  • 改写原先每一个方法里的代码,需要的东西直接从队列中取出,此时方法都无需多余参数了
  • 每当从一个队列取出数据,记得执行task_done()方法,使计数减一
  • run()方法里把yaozhixing的事情都开启一个线程,比较慢的事情,比如网络请求,可以给其多开几个线程

这两步挺重要:

  • 把子线程设置为守护线程,该线程不重要;主线程结束,子线程结束
  • 让主线程等待阻塞,等待队列的任务完成之后再完成

如果不做这两个步骤,会导致:

  • 不把子线程设置为守护线程,会导致程序一直不能结束
  • 主线程如果不阻塞,会导致其它的事情还没做完,程序却已经结束了

经过上面的解释,就直接上代码了:

 1 import requests
 2 import json
 3 import threading
 4 from queue import Queue
 5 from lxml import etree
 6
 7
 8 class QiubaSpider(object):
 9     """爬取糗事百科的热门下的数据"""
10
11     def __init__(self):
12         self.url_temp = ‘https://www.qiushibaike.com/text/page/{}/‘
13         self.headers = {
14             ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36‘,
15         }
16         self.url_queue = Queue()  # 存放url的队列
17         self.html_queue = Queue()  # 存放响应的队列
18         self.content_queue = Queue()  # 存放content_list的对列
19
20     def get_url_list(self):  # 构造url_list
21         # return [self.url_temp.format(i) for i in range(1, 14)]
22         for i in range(1, 14):
23             self.url_queue.put(self.url_temp.format(i))  # 每一个构造出的url放入队列
24
25     def pass_url(self):  # 发送请求
26         while True:
27             url = self.url_queue.get()  # 从队列里面取出一个url
28             print(url)
29             response = requests.get(url, headers=self.headers)
30             # return response.content.decode()
31             self.html_queue.put(response.content.decode())  # 将返回的结果放入队列
32             self.url_queue.task_done()  # 使计数减一
33             print(1)
34
35     def get_content_list(self):  # 提取数据
36         while True:
37             html_str = self.html_queue.get()  # 从队列中取出
38             html = etree.HTML(html_str)
39             div_list = html.xpath(‘//div[@id="content-left"]/div‘)  # 分组
40             content_list = []
41             for div in div_list:
42                 item = {}
43                 # 底下全是利用xpath和一些函数对数据的处理
44                 item[‘content‘] = div.xpath(‘.//div[@class="content"]/span/text()‘)
45                 item[‘content‘] = [i.replace(‘\n‘, ‘‘) for i in item[‘content‘]]
46                 item[‘author_gender‘] = div.xpath(‘.//div[contains(@class, "articleGend")]/@class‘)
47                 item[‘author_gender‘] = item[‘author_gender‘][0].split(‘ ‘)[-1].replace(‘Icon‘, ‘‘) if len(
48                     item[‘author_gender‘]) > 0 else None
49                 item[‘author_age‘] = div.xpath(‘.//div[contains(@class, "articleGend")]/text()‘)
50                 item[‘author_age‘] = item[‘author_age‘][0] if len(item[‘author_age‘]) > 0 else None
51                 item[‘author_img‘] = div.xpath(‘.//div[@class="author clearfix"]//img/@src‘)
52                 item[‘author_img‘] = ‘https‘ + item[‘author_img‘][0] if len(item[‘author_img‘]) > 0 else None
53                 item[‘stats_vote‘] = div.xpath(‘.//span[@class="stats-vote"]/i/text()‘)
54                 item[‘stats_vote‘] = item[‘stats_vote‘][0] if len(item[‘stats_vote‘]) > 0 else None
55                 content_list.append(item)
56             # return content_list
57             self.content_queue.put(content_list)
58             self.html_queue.task_done()  # 计数减一
59             print(2)
60
61     def save_content_list(self):  # 保存
62         while True:
63             content_list = self.content_queue.get()  # 获取
64             with open(‘qiuba.txt‘, ‘a‘, encoding=‘utf-8‘) as f:
65                 f.write(json.dumps(content_list, ensure_ascii=False, indent=4))
66                 f.write(‘\n‘)  # 换行
67             self.content_queue.task_done()  # 计数减一
68             print(3)
69
70
71     def run(self):  # 实现主要逻辑
72         """ 每一件事开启一个线程,现在都是从队列里面获取,不用传参"""
73         thread_list = []  # 用来存取线程,因为四个线程一个个启动太麻烦
74         # 1.构造url_list,热门的一共13页
75         t_url = threading.Thread(target=self.get_url_list)
76         thread_list.append(t_url)
77         # 2.遍历发送请求,获取响应
78         for i in range(5):  # 为发送请求这里开启5个线程,直接循环即可
79             t_pass = threading.Thread(target=self.pass_url)
80             thread_list.append(t_pass)
81         # 3.提取数据
82         for i in range(3):  # 为提取数据这里开启3个线程
83             t_html = threading.Thread(target=self.get_content_list)
84             thread_list.append(t_html)
85         # 4.保存数据
86         t_save = threading.Thread(target=self.save_content_list)
87         thread_list.append(t_save)
88         for t in thread_list:
89             t.setDaemon(True)  # 把子线程设置为守护线程,该线程不重要;主线程结束,子线程结束
90             t.start()
91         for q in [self.url_queue, self.html_queue, self.content_queue]:
92             q.join()  # 让主线程等待阻塞,等待队列的任务完成之后再完成
93         print(‘主线程结束!‘)
94
95
96 if __name__ == ‘__main__‘:
97     qiubai = QiubaSpider()
98     qiubai.run()

原文地址:https://www.cnblogs.com/springionic/p/11122261.html

时间: 2024-11-05 16:29:32

多线程爬取糗事百科热门段子 (改写前天的博客)的相关文章

使用Python爬取糗事百科热门文章

默认情况下取糗事百科热门文章只有35页,每页20条,根据下面代码可以一次性输出所有的文章,也可以选择一次输出一条信息,回车继续.不支持图片内容的显示,显示内容包括作者,热度(觉得好笑的人越多,热度越高),内容.从热度最高开始显示到最低.实现代码如下: #!/usr/bin/python #coding:utf8 """ 爬取糗事百科热门文章 """ import urllib2 import re #模拟浏览器访问,否则无法访问 user_age

爬虫 爬取糗事百科热门板块的信息

分析: 1.先查看返回的内容是否与显示的内容一样 2.再看页数的变化,每次会加一,总共13页,因此可以一次性构造地址列表 3.因此可直接结合 chrome插件 xpath helper 与 elemetns显示的内容进行定位要爬取的内容 用到的模块 requests+json+lxml+xpath 下面是代码: import requests import json from lxml import etree class QiubaiSpider: def __init__(self): se

爬虫实践-爬取糗事百科网段子信息

qiushibaike.py: # 导入相应的库文件import requestsimport re # 加入请求头headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 ' '(KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'} # 初始化列表,用于装入爬虫信息info_lists = [] # 定义获取用户性别的函数def j

Python爬虫实战-爬取糗事百科段子

1.本文的目的是练习Web爬虫 目标: 1.爬去糗事百科热门段子 2.去除带图片的段子 3.获取段子的发布时间,发布人,段子内容,点赞数. 2.首先我们确定URL为http://www.qiushibaike.com/hot/page/10(可以随便自行选择),先构造看看能否成功 构造代码: 1 # -*- coding:utf-8 -*- 2 import urllib 3 import urllib2 4 import re 5 6 page = 10 7 url = 'http://www

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

首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把,这次我们尝试一下用爬虫把他们抓取下来. 友情提示 糗事百科在前一段时间进行了改版,导致之前的代码没法用了,会导致无法输出和CPU占用过高的情况,是因为正则表达式没有匹配到的缘故. 现在,博主已经对程序进行了重新修改,代码亲测可用,包括截图和说明,之前一直在忙所以没有及时更新,望大家海涵! 更新时间:2015/8/2 糗事百科又又又又改版了,博主已经没心再去一次次匹配它了,如果大家遇到长时间运行不出结果也不报错的情况,请大家参考最新的评

python3 爬虫之爬取糗事百科

闲着没事爬个糗事百科的笑话看看 python3中用urllib.request.urlopen()打开糗事百科链接会提示以下错误 http.client.RemoteDisconnected: Remote end closed connection without response 但是打开别的链接就正常,很奇怪不知道为什么,没办法改用第三方模块requests,也可以用urllib3模块,还有一个第三方模块就是bs4(beautifulsoup4) requests模块安装和使用,这里就不说

python爬取糗事百科段子

初步爬取糗事百科第一页段子(发布人,发布内容,好笑数和评论数) 1 #-*-coding:utf-8-*- 2 import urllib 3 import urllib2 4 import re 5 page = 1 6 url ='http://www.qiushibaike.com/hot/page/'+str(page) #第一页URL 7 headers={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/

PHP爬取糗事百科首页糗事

突然想获取一些网上的数据来玩玩,因为有SAE的MySql数据库,让它在那呆着没有什么卵用!于是就开始用PHP编写一个爬取糗事百科首页糗事的小程序,数据都保存在MySql中,岂不是很好玩! 说干就干!首先确定思路 获取HTML源码--->解析HTML--->保存到数据库 没有什么难的 1.创建PHP文件"getDataToDB.php", 2.获取指定URL的HTML源码 这里我用的是curl函数,详细内容参见PHP手册 代码为 <span style="fo

爬取糗事百科的图片

小编,最近写了个单线程的爬虫,主要是爬取糗事百科的图片之类的,下面是源代码,小伙伴们可以拿去参照,学习 #!/usr/bin/env python# -*- coding:utf-8 -*-import requests,jsonimport requests,re,os,timeimport urllib.requestimport urllib.parseimport sslimport unittestfrom selenium import webdriver headers = {"U