多线程爬虫
应用场景
1、多进程 :CPU密集程序
2、多线程 :爬虫(网络I/O)、本地磁盘I/O
- 队列
# 导入模块
from queue import Queue
# 使用
q = Queue()
q.put(url)
q.get() # 当队列为空时,阻塞
q.empty() # 判断队列是否为空,True/False
- 线程模块
# 导入模块
from threading import Thread
# 使用流程
t = Thread(target=函数名) # 创建线程对象
t.start() # 创建并启动线程
t.join() # 阻塞等待回收线程
# 创建多线程
t_list = []
for i in range(5):
t = Thread(target=函数名)
t_list.append(t)
t.start()
for i in t_list:
i.join()
小米应用商店抓取(多线程)
- 目标
1、网址 :百度搜 - 小米应用商店,进入官网
2、目标 :应用分类 - 聊天社交
应用名称
应用链接
- 实现步骤
1、确认是否为动态加载
1、页面局部刷新
2、右键查看网页源代码,搜索关键字未搜到
# 此网站为动态加载网站,需要抓取网络数据包分析
2、F12抓取网络数据包
1、抓取返回json数据的URL地址(Headers中的Request URL)
http://app.mi.com/categotyAllListApi?page={}&categoryId=2&pageSize=30
2、查看并分析查询参数(headers中的Query String Parameters)
page: 1
categoryId: 2
pageSize: 30
# 只有page再变,0 1 2 3 ... ... ,这样我们就可以通过控制page的直拼接多个返回json数据的URL地址
- 代码实现
import requests
from threading import Thread
from queue import Queue
import json
import time
class XiaomiSpider(object):
def __init__(self):
self.headers = {'User-Agent':'Mozilla/5.0'}
self.url = 'http://app.mi.com/categotyAllListApi?page={}&categoryId=2&pageSize=30'
# 定义队列,用来存放URL地址
self.url_queue = Queue()
# URL入队列
def url_in(self):
# 拼接多个URL地址,然后put()到队列中
for i in range(67):
self.url.format((str(i)))
self.url_queue.put(self.url)
# 线程事件函数(请求,解析提取数据)
def get_page(self):
# 先get()URL地址,发请求
# json模块做解析
# 循环从队列中获取url抓取数据
while True:
# 当队列不为空时,获取url地址
if not self.url_queue.empty():
url = self.url_queue.get()
html = requests.get(url,headers=self.headers).text
self.parse_page(html)
else:
break
# 解析函数
def parse_page(self,html):
app_json = json.loads(html)
for app in app_json['data']:
# 应用名称
name = app['displayName']
# 应用链接
link = 'http://app.mi.com/details?id={}'.format(app['packageName'])
d = { '名称' : name,'链接' : link }
print(d)
# 主函数
def main(self):
self.url_in()
# 存放所有线程的列表
t_list = []
for i in range(10):
t = Thread(target=self.get_page)
t.start()
t_list.append(t)
# 统一回收线程
for p in t_list:
p.join()
if __name__ == '__main__':
start = time.time()
spider = XiaomiSpider()
spider.main()
end = time.time()
print('执行时间:%.2f' % (end-start))