避坑指南:新手爬百度图片3个致命错,改完批量保存本地(亲测有效)

避坑指南:新手爬百度图片3个致命错,改完批量保存本地(亲测有效)

新手爬百度图片时,最容易遇到“只能爬30张”“保存的图模糊/打不开”“爬几次就被封”这3个问题——看似简单的批量下载,实则因为百度图片的动态加载+反爬机制+缩略图陷阱,让很多新手卡壳。

本文针对性解决这3个核心坑,用 requests 模拟接口请求、json 解析数据,改完代码就能批量爬取高清原图并保存本地,全程带避坑说明和完整代码,新手也能10分钟上手!

先明确:百度图片的爬取核心逻辑

百度图片不是静态网页,而是下滑时通过API接口动态加载图片数据(返回JSON格式),而非直接嵌入HTML。新手的误区的是“爬HTML找img标签”,正确思路是“抓包找API接口→模拟请求→提取原图链接→下载保存”。

新手常见3个错(附解决方案)

错1:只爬静态HTML,最多拿到30张(动态加载未处理)

表现:

运行代码后只保存了30-50张图片,下滑百度图片页面看到的更多图片爬不到。

原因:

百度图片首页的HTML只加载了“初始一屏”的图片(约30张),后续图片需要下滑时触发AJAX请求,从API接口获取更多数据。新手直接用 requests.get 爬首页HTML,自然拿不到后续图片。

解决:

抓包找到百度图片的数据接口(关键!);分析接口参数,循环请求不同“页码”,批量获取图片数据。

如何抓包找接口?(新手也会)

