原标题:应用python多线程爬虫下载王者荣耀壁纸
1.了解完成这个项目需要的模块
我这次做的这个项目需要的模块有:urllib、threading、json、random、time、os、sys
既然是爬虫,怎么少得了urllib模块呢?不过requests模块也行,只不过我这用得时urllib模块;threading(多线程模块);json模块,这些壁纸的下载链接是动态加载出来的,而真正的下载链接是在一个js文件下面,所以我导入json模块;random模块,这个模块我主要是用来给下载的壁纸取名称的,避免壁纸同名啊!;time模块,我主要是得到时间戳,然后拼接网址的,不过,好像也可以不需要这个模块也行;os模块,我主要是用来创建文件夹的;sys模块,我是用来退出程序的,如果我上面创建的文件夹已经存在了,那么应用这个模块下面的exit方法就可以退出程序了。
2.怎样实现多线程下载壁纸
首先,我们需要来到这个网址下面:王者荣耀壁纸
可以发现,这个网址下面有很多王者荣耀英雄的壁纸,我们按电脑键盘的F12键,来到如下界面:
但这个网址上面的图片下载链接是动态加载出来的,我们查看一下源代码就知道了,根本没有。
这个时候,我们可以看一下Network下面的JS,如下:
我们只需解析这个json文件下面的数据,就可以得到这些壁纸的下载链接了。
代码(这里我直接写了一个函数):
def get_img(url,id): # 定义一个函数,用于得到一页图片的下载链接
headers={
'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3756.400 QQBrowser/10.5.4039.400'
} # 添加一个请求头
request_1=request.Request(url=url,headers=headers)
responce=request.urlopen(request_1)
str_info=responce.read().decode('utf-8')
str_info=str_info[str_info.find('(')+1:str_info.rfind(')')] # 字符串处理,用于得到json数据
dict_info=json.loads(str_info)
list_info=dict_info['List']
key='sProdImgNo_{}'.format(id)
imgs=[parse.unquote(dict_1[key]) for dict_1 in list_info]
imgs=[str_1.replace(str_1[str_1.rfind('/')+1:],'0') for str_1 in imgs] # 对下载网址进行处理,否则得到的图片大小会不一致
return imgs
通过这个函数,我们就可以得到这一页所有壁纸的下载链接了。
怎样得到所有页的图片呢?这也很简单,我们只需对这个网址进行分析即可。
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=0&iOrder=0&iSortNumClose=1&jsoncallback=jQuery17105769768244876481_1588304946657&iAMSActivityId=51991&everyRead=true&iTypeId=2&iFlowId=267733&iActId=2735&iModuleId=2735&=1588304946853
好像只需更改这个网址下面page参数就可以访问不同页的壁纸了。为了使访问的时间不一样,我把最后面的那个参数也改了,最后面那个好像是一个时间戳,但一个时间戳的整数部分只有10位,而这里有13位,我猜测这多出来的三位应该是小数部分的,不过我也不知道对不对。不过,也可以使用同一个时段,这样也可以访问到数据。
代码:
def get_allimgs(): # 得到所有图片的下载链接
imgs=[] # 定义一个列表,用于存储所有图片的下载链接
list_1 = ['215,120', '1024,768', '1280,720', '1280,1024', '1440,900', '1920,1080', '1920,1200',
'1920,1440'] # 图片大小列表,宽 高
for i in range(len(list_1)):
print('【{}】->{}'.format(i+1,list_1[i]))
id=int(input('请输入你想下载的的图片大小:'))
for i in range(22):
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={}&iOrder=0&iSortNumClose=1&jsoncallback=jQuery171013320231189766485_1588287984049&iAMSActivityId=51991&_everyRead=true&iTypeId=2&iFlowId=267733&iActId=2735&iModuleId=2735&_={}'.format(i,int(time.time()*1000))
imgs.extend(get_img(url=url,id=id))
return imgs
最后面就是下载阶段了,因为我觉得我自己对于多线程的理解还不够,所以,这里,我就不跟大家讲了,希望大家理解。
下载完成之后,可以有如下结果:
打开一张壁纸看一下吧!
是不是挺炫酷的。
3.运行结果
应用python爬虫下载王者荣耀壁纸
4.完整代码
from urllib import parse
from urllib import request
import json # json 模块
import threading # 多线程模块
import random
import time
import os
import sys
def get_img(url,id): # 定义一个函数,用于得到一页图片的下载链接
headers={
'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3756.400 QQBrowser/10.5.4039.400'
} # 添加一个请求头
request_1=request.Request(url=url,headers=headers)
responce=request.urlopen(request_1)
str_info=responce.read().decode('utf-8')
str_info=str_info[str_info.find('(')+1:str_info.rfind(')')] # 字符串处理,用于得到json数据
dict_info=json.loads(str_info)
list_info=dict_info['List']
key='sProdImgNo_{}'.format(id)
imgs=[parse.unquote(dict_1[key]) for dict_1 in list_info]
imgs=[str_1.replace(str_1[str_1.rfind('/')+1:],'0') for str_1 in imgs] # 对下载网址进行处理,否则得到的图片大小会不一致
return imgs
def get_allimgs(): # 得到所有图片的下载链接
imgs=[] # 定义一个列表,用于存储所有图片的下载链接
list_1 = ['215,120', '1024,768', '1280,720', '1280,1024', '1440,900', '1920,1080', '1920,1200',
'1920,1440'] # 图片大小列表,宽 高
for i in range(len(list_1)):
print('【{}】->{}'.format(i+1,list_1[i]))
id=int(input('请输入你想下载的的图片大小:'))
for i in range(22):
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={}&iOrder=0&iSortNumClose=1&jsoncallback=jQuery171013320231189766485_1588287984049&iAMSActivityId=51991&_everyRead=true&iTypeId=2&iFlowId=267733&iActId=2735&iModuleId=2735&_={}'.format(i,int(time.time()*1000))
imgs.extend(get_img(url=url,id=id))
return imgs
def md_dir(): # 创建文件夹,如果文件夹已经存在,直接退出程序
name=input('请输入你想创建的文件夹名称:')
path='./{}'.format(name)
try:
os.mkdir(path=path)
except:
sys.exit() # 直接退出程序
return path
def Download(imgs,path): #下载图片
while True:
if len(imgs)==0:
break
url=imgs.pop()
try:
request.urlretrieve(url=url,filename=path+'/{}.png'.format(random.random())) # 图片的名称为随机数
print('{}---->线程{}正在加载'.format('-'*int(10*random.random()),threading.current_thread().getName()))
except:
print('出错啦!')
if __name__ == '__main__':
print('欢迎来到王者荣耀!')
path=md_dir()
imgs=get_allimgs()
threading_list=[]
for i in range(10): # 创建十个线程
threading_1=threading.Thread(target=Download,args=(imgs,path,))
threading_1.start()
threading_list.append(threading_1)
for i in threading_list:
i.join()
print('下载完毕!当前线程为{}'.format(threading.current_thread().getName()))
5.改进与总结
改进:这个项目要说改进的话,就是应用IP代理池来爬取壁纸,因为,我在第一次运行程序的时候,很快就下载完毕了,之后,下载速度就稍微慢了一些,而且出现404错误。不过,我也不知道是不是这个原因。
总结:如果大家觉得我的这个项目做得还行的话,记得点赞啊!在以后,我会更多分享的,谢谢!