多线程爬取小米商城
前言:想必大家对python的多线程还不是很了解吧,今天我们的学习任务就是怎么使用多线程去爬取小米商城的App应用
1. 分析目标站点
目标URL : http://app.mi.com/category/15#page=0 小米商城
点击 “游戏-全部应用” 下方的下一页后发现整个页面只刷新了部分内容,这就说明整个网页都是动态加载来的,以下总结了怎么去判断整个网页是不是动态加载的。
总结:
- 鼠标往下滚动时加载了内容,但是整个页面没有重新加载
- 当点击下一页或者往下翻滚的时候只刷新了网页中的部分内容,整个页面也没有重新加载
- 当在页面中能找到的内容在网页源代码中找不到此内容时
小贴士:当碰到无法抓取的动态加载网页时,推荐使用selenium,可以python的第三方库中安装,这个库可以人为的操作浏览器去做自己想要做的事情,当我们以浏览器去操作网页时,我们也就不用考虑这个网页是不是动态加载的了。
2. 分析加载的数据
a) 抓包。当确定网页中的内容是动态异步加载时,我们第一个要做的抓包,右键检查进入Network → XHR中,异步加载的数据一般都可以在这里进行显示
b) 分析url。观察发送请求的url,发现只有page在变,而且第一页中的page对应的值为0,所以只需要改变page的值便可以获取全部的内容了。
3.分析代码
a) 创建请求url的队列。今天我们的主要内容是怎么去使用多线程爬取内容,所以我们第一步要做的就是怎么去创建发送请求url的队列。代码如下
我们首先将要爬取的url加入到url _list这个队列中去
class Xmshoop_spider(object):
def __init__(self):
self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36'}
self.url = 'http://app.mi.com/categotyAllListApi?page={}&categoryId=15&pageSize=30' # 需要爬取的url,通过改变page的值从而获取所有需要发送请求的url
self.url_list = Queue() # 创建先进先出队列
def send_request(self):
pass
def parse_json(self):
pass
def main(self):
for i in range(0,67): # for循环
self.url_list.put(self.url.format(i)) # 将要爬取的url通过put方法加入到队列中
if __name__ == '__main__':
spider = Xmshoop_spider()
spider.main()
b) 发送请求获取数据。通过队列的get方法取出最先put进去的url,因为我们创建的是先进先出队列,所以我们get得到的就是第一个放进去的url。
取出第一个url并发送请求获取数据
def send_request(self):
response = requests.get(self.url_list.get(),headers=self.headers).json() # 通过get方法取出第一个放进去的url,然后将获取到的json数据转为python中的字典类型数据
print(response)
c)分析数据。获取到数据后肯定就要提取出我们想要的数据,这里我告诉大家两种提取json数据的方法
- 将获取的json数据转为python中的字典类型,然后去提取
- 使用jsonpath语法直接对json数据进行操作并提取数据
d) 多线程请求数据。
def main(self):
t_list = []
for i in range(0,67): # for循环
self.url_list.put(self.url.format(i)) # 将要爬取的url通过put方法加入到队列中
for x in range(5):
t1 = Thread(target=self.send_request) # target的值函数名
t1.start() # 启动线程
t_list.append(t1) # 将线程加入到列表中
for t in t_list:
t.join() # 让主线程等待子线程结束
4. 完整代码:
import requests
from threading import Thread
from queue import Queue
class Xmshoop_spider(object):
def __init__(self):
self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36'}
self.url = 'http://app.mi.com/categotyAllListApi?page={}&categoryId=15&pageSize=30' # 需要爬取的url,通过改变page的值从而获取所有需要发送请求的url
self.url_list = Queue() # 创建先进先出队列
self.count = 0
def send_request(self):
while not self.url_list.empty():
response = requests.get(self.url_list.get(),headers=self.headers).json() # 通过get方法取出第一个放进去的url,然后将获取到的json数据转为python中的字典类型数据
self.parse_json(response)
def parse_json(self,res):
for data in res['data']:
name = data['displayName']
img_url = data['icon']
print(name,img_url)
self.count += 1
def main(self):
t_list = []
for i in range(0,67):
self.url_list.put(self.url.format(i)) # 将要爬取的url通过put方法加入到队列中
for x in range(5): # for循环5次,总共创建了5个线程去爬取
t1 = Thread(target=self.send_request) # 创建线程
t1.start() # 启动线程
t_list.append(t1)
for t in t_list:
t.join() # 主线程会一直阻塞等待子线程结束
if __name__ == '__main__':
spider = Xmshoop_spider()
spider.main()
print(spider.count) # 显示总共爬取了多少个数据
a) 检查结果。一页30个应用信息,67页正好2010条数据,对比开启线程和不开启线程爬取数据所花费的时间
- 开启10个线程花费1s
- 不开启线程花费了10s
结语:本章的多线程学习就到这里结束了,有觉得小编写的还不错的评论加点赞,你们的支持是我最大的动力。