马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
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()
|