Python3.8抓取百度图片高清原图『原来如此简单』『最新记录贴』

网上爬取百度图片的五花八门,要么有的过时的,有的则是爬取的是缩略图,不是原图等。
鉴于此在学习的过程中,记录此贴。在写本文的时候,代码是可用的。

前言

1.首先要有第一个明白的地方是百度图片目前是动态页面,无法正常使用爬取元素标签的方式去抓取图片。
2.使用requests请求百度图片时,返回的响应体里原图的链接是加密的。(所以直接能取到或者看到的都是非原图)
3.我也只是个小白,学习的过程看到网上文章比较乱,所以特地记录此贴。有什么任何错误,欢迎指教,但别开喷,谢谢。

工具包

脚本使用的工具包有:

import json
import re
import time
from concurrent.futures.thread import ThreadPoolExecutor
import requests

其中requests 可以使用 pip install requests 安装,我使用的版本是 2.23.0。

代码

本来是打算一步一步讲解,但是太浪费时间了。所以我选择注解代码的方式。希望大家能看得懂


# 储存所抓取到的原图链接
img_list = []

# 线程池,最大个数为150
pool = ThreadPoolExecutor(max_workers=int(150))

# 请求头
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36'
                         ' (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36'}

# 百度图片请求链接
base_url = r"https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&" \
           r"fp=result&queryWord={keyword}&cl=2&lm=-1&ie=utf-8&oe=utf-8&" \
           r"adpicid=&st=&z=&ic=&hd=&latest=©right=&word={keyword}&s=&" \
           r"se=&tab=&width=&height=&face=&istype=&qc=&nc=&fr=&expermode=&force=&pn={index}&rn=30&gsm=1e"


# 解密百度原图地址函数,来自网上,非常感谢。
def decode_url(url):
    """
    对百度加密后的地址进行解码
    :param url:百度加密的url
    :return:解码后的url
    """
    if not url:
        return None
    table = {'w': "a", 'k': "b", 'v': "c", '1': "d", 'j': "e", 'u': "f", '2': "g", 'i': "h",
             't': "i", '3': "j", 'h': "k", 's': "l", '4': "m", 'g': "n", '5': "o", 'r': "p",
             'q': "q", '6': "r", 'f': "s", 'p': "t", '7': "u", 'e': "v", 'o': "w", '8': "1",
             'd': "2", 'n': "3", '9': "4", 'c': "5", 'm': "6", '0': "7",
             'b': "8", 'l': "9", 'a': "0", '_z2C$q': ":", "_z&e3B": ".", 'AzdH3F': "/"}
    url = re.sub(r'(?P_z2C\$q|_z\&e3B|AzdH3F+)', lambda matched: table.get(matched.group('value')), url)
    return re.sub(r'(?P[0-9a-w])', lambda matched: table.get(matched.group('value')), url)


# 获取百度图片的函数
def get_img(get_index):
    global img_list

    # 构造一个完整的请求链接
    get_url = base_url.format(keyword=search_key, index=get_index)

    # 获得响应数据
    get_response = requests.get(get_url, headers=headers).text

    # 由于获得的响应数据是json类型,所以直接json格式化
    json_data = json.loads(get_response, strict=False)

    # 列表推导式,推导得到解密后的原图地址
    url_list = [decode_url(data.get('objURL')) for data in json_data.get('data')]

    # 这一步是删了列表里最后一个元素,原因是因为百度返回的每一条数据里永远会多一个空的数据,所以将他删除
    if len(url_list) >= 1:
        del url_list[len(url_list) - 1]

    # 将这个原图网址的列表 放到img_list里    
    img_list += url_list
    print("当前图片数量: %d" % len(img_list))
    print("总用时:%s" % (time.time() - start))


search_key = input("请输入想搜索照片的关键词:")

# 构造一个完整的请求链接
full_url = base_url.format(keyword=search_key, index=0)

# 获得响应数据
response = requests.get(full_url, headers=headers).text

# 由于获得的响应数据是json类型,所以直接json格式化
json_list = json.loads(response, strict=False)

# list_num是百度返回数据里告诉我们搜索图片的总量
list_num = int(json_list.get('listNum'))

# 计时
start = time.time()

# 通过对list_num处理,来决定需要请求多少次,每次的图片数量是30.之所以是30是因为百度网页每次请求时默认是30条数据,所以我采用了默认值。
for index in range(0, list_num, 30):
    # 开启一个线程处理请求和数据
    t = pool.submit(get_img, index)

文章里我只输出了【图片总量】和【总用时】,所有原图链接储存在img_list里,如果需要看到连接,可以直接输出,或者写到文件里,这里我就不写了。

成果

展示我自己输出的结果
Python3.8抓取百度图片高清原图『原来如此简单』『最新记录贴』_第1张图片
1695张图片,用时不到1秒,还可以了。

你可能感兴趣的:(python,json,http)