|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 H原子 于 2021-6-11 18:43 编辑
时间:2021.06.08
作者:H原子
分析:
待爬取根网页:https://pvp.qq.com/web201605/wallpaper.shtml###
1)通过浏览器检查元素和网页源代码进行对比,猜测此网页使用了Ajax与web服务器通信,
或者使用了js对页面进行了渲染。
2)通过查找浏览器向目标服务器发出的所有请求,确定是使用了Ajax,
请求包名为:
workList_inc.cgi?activityId=2735&sVerifyCode=ABCD&…267733&iActId=2735&iModuleId=2735&_=1623155585880
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=24&iOrder=0&iSortNumClose=1&jsoncallback=jQuery17102744849148361894_1623155545802
&iAMSActivityId=51991&_everyRead=true&iTypeId=2&iFlowId=267733&iActId=2735&iModuleId=2735&_=1623155585880
响应包URL截图
**注意**
(1)page参数:page=0表示返回第一页所需的信息,以此类推(创作这篇文章时共有25页)
(2)jsoncallback参数:指定返回的json格式(实际就是利用该参数的值将json对象括起来),使用时删去该参数
3)通过分析响应信息得到:每张壁纸对应有8张图片地址,第1张为展示图片,后7张为不同分辨率的图片
由于响应对内容加密了得到如下URL:
"http%3A%2F%2Fshp%2Eqpic%2Ecn%2Fishow%2F2735122519%2F1545737998%5F%2D888937974%5F13439%5FsProdImgNo%5F6%2Ejpg%2F200"
通过urllib.parse.unquote()解码得:
'http://shp.qpic.cn/ishow/2735122519/1545737998_-888937974_13439_sProdImgNo_6.jpg/200'
响应内容截图
**注意**
(1)这里将解码后的URL输入浏览器并不能得到预期的高分辨率图片,需要将末尾数字200改为0
(2)还可以通过 requests.utlis.unquote():解码
requests.utils.quote():编码
4)读取json格式响应内容,获取图片下载地址,下载保存。
结果展示:
总计有489个主题,每个主题有8张图片,应有4912张,实际有4911,一张下载失败
总文件数截图
保存形式截图
源代码获取:
- import requests
- import json
- from urllib import parse
- from urllib import request
- import os
- import threading
- from queue import Queue
- #生产者:通过page_queue队列获取页面对应Ajax响应地址,提取所有页面数据,获取壁纸主题名并创建相应文件夹,并将所有的图片下载地址和保存路径加入到imgurl_queue队列中
- class Producer(threading.Thread):
- def __init__(self,page_queue,imgurl_queue,*args,**kwargs):
- self.page_queue = page_queue
- self.imgurl_queue = imgurl_queue
- super().__init__()
-
- def run(self):
- headers = {
- 'user-agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'
- }
- while not self.page_queue.empty():
- try:
- response = requests.get(self.page_queue.get(),headers = headers)
- except:
- print('获取页面数据失败')
- jsondata = json.loads(response.content)
- datas = jsondata['List']
- for data in datas:
- theme_name = parse.unquote(data['sProdName']).replace(':','').strip()#有些主题名含有英文‘:’或者空格,这类名字不能命名文件夹
- theme_name = os.path.join('images',theme_name)
- if not os.path.exists(theme_name):#当该主题文件夹未创建时创建(不加这个判断会报出'文件已存在的错误')
- os.mkdir(theme_name)
- for x in range(1,9):
- imgdict = {}
- imgdict['imgurl'] = parse.unquote(data['sProdImgNo_%d'%x])[:-3]+'0'#利用切片将200修改为0
- imgdict['imgpath'] = os.path.join(theme_name,'%d.jpg'%x)#图片命名为:x.jpg的格式
- self.imgurl_queue.put(imgdict)
- #消费者:通过imgurl_queue队列获取图片下载地址和保存路径,将图片下载至对应路径
- class Consumer(threading.Thread):
- def __init__(self,imgurl_queue,*args,**kwargs):
- self.imgurl_queue = imgurl_queue
- super().__init__()
-
- def run(self):
- while True:
- try:
- img_obj = self.imgurl_queue.get(timeout=10)#队列为空阻塞时,等待10s,超时将触发异常,此时下载完成
- imgurl = img_obj.get('imgurl')
- imgpath = img_obj.get('imgpath')
- try:
- request.urlretrieve(imgurl,imgpath)#传递url和下载路径即可完成下载
- except:
- print('%s图片下载失败' % imgpath)
- except:
- print('所有图片已下载完毕...')
- break
- def main():
- if not os.path.exists('images'):#将所有下载的壁纸都保存在images文件夹下
- os.mkdir('images')
-
- Ajax_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&iAMSActivityId=51991&_everyRead=true&iTypeId=2&iFlowId=267733&iActId=2735&iModuleId=2735&_=1623155585880'
- page_queue = Queue(30)#目前总共有25页,大小为30足够了
- imgurl_queue = Queue(1000)
-
- #将所有页面对应的Ajax响应地址加入到page_queue队列中
- for i in range(25):
- page_queue.put(Ajax_url.format(i))
-
- #创建生产者线程
- for x in range(3):
- tp = Producer(page_queue,imgurl_queue,name='生产者%d号'%x)
- tp.start()
- #创建消费者线程
- for x in range(5):
- tc = Consumer(imgurl_queue,name='消费者%d号'%x)
- tc.start()
-
-
- if __name__=='__main__':
- main()
复制代码 |
|