打开百度图片(https://image.baidu.com/),搜索关键词(如“猫咪”);按F12打开开发者工具→切换到「Network」→刷新页面→筛选「XHR/ Fetch」(动态请求);找到名称含「acjson」的请求(这就是图片数据接口),点击它→「Headers」查看请求URL和参数,「Response」查看返回的JSON数据(包含图片链接)。

接口示例(已简化):

https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord=猫咪&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=&hd=1&latest=0©right=0&word=猫咪&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&force=&pn=30&rn=60&gsm=1e&1731234567890=

核心参数说明(必须正确设置):

word:搜索关键词(如“猫咪”,需URL编码);pn:已加载的图片总数(分页关键!第1页pn=0,第2页pn=60,第3页pn=120…每次加60);rn:每页返回的图片数量(最大60,设置多了会被限制);hd:是否高清(1=高清,0=标清)。

错2:爬的是缩略图,保存后模糊/失效(原图链接提取错误)

表现:

保存的图片只有几百KB,模糊不清,甚至打开提示“文件损坏”。

原因:

新手直接提取JSON中thumbURL(缩略图链接)或HTML中img标签的src,这些都是百度用于预览的缩略图,不仅画质差,还可能带时效性(过期失效)。

解决:

提取JSON中的原图链接字段,优先级:replaceUrl[0].ObjURL > ObjURL > hoverURL(这些是高清原图链接,无时效限制)。

错3:请求太“硬”,被百度反爬封禁(无反爬措施)

表现:

前几次能爬,后来报错403 Forbidden,甚至本地网络访问百度图片都变慢(IP被临时限制)。

原因:

未设置请求头,被识别为“爬虫”;请求频率太快(毫秒级请求,不像人类操作);同一IP反复请求,触发百度反爬机制。

解决:

完善请求头(模拟真实浏览器,必带User-Agent和Referer);限速爬取(每请求1页暂停1-3秒,随机时间更安全);可选:使用代理IP池(避免单一IP被封);随机化请求参数(如时间戳1731234567890,每次请求生成新值)。

改完就能用:批量爬百度图片完整代码(避坑版)

核心功能:

支持自定义关键词、爬取数量、保存路径;自动获取高清原图,避免缩略图;带反爬措施,不易被封;自动创建文件夹,批量保存本地,跳过失效链接。

import requests

import json

import os

import random

import time

from urllib.parse import quote # URL编码(处理关键词中的中文)

from loguru import logger

# ---------------------- 配置参数(新手可直接修改这部分) ----------------------

KEYWORD = "猫咪" # 搜索关键词(可替换为其他,如“风景”“动漫”)

SAVE_DIR = f"./百度图片_{KEYWORD}" # 图片保存目录(自动创建)

TOTAL_NUM = 300 # 目标爬取数量(最大建议≤1000,避免触发反爬)

PER_PAGE = 60 # 每页爬取数量(最大60,百度限制)

TIMEOUT = 10 # 请求超时时间(秒)

DELAY = (1.5, 3) # 每页爬取间隔(1.5-3秒随机,模拟人类操作)

# 完善请求头(模拟浏览器,关键反爬措施)

HEADERS = {

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",

"Referer": "https://image.baidu.com/", # 表示请求来源是百度图片,必带!

"Accept": "text/plain, */*; q=0.01",

"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",

"X-Requested-With": "XMLHttpRequest" # 标识为AJAX请求,符合百度接口预期

}

# ---------------------- 工具函数(无需修改) ----------------------

def create_save_dir():

"""创建图片保存目录,不存在则新建"""

if not os.path.exists(SAVE_DIR):

os.makedirs(SAVE_DIR)

logger.info(f"✅ 创建保存目录:{SAVE_DIR}")

else:

logger.info(f"✅ 保存目录已存在:{SAVE_DIR}")

def get_image_urls(page_pn):

"""请求百度图片API,获取当前页的原图链接列表"""

# 百度图片API接口(核心!)

api_url = "https://image.baidu.com/search/acjson"

# 构造请求参数(动态生成时间戳,避免重复)

params = {

"tn": "resultjson_com",

"ipn": "rj",

"ct": 201326592,

"is": "",

"fp": "result",

"queryWord": KEYWORD,

"cl": 2,

"lm": -1,

"ie": "utf-8",

"oe": "utf-8",

"adpicid": "",

"st": -1,

"z": "",

"ic": "",

"hd": 1, # 1=高清图,0=标清图

"latest": 0,

"copyright": 0,

"word": quote(KEYWORD), # 关键词URL编码(处理中文/特殊字符)

"s": "",

"se": "",

"tab": "",

"width": "",

"height": "",

"face": 0,

"istype": 2,

"qc": "",

"nc": 1,

"fr": "",

"expermode": "",

"force": "",

"pn": page_pn, # 已加载图片总数(分页关键)

"rn": PER_PAGE, # 每页返回数量

"gsm": "1e",

str(random.randint(1000000000000, 9999999999999)): "" # 随机时间戳参数,反爬

}

try:

# 发送请求(关闭SSL验证,避免部分环境报错)

response = requests.get(

url=api_url,

headers=HEADERS,

params=params,

timeout=TIMEOUT,

verify=False

)

response.raise_for_status() # 状态码非200则抛异常

# 解析JSON数据(百度返回的JSON可能带多余字符,需处理)

# 解决:用try-except捕获,若解析失败则清理多余字符

try:

data = response.json()

except json.decoder.JSONDecodeError:

# 清理JSON字符串前后的多余字符(如百度有时会加")]}'")

clean_text = response.text.lstrip(")]}'").strip()

data = json.loads(clean_text)

# 提取原图链接(优先级:replaceUrl[0].ObjURL > ObjURL > hoverURL)

image_urls = []

for item in data.get("data", []):

if not item: # 过滤空数据

continue

# 按优先级获取原图链接

if "replaceUrl" in item and len(item["replaceUrl"]) > 0:

img_url = item["replaceUrl"][0]["ObjURL"]

elif "ObjURL" in item:

img_url = item["ObjURL"]

elif "hoverURL" in item:

img_url = item["hoverURL"]

else:

continue

# 过滤无效链接(仅保留http/https开头的图片链接)

if img_url.startswith(("http://", "https://")):

image_urls.append(img_url)

logger.info(f"✅ 第{page_pn//PER_PAGE + 1}页获取到{len(image_urls)}个有效图片链接")

return image_urls

except requests.exceptions.RequestException as e:

logger.error(f"❌ 第{page_pn//PER_PAGE + 1}页请求失败:{str(e)}")

return []

def download_image(img_url, img_index):

"""下载单张图片到本地,返回是否下载成功"""

# 提取图片后缀(优先从URL获取,默认.jpg)

suffix = img_url.split(".")[-1].lower()

if suffix not in ["jpg", "jpeg", "png", "gif", "bmp"]:

suffix = "jpg"

# 图片保存路径(避免重名,用“关键词+序号”命名)

img_path = os.path.join(SAVE_DIR, f"{KEYWORD}_{img_index:04d}.{suffix}")

try:

# 下载图片(添加请求头,避免部分网站拒绝爬虫请求)

img_headers = HEADERS.copy()

img_headers["Referer"] = img_url # 部分图片需要Referer验证

response = requests.get(

url=img_url,

headers=img_headers,

timeout=TIMEOUT,

stream=True, # 流式下载,适合大文件

verify=False

)

response.raise_for_status()

# 保存图片到本地(二进制写入)

with open(img_path, "wb") as f:

for chunk in response.iter_content(chunk_size=1024):

if chunk:

f.write(chunk)

logger.success(f"📥 下载成功:{img_path}")

return True

except requests.exceptions.RequestException as e:

logger.warning(f"❌ 下载失败(索引{img_index}):{str(e)}")

return False

# ---------------------- 核心爬取逻辑(无需修改) ----------------------

def crawl_baidu_images():

"""完整爬取流程:创建目录→循环请求→下载图片→统计结果"""

# 1. 创建保存目录

create_save_dir()

# 2. 初始化变量

total_downloaded = 0 # 已下载图片数量

page_pn = 0 # 初始页码参数(pn=0表示第1页)

# 3. 循环爬取,直到达到目标数量或无更多图片

while total_downloaded < TOTAL_NUM:

# 获取当前页图片链接

image_urls = get_image_urls(page_pn)

if not image_urls:

logger.warning(f"⚠️ 未获取到更多图片,爬取可能提前结束")

break

# 下载当前页图片

for img_url in image_urls:

if total_downloaded >= TOTAL_NUM:

break # 达到目标数量,停止下载

# 下载图片(索引从1开始)

success = download_image(img_url, total_downloaded + 1)

if success:

total_downloaded += 1

# 单张图片下载间隔(0.3-0.8秒,避免高频请求)

time.sleep(random.uniform(0.3, 0.8))

# 每页爬取完成后,暂停随机时间(反爬关键)

time.sleep(random.uniform(*DELAY))

# 更新下一页的pn参数(每次加PER_PAGE)

page_pn += PER_PAGE

# 4. 爬取完成,统计结果

logger.info("="*50)

logger.info(f"🎉 爬取结束!")

logger.info(f"📊 目标爬取:{TOTAL_NUM}张")

logger.info(f"📊 成功下载:{total_downloaded}张")

logger.info(f"📊 保存路径:{os.path.abspath(SAVE_DIR)}")

logger.info("="*50)

# ---------------------- 启动爬取(运行这里即可) ----------------------

if __name__ == "__main__":

# 关闭requests的SSL警告(避免控制台刷屏)

requests.packages.urllib3.disable_warnings()

# 启动爬取

crawl_baidu_images()

代码运行步骤(新手友好)

安装依赖(终端输入):

pip install requests loguru -i https://pypi.tuna.tsinghua.edu.cn/simple

修改配置参数(KEYWORD 改关键词,TOTAL_NUM 改爬取数量);运行代码:python 百度图片爬虫.py(保存代码时用这个文件名);查看结果:代码所在目录会生成 百度图片_关键词 文件夹,图片已批量保存。

额外避坑:新手容易忽略的4个细节

关键词URL编码:必须用 quote(KEYWORD) 处理中文关键词(如“猫咪”→%E7%8C%AB%E5%92%AA),否则请求会返回空数据;JSON解析失败:百度返回的JSON可能带多余字符(如 )]}'"),代码中已加 clean_text 处理,避免解析报错;图片后缀处理:有些链接没有明确后缀,默认保存为 .jpg,避免文件格式错误;SSL验证警告:代码中 verify=False 关闭SSL验证(部分环境会因证书问题报错),同时用 disable_warnings() 屏蔽警告,不影响运行。

