鱼C论坛

 找回密码
 立即注册
查看: 2529|回复: 10

[作品展示] 多线程爬取全部王者高清壁纸

[复制链接]
发表于 2021-6-11 18:38:50 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

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截图

响应包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()

本帖被以下淘专辑推荐:

  • · python|主题: 62, 订阅: 4
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-6-11 23:56:26 From FishC Mobile | 显示全部楼层
贴图是个好习惯
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-6-12 09:28:29 | 显示全部楼层
贴图是个好习惯,没图没诱惑
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-12 19:00:44 From FishC Mobile | 显示全部楼层
阿这…,有道理
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-6-12 21:45:48 | 显示全部楼层
虽然我看不懂,但是我知道这一定很厉害!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-6-17 21:55:39 | 显示全部楼层
分析出来才是最难的吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-6-17 22:48:06 | 显示全部楼层
支持一下,希望楼主做的更好,加油!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-6-18 12:26:05 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-6-18 15:41:37 | 显示全部楼层
很酷很酷,可是看不懂源码。。。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-6-18 21:01:58 | 显示全部楼层
亲测,可以下载,如果有显示进度情况就好了。。。

刚打开还以为没有反应。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-21 11:44:05 | 显示全部楼层
努力学习中,图片和进度条下次一定,感谢大家前来捧场
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-23 21:14

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表