这一章,咱们通过实战来运用多线程爬虫,就来爬取目前最火的王者荣耀游戏的皮肤。看看跟普通爬虫方式相比,会不会更快捷。
关于普通方式爬取,大家可以看看这篇文章:Python爬虫实战之爬取王者荣耀皮肤
第一步,定义生产者
第二步,定义消费者
第三步,定义主线程函数
生产者和消费者的概念,咱们在之前就已经讨论过,这里生产者就是生产图片名称及url,消费者就是通过生产者生产的名字、url来保存图片文件,这就是整个多线程爬虫的思路。
第一步,定义生产者
1.先导入几个模块、参数:
import requests
from urllib import parse
import os
from urllib import request
import threading
import queue
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36','referer':'https://pvp.qq.com/web201605/wallpaper.shtml'
}
2.通过定义类、继承参数、run方法来定义生产者
super()能动态拿到父类的初始化属性,继承于父类,而父类要加上不定常参数(位置参数和关键字参数),之后就能初始化要用到的参数:
class Producer(threading.Thread):
def __init__(self,page_queue,image_queue,*args,**kwargs):
super(Producer,self).__init__(*args,**kwargs)
self.page_queue = page_queue # 多页队列
self.image_queue = image_queue # 图片队列
def run(self) -> None:
# 当队列不为空的时候才能从中取值
while not self.page_queue.empty():
page_url = self.page_queue.get() # 取出页队列的值(url)
resp = requests.get(page_url, headers=headers)
result = resp.json()
datas = result['List']
for data in datas:
# 遍历url、解码、替换,得到正确图片url
image_urls = [parse.unquote(data['sProdImgNo_{}'.format(i)]).replace('200','0') for i in range(1,9)]
# 获取图片名
name = parse.unquote(data['sProdName'])
dir_path = os.path.join('image', name)
# 没有文件夹我才去创建
if not os.path.exists(dir_path):
os.mkdir(dir_path)
# 把图片的url放到队列当中
for index,image_url in enumerate(image_urls):
self.image_queue.put({'image_url':image_url,'image_path':os.path.join(dir_path,'%d.jpg'%(index+1))})
第二步,定义消费者
消费者的逻辑是获取数据,下载图片:
class Consumer(threading.Thread):
def __init__(self, image_queue, *args, **kwargs):
super(Consumer, self).__init__(*args, **kwargs)
self.image_queue = image_queue # 图片队列
def run(self) -> None:
while True:
# 获取图片的url和下载路径(下完就自动完成)
try:
image_obj = self.image_queue.get(timeout=10)
image_url = image_obj.get('image_url')
image_path = image_obj.get('image_path')
try:
# 下载图片(在下一级)
request.urlretrieve(image_url,image_path)
print(image_path,'下载成功!')
except:
print(image_path+'下载完毕!')
except:
break
第三步,定义主线程函数
def main():
# 创建页数的队列
page_queue = queue.Queue(18)
# 创建图片的队列
image_queue = queue.Queue(1000)
# 第一页到第十页
for x in range(0,11):
page_url = 'https://apps.game.qq.com/cgi-bin/ams/module/ishow/V1.0/query/workList_inc.cgi?activityId=2735&sVerifyCode=ABCD&sDataType=JSON&iListNum=20&totalpage=0&page={page}&iOrder=0&iSortNumClose=1&iAMSActivityId=51991&_everyRead=true&iTypeId=2&iFlowId=267733&iActId=2735&iModuleId=2735&_=1597938787974'.format(page=x)
# 把页数的url添加到页数的队列当中
page_queue.put(page_url)
# 定义3个生产者线程
for x in range(3):
p = Producer(page_queue,image_queue)
p.start()
# 定义5个消费者线程
for x in range(5):
c = Consumer(image_queue)
c.start()
if __name__ == '__main__':
main()
执行整个代码,会发现报了一个错:
针对这个问题,只需把获取图片名这里的代码修改即可:
name = parse.unquote(data['sProdName']).replace('1:1','').strip()
先把1:1替换为空格,后面的strip()表示:如果strip()的参数为空,那么会默认删除字符串头和尾的空白字符,即把前面的空格删除了。
再次执行整个代码,结果如下:
可以看到,下载速度比起普通爬取,更加快捷了!
至此,多线程爬虫来爬取王者荣耀皮肤,到这里就介绍完毕了,感兴趣的小伙伴可以来试一试
Python爬虫基础部分:
- Python 怎么快速入门?11篇实战干货带你深入了解 Python爬虫!建议收藏
Python爬虫进阶部分:
- 第一篇:Python爬虫进阶(一)爬虫之动态数据与selenium
- 第二篇:Python爬虫进阶(二)爬虫之多任务模块(Ⅰ)
- 第三篇:Python爬虫进阶(三)爬虫之多任务模块(Ⅱ)
- 第四篇:Python爬虫进阶(四)爬虫之多任务模块(Ⅲ)
- 第五篇:Python爬虫实战之 爬取王者荣耀皮肤
最近在知乎创建了一个新的Python技术圈子,在里面每天都会分享好玩有趣的Python知识,你如果对Python这门技术感兴趣的可以加入哦!交个朋友
Python技术 - 知乎www.zhihu.com