常见问题排查(爬取失败必看)

1. 爬不到数据,返回空链接?

原因:关键词未编码、请求头缺失 Referer、pn 参数设置错误;解决:确保 word=quote(KEYWORD)、Referer="https://image.baidu.com/"、pn 每次加 PER_PAGE(如60)。

2. 下载失败,提示“403 Forbidden”?

原因:图片链接需要 Referer 验证,或IP被限制;解决:代码中已给图片下载添加 img_headers["Referer"] = img_url,若仍失败,暂停10分钟再爬,或更换IP。

3. 爬取数量达不到目标?

原因:百度对单关键词爬取数量有限制(一般≤1000张),或部分链接失效;解决:降低 TOTAL_NUM(如改为500),或换关键词爬取。

4. 图片打开模糊?

原因:hd 参数设为0(标清);解决:确保 params["hd"] = 1(高清图),且提取的是 replaceUrl[0].ObjURL 等原图链接。

合规性说明(重要!)

遵守百度 robots.txt 协议:百度图片允许非商业、个人学习用途的爬取,禁止大规模、高频次爬取;控制爬取频率:代码中已加限速,请勿删除 time.sleep 相关代码,避免给百度服务器造成压力;数据用途:爬取的图片仅用于个人学习、研究,不得用于商业用途、二次创作或非法传播(注意图片版权!)。

总结

新手爬百度图片的核心是“绕开静态HTML,抓准API接口+处理反爬+提取原图”,改完本文提到的3个核心错,就能稳定批量保存高清图片。

这套思路可复用在其他图片网站(如必应图片、360图片),只需修改API接口和参数即可。如果想进一步优化,可添加代理IP池、多线程下载(新手不建议,容易触发反爬)、图片去重等功能!

相关文章

06世界杯英格兰阵型图 06世界杯英格兰战绩
英国投注网站365

06世界杯英格兰阵型图 06世界杯英格兰战绩

⌛ 10-17 👁️ 5815
六龙争霸3D天煌职业好不好?天煌职业技能解析
28365-365体育备用

六龙争霸3D天煌职业好不好?天煌职业技能解析

⌛ 09-29 👁️ 7411