Selenium实战:Python爬虫批量下载百度图片全流程解析
1. 项目概述与核心价值
最近在整理一个项目,需要用到大量的特定主题图片,手动下载显然不现实。于是,我又一次打开了熟悉的Python,准备用爬虫来解决。这次的目标是百度图片,工具选择了老朋友Selenium。为什么不用更快的 requests 库?因为百度图片的搜索结果页是动态加载的,图片链接藏在JavaScript渲染后的页面里, requests 直接抓取源码是看不到的。Selenium能模拟真实浏览器操作,完美解决这个问题。这篇文章,我就来手把手带你用Selenium实现百度图片的批量爬取,从环境搭建到代码逐行解析,再到如何优雅地处理反爬和优化效率,我会把每一步的思考、踩过的坑和最终验证有效的方案都分享出来。无论你是刚接触爬虫的新手,还是想了解Selenium动态爬取技巧的朋友,这篇实战指南都能让你直接上手,把代码跑起来,把图片下下来。
2. 环境准备与工具选型解析
2.1 为什么选择Selenium+Chrome组合?
在爬取动态网页时,我们有几个选择: requests +解析动态数据接口、 Selenium 、 Pyppeteer 或 Playwright 。对于百度图片,直接分析其图片数据的XHR请求接口比较复杂,参数加密且可能频繁变动,对新手不友好。Selenium模拟真人操作浏览器,绕过直接分析接口的麻烦,虽然速度不如直接请求接口快,但胜在稳定、直观、易于理解和调试。Chrome浏览器拥有最广泛的支持和丰富的开发者工具,因此我们选择Selenium驱动Chrome的方案。 Playwright 是后起之秀,功能强大,但生态和资料相对Selenium略少,从学习成本和稳定性考虑,本次实战选用经典的Selenium。
2.2 详细环境搭建步骤
首先,确保你已安装Python(3.6及以上版本)。我们通过pip安装必要的库。打开你的命令行终端(CMD、PowerShell或Terminal),执行以下命令:
pip install selenium
接下来是最关键的一步:下载与你的Chrome浏览器版本匹配的 ChromeDriver 。这是Selenium控制Chrome的桥梁。版本不匹配会导致程序无法启动。
- 查看Chrome版本 :打开Chrome浏览器,点击右上角三个点 -> 帮助 -> 关于Google Chrome,记下版本号(例如:124.0.6367.91)。
- 下载ChromeDriver :访问ChromeDriver官方下载站或国内镜像站。找到与你Chrome主版本号(例如124)一致的驱动程序版本进行下载。
- 放置ChromeDriver :下载后是一个可执行文件(如
chromedriver.exe(Windows)或chromedriver(Mac/Linux))。你有两种处理方式:- 方式一(推荐,方便管理) :将其放在一个固定的、不含中文和空格的目录下,例如
D:\Tools\chromedriver.exe。然后在代码中指定这个路径。 - 方式二(加入系统PATH) :将
chromedriver所在目录添加到系统的环境变量PATH中。这样可以在代码中直接使用webdriver.Chrome()而不指定路径。
- 方式一(推荐,方便管理) :将其放在一个固定的、不含中文和空格的目录下,例如
为了更好的开发体验,我们还可以安装一个用于解析HTML的库 lxml ,它比标准库的 html.parser 更快。
pip install lxml
3. 核心思路与代码结构设计
3.1 爬虫流程拆解
我们的目标是:输入一个关键词,自动爬取百度图片搜索结果中前N张图片,并保存到本地文件夹。整个流程可以分解为以下几步:
- 启动浏览器 :使用Selenium启动一个Chrome浏览器实例,并可配置为“无头模式”(不显示图形界面,节省资源)。
- 访问搜索页 :构造百度图片搜索的URL(例如:
https://image.baidu.com/search/index?tn=baiduimage&word=关键词),驱动浏览器打开。 - 模拟滚动加载 :百度图片采用“瀑布流”懒加载,需要模拟用户滚动鼠标滚轮的行为,让浏览器加载出更多图片。
- 定位图片元素 :图片加载出来后,我们需要在页面HTML中找到所有图片对应的标签。这里的关键是分析图片的真实地址(
src属性)藏在哪里。 - 提取图片链接 :从定位到的元素中,提取出高清大图的URL地址。百度图片的缩略图和小图地址与真实大图地址不同,需要仔细甄别。
- 下载与保存 :遍历提取到的图片链接,使用网络请求库(如
requests)将图片二进制数据下载下来,并以合理的文件名保存到本地。 - 关闭资源 :完成下载后,关闭浏览器驱动,释放资源。
3.2 项目目录结构规划
在写代码前,规划好目录结构能让项目更清晰。建议创建一个如下结构的项目文件夹:
baidu_image_crawler/
├── main.py # 主程序入口
├── downloader.py # 图片下载器模块
├── utils.py # 工具函数(如处理文件名)
├── chromedriver.exe # ChromeDriver程序(如果采用方式一放置)
├── logs/ # 日志目录(可选)
└── images/ # 图片保存目录
└── 关键词1/ # 按关键词创建子文件夹
└── 关键词2/
我们将核心功能模块化, main.py 负责控制浏览器和主流程, downloader.py 负责具体的下载逻辑, utils.py 放一些辅助函数。这样代码可读性和可维护性更好。
4. 逐行代码超详细解析与实现
现在,我们进入最核心的部分,一步步编写并解析代码。我会先给出完整代码块,然后分段进行详细解释。
4.1 主程序模块 (main.py)
import time
import os
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from downloader import download_image
from utils import safe_filename
def init_browser(headless=True):
"""
初始化并返回一个Chrome浏览器驱动实例。
headless: 是否启用无头模式(不显示浏览器界面)
"""
options = webdriver.ChromeOptions()
# 添加一些常用选项以优化性能和避免检测
options.add_argument('--disable-blink-features=AutomationControlled') # 隐藏自动化控制标识
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
# 禁用图片加载可以极大加快滚动加载速度,但我们就看不到图片了。
# 如果只是为了获取链接,可以开启。如果需要预览或处理图片本身,则关闭。
# prefs = {"profile.managed_default_content_settings.images": 2}
# options.add_experimental_option("prefs", prefs)
if headless:
options.add_argument('--headless') # 无头模式
options.add_argument('--disable-gpu') # 早期版本在Windows上需要
# 指定ChromeDriver路径。如果已加入PATH,可以写 `webdriver.Chrome(options=options)`
service = Service(executable_path='./chromedriver.exe') # 请根据你的实际路径修改
browser = webdriver.Chrome(service=service, options=options)
# 执行CDP命令,进一步规避检测
browser.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': '''
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
});
'''
})
return browser
def scroll_to_bottom(browser, scroll_pause_time=2, max_scrolls=20):
"""
模拟滚动浏览器到底部,以触发图片懒加载。
browser: 浏览器实例
scroll_pause_time: 每次滚动后等待页面加载的时间(秒)
max_scrolls: 最大滚动次数,防止无限滚动
"""
last_height = browser.execute_script("return document.body.scrollHeight")
scroll_count = 0
while scroll_count < max_scrolls:
# 滚动到页面底部
browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# 等待页面加载
time.sleep(scroll_pause_time)
# 计算新的滚动高度并与上一次对比
new_height = browser.execute_script("return document.body.scrollHeight")
if new_height == last_height:
# 如果高度不再变化,可能已加载完毕或遇到“加载更多”按钮
try:
# 尝试点击“加载更多”按钮(如果存在)
load_more_button = browser.find_element(By.CLASS_NAME, 'more')
load_more_button.click()
time.sleep(scroll_pause_time)
except:
# 没有找到按钮,说明可能真的加载完了
break
last_height = new_height
scroll_count += 1
print(f"已滚动 {scroll_count} 次,当前页面高度:{new_height}px")
def extract_image_urls(browser):
"""
从当前浏览器页面中提取所有图片的真实大图URL。
这是最关键也是最容易出错的一步。
"""
image_urls = []
# 百度图片的图片元素比较复杂。经过分析,缩略图通常放在 `img` 标签,但 `src` 是base64或小图链接。
# 真实的大图链接藏在父级 `a` 标签的 `href` 属性,或者图片元素的 `data-` 自定义属性里。
# 更可靠的方法是找到图片容器,然后获取其 `data-objurl` 或 `data-url` 属性。
# 方法一:尝试通过特定CSS选择器查找(稳定性取决于百度页面结构是否变化)
try:
# 查找所有具有 `data-objurl` 属性的元素(这是旧版百度图片的结构)
img_elements = browser.find_elements(By.CSS_SELECTOR, '.imgitem, .imgbox, .imgitem .imgbox')
for img_element in img_elements:
objurl = img_element.get_attribute('data-objurl')
if objurl and objurl.startswith('http'):
image_urls.append(objurl)
except Exception as e:
print(f"通过CSS选择器查找元素出错: {e}")
# 方法二:如果方法一没找到,尝试更通用的查找图片元素并分析其属性
if not image_urls:
print("方法一未找到足够链接,尝试方法二...")
all_images = browser.find_elements(By.TAG_NAME, 'img')
for img in all_images:
src = img.get_attribute('src')
data_src = img.get_attribute('data-src')
data_url = img.get_attribute('data-url')
# 优先取 data-url, 其次是 data-src,最后是 src,并过滤掉base64和小图
target_url = data_url or data_src or src
if target_url and target_url.startswith('http') and 'thumb' not in target_url and 'src=' not in target_url:
# 进一步清洗URL,有时URL被编码或包含多余参数
clean_url = target_url.split('?')[0] if '?' in target_url else target_url
if clean_url not in image_urls:
image_urls.append(clean_url)
# 去重
image_urls = list(set(image_urls))
print(f"共提取到 {len(image_urls)} 个疑似图片链接。")
return image_urls
def main():
keyword = input("请输入要搜索的图片关键词: ")
max_downloads = int(input("请输入想要下载的最大图片数量 (例如 50): "))
save_dir = os.path.join('images', safe_filename(keyword))
# 创建保存目录
if not os.path.exists(save_dir):
os.makedirs(save_dir)
print(f"初始化浏览器(无头模式)...")
browser = init_browser(headless=True) # 调试时可设为False看浏览器操作
try:
# 构造搜索URL
search_url = f"https://image.baidu.com/search/index?tn=baiduimage&word={keyword}"
print(f"正在访问: {search_url}")
browser.get(search_url)
# 等待页面初步加载
time.sleep(3)
# 模拟滚动加载更多图片
print("开始模拟滚动加载...")
scroll_to_bottom(browser, scroll_pause_time=2, max_scrolls=15)
# 提取图片链接
print("开始解析页面提取图片链接...")
img_urls = extract_image_urls(browser)
if not img_urls:
print("未提取到任何图片链接,请检查页面结构或选择器。")
# 调试时可保存页面源码
# with open('debug_page.html', 'w', encoding='utf-8') as f:
# f.write(browser.page_source)
return
# 限制下载数量
download_urls = img_urls[:max_downloads]
print(f"准备下载前 {len(download_urls)} 张图片...")
# 下载图片
success_count = 0
for idx, url in enumerate(download_urls, 1):
print(f"({idx}/{len(download_urls)}) 正在下载: {url[:80]}...")
filepath = os.path.join(save_dir, f"{safe_filename(keyword)}_{idx:04d}.jpg")
if download_image(url, filepath):
success_count += 1
time.sleep(0.5) # 礼貌性延迟,避免请求过快
print(f"下载完成!成功下载 {success_count} 张图片,保存至目录: {save_dir}")
except Exception as e:
print(f"主流程发生错误: {e}")
finally:
# 确保浏览器被关闭
browser.quit()
print("浏览器已关闭。")
if __name__ == '__main__':
main()
代码解析与关键点说明:
-
init_browser函数 :这是启动浏览器的核心。我们创建了ChromeOptions对象来添加各种配置。--disable-blink-features=AutomationControlled和相关excludeSwitches选项是为了隐藏Selenium的自动化特征,降低被网站识别为爬虫的风险。这是应对反爬的重要一步。headless参数让你可以选择是否显示浏览器窗口。调试时设为False可以看到浏览器操作过程,非常直观;正式运行时设为True可以节省资源。Service对象用于指定chromedriver.exe的路径。这是Selenium 4.x的推荐写法。execute_cdp_cmd执行了一个Chrome DevTools Protocol命令,将navigator.webdriver属性重写为undefined,这是目前比较有效的反反爬手段之一。
-
scroll_to_bottom函数 :模拟人类滚动行为。核心是使用browser.execute_script执行JavaScript代码window.scrollTo来滚动页面。通过对比滚动前后页面的总高度(scrollHeight)来判断是否已滚动到底。如果高度不变,可能触发了“加载更多”按钮,代码尝试查找并点击它。max_scrolls参数防止因页面无限滚动而陷入死循环。 -
extract_image_urls函数 :这是 最核心也是最脆弱 的部分,因为完全依赖于百度图片前端的HTML结构。我提供了两种策略:- 方法一(精准定位) :尝试使用特定的CSS选择器(如
.imgitem)来定位图片容器元素,然后获取其data-objurl属性。这个属性通常直接存放高清大图的URL。这种方法最直接,但如果百度前端改版,选择器可能失效。 - 方法二(兜底策略) :如果方法一失败,则遍历页面所有
<img>标签,分析其src、data-src、data-url等属性,通过一些规则(如过滤包含thumb、src=等关键词的链接)来筛选出可能是大图的URL。这种方法更通用,但可能混入一些非目标图片或小图。 - 重要提示 :网页结构随时可能变化。如果某天发现爬取不到链接了,第一件事就是用
browser.page_source将页面HTML保存下来,然后用浏览器开发者工具(F12)重新分析图片元素的结构和属性,更新这个函数里的选择器和属性提取逻辑。
- 方法一(精准定位) :尝试使用特定的CSS选择器(如
-
main函数 :主流程控制器。它组织以上所有步骤:接收用户输入、创建目录、启动浏览器、访问URL、滚动、解析链接、最后调用下载模块。time.sleep的运用是为了给页面加载和网络请求留出时间,是简单有效的“礼貌等待”。
4.2 下载器模块 (downloader.py)
import requests
from fake_useragent import UserAgent
import os
def download_image(url, filepath, timeout=10, retry=2):
"""
下载单张图片并保存到指定路径。
url: 图片的URL地址
filepath: 本地保存路径(包含文件名)
timeout: 请求超时时间(秒)
retry: 失败重试次数
"""
headers = {
'User-Agent': UserAgent().random # 使用随机User-Agent
}
for attempt in range(retry + 1):
try:
response = requests.get(url, headers=headers, timeout=timeout, stream=True)
response.raise_for_status() # 检查HTTP请求是否成功
# 检查内容类型是否为图片
content_type = response.headers.get('content-type', '')
if 'image' not in content_type:
print(f" 警告:URL返回的内容不是图片 (Content-Type: {content_type}),跳过。")
return False
# 以二进制写入模式保存图片
with open(filepath, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
print(f" 图片已保存至: {filepath}")
return True
except requests.exceptions.Timeout:
print(f" 第{attempt+1}次尝试下载超时: {url}")
except requests.exceptions.HTTPError as e:
print(f" HTTP错误 ({e.response.status_code}): {url}")
if e.response.status_code == 404:
return False # 404错误无需重试
if e.response.status_code == 403:
print(" 可能遇到反爬限制,建议增加延迟或更换IP。")
except requests.exceptions.RequestException as e:
print(f" 下载请求异常: {e}")
except IOError as e:
print(f" 文件写入错误: {e}")
return False
if attempt < retry:
print(f" 等待1秒后重试...")
time.sleep(1)
print(f" 下载失败,已重试{retry}次: {url}")
return False
# 需要安装 fake_useragent 库
# pip install fake_useragent
代码解析与关键点说明:
-
fake_useragent库 :用于生成随机的、真实的浏览器User-Agent字符串。固定或单一的User-Agent容易被识别为爬虫。随机化User-Agent是基础的反反爬措施。 -
stream=True参数 :当下载大文件(如图片)时,使用流式传输可以避免一次性将整个响应内容读入内存。我们通过response.iter_content分块读取和写入文件,这对内存更友好。 - 内容类型检查 :通过检查HTTP响应头中的
Content-Type字段,确认我们下载的确实是图片数据,而不是错误的HTML页面或其他文件。这是一个健壮性检查。 - 异常处理与重试机制 :网络请求充满不确定性。我们捕获了超时(
Timeout)、HTTP错误(如404、403)、通用请求异常和IO错误。对于可重试的错误(如超时、网络波动),我们设置了重试逻辑。对于明确的错误(如404),则直接放弃。这是保证爬虫稳定运行的必要环节。 -
raise_for_status():这个方法在HTTP响应状态码不是200时抛出HTTPError异常,让我们能集中处理失败的请求。
4.3 工具模块 (utils.py)
import re
import os
def safe_filename(filename, max_length=200):
"""
将字符串转换为安全的文件名(移除非法字符,限制长度)。
filename: 原始字符串
max_length: 文件名最大允许长度
"""
# 定义非法字符(Windows/Linux/Unix通用)
illegal_chars = r'[<>:"/\\|?*\x00-\x1f]'
# 替换非法字符为下划线
safe_name = re.sub(illegal_chars, '_', filename)
# 去除首尾空格和点(点在某些系统中特殊)
safe_name = safe_name.strip('. ')
# 限制长度
if len(safe_name) > max_length:
# 保留扩展名(如果有的话)
name_part, ext_part = os.path.splitext(safe_name)
# 截断主文件名部分
name_part = name_part[:max_length - len(ext_part)]
safe_name = name_part + ext_part if name_part else ext_part[1:] # 处理无主文件名的情况
# 如果文件名最终为空(例如输入全是非法字符),返回一个默认名
if not safe_name:
safe_name = 'unnamed_file'
return safe_name
代码解析与关键点说明:
这个工具函数虽然小,但很重要。它处理用户输入的关键词,将其转换为合法的文件名。不同操作系统对文件名中的字符(如 <>:"/\|?* )和长度有限制。直接使用关键词作为文件夹名或文件名的一部分,如果关键词包含这些字符,会导致程序出错。这个函数通过正则表达式移除或替换非法字符,并截断过长的文件名,确保了文件操作的稳定性。
5. 高级技巧、反爬策略与性能优化
5.1 应对反爬虫机制的策略
百度和其他大型网站都有反爬虫措施。我们的代码已经包含了一些基础策略:
- 隐藏自动化特征 :通过ChromeOptions和CDP命令,尽可能让Selenium驱动的浏览器看起来像普通用户。
- 随机User-Agent :每次请求使用不同的浏览器标识。
- 模拟人类行为 :
scroll_to_bottom函数中的滚动和等待,模仿了真人浏览时的停顿。可以进一步随机化滚动距离和等待时间,使其更“人性化”。 - 请求间隔 :在主循环下载图片时,我们设置了
time.sleep(0.5),这是最基本的礼貌延迟,避免在短时间内对服务器发起大量请求。
如果遇到更严格的反爬(如IP被封、出现验证码),可以考虑以下进阶方案:
- 使用代理IP池 :这是解决IP封锁最有效的方法。可以在
download_image函数的requests.get中或Selenium启动浏览器时设置代理。# 在download_image的requests中使用代理 proxies = { 'http': 'http://your_proxy_ip:port', 'https': 'http://your_proxy_ip:port' } response = requests.get(url, headers=headers, proxies=proxies, ...) # 在init_browser中为Selenium设置代理 options.add_argument('--proxy-server=http://your_proxy_ip:port') - 处理验证码 :如果页面弹出验证码,自动化处理难度较大。可以考虑:
- 手动介入 :调试时关闭无头模式,手动输入验证码。
- 使用打码平台 :付费服务,通过API发送验证码图片,返回识别结果。
- 降低请求频率 :这是最经济的方法,增加
time.sleep的间隔,减少触发验证码的概率。
- 使用更稳定的定位方式 :如果因为页面动态加载导致元素定位失败,可以使用Selenium的“显式等待”(
WebDriverWait),而不是固定的time.sleep。这在main.py中已导入,但未使用。例如,等待某个特定元素出现后再进行下一步操作,可以提高代码的健壮性。
5.2 性能优化与扩展思路
- 多线程/异步下载 :当前代码是单线程顺序下载图片,如果图片很多,速度会较慢。可以使用
concurrent.futures.ThreadPoolExecutor实现多线程并发下载,显著提升下载速度。 但要注意,并发过高会急剧增加被封IP的风险,务必谨慎控制线程数(如3-5个),并考虑配合代理IP使用。 - 断点续传与状态保存 :如果要爬取海量图片,可以考虑将已成功下载的图片URL记录到一个文件或数据库中。程序重启时,先读取这个记录,过滤掉已下载的URL,实现断点续爬。
- 更智能的滚动加载 :当前的滚动逻辑是滚到底部。可以改进为根据要下载的图片数量动态控制滚动次数,比如当收集到的链接数达到
max_downloads的2倍时就停止滚动,避免不必要的网络请求和等待。 - 错误URL过滤与去重 :在
extract_image_urls函数提取的链接中,可能混入非图片链接或重复链接。可以在下载前增加一个过滤步骤,例如检查URL后缀是否为常见图片格式(.jpg,.jpeg,.png,.gif,.webp),或者使用布隆过滤器进行高效去重。
6. 常见问题排查与实战心得
6.1 问题速查表
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
程序报错 WebDriverException: Message: unknown error: cannot find Chrome binary |
Chrome浏览器未安装,或安装路径不在默认位置。 | 确保已安装Chrome。或在 ChromeOptions 中指定浏览器路径: options.binary_location = r'C:\...\chrome.exe' |
报错 SessionNotCreatedException: ... This version of ChromeDriver only supports Chrome version ... |
ChromeDriver版本与Chrome浏览器版本不匹配。 | 严格按本文2.2节步骤,下载与Chrome主版本号一致的ChromeDriver。 |
| 能打开浏览器,但访问页面空白或异常。 | 网络问题、网站屏蔽、或浏览器选项冲突。 | 1. 检查网络。2. 尝试关闭无头模式( headless=False )看具体情况。3. 暂时注释掉 options 中部分反爬参数再试。 |
extract_image_urls 函数返回的链接列表为空。 |
百度图片页面HTML结构已更新,代码中的CSS选择器或属性名失效。 | 这是最常见的问题! 1. 关闭无头模式,肉眼观察页面是否正常加载。2. 在 extract_image_urls 函数出错位置,使用 browser.page_source 将HTML保存到本地文件分析。3. 用浏览器开发者工具(F12)重新审查图片元素,找到存放真实大图URL的新属性或新选择器,更新代码。 |
| 可以提取到链接,但下载的图片很小(缩略图)。 | 提取到的URL是缩略图地址,不是原图地址。 | 检查提取逻辑。百度图片的真实大图URL可能藏在 data-objurl 、 data-url 或父级 <a> 标签的 href 中,且链接中通常不包含 thumb 、 src= 等字样。仔细分析页面元素结构。 |
| 下载部分图片失败,返回403 Forbidden错误。 | 目标图片服务器有防盗链或反爬机制。 | 1. 在 download_image 的请求头中,尝试添加 Referer 字段,通常设置为百度图片搜索页的URL。2. 显著增加请求间隔( time.sleep )。3. 考虑使用代理IP。 |
| 程序运行一段时间后卡住或崩溃。 | 可能内存泄漏、网络不稳定、或触发了网站的反爬导致连接被重置。 | 1. 确保在 finally 块中调用了 browser.quit() 。2. 为网络请求设置合理的 timeout 。3. 加入更完善的异常捕获和日志记录,定位具体崩溃点。 |
6.2 实操心得与注意事项
- 尊重
robots.txt:在爬取任何网站前,都应查看其robots.txt文件(例如:https://image.baidu.com/robots.txt)。这个文件规定了哪些目录允许或禁止爬虫访问。虽然技术上可以绕过,但遵守它是一个良好的网络公民准则,也能避免法律风险。对于个人学习、小规模数据抓取通常问题不大,但切忌进行大规模、商业化的恶意爬取,给对方服务器造成压力。 - 调试时关闭无头模式 :在开发调试阶段,务必设置
init_browser(headless=False)。这样你能亲眼看到浏览器是如何操作、页面是如何加载的,对于定位元素、分析页面结构、排查问题有不可替代的作用。 - “选择器”是动态爬虫的生命线 :Selenium爬虫的稳定性高度依赖于对页面HTML结构的解析。网站前端微小的改动就可能导致你的选择器失效。因此,提取链接的代码(
extract_image_urls)要有足够的鲁棒性,最好像示例中那样提供多套备选方案,并做好详细的错误日志记录。 - 延迟是美德也是盾牌 :在爬虫代码中适当添加
time.sleep(),不仅是为了等待页面加载完成,更是对目标网站服务器的基本尊重。过于频繁的请求无异于DDoS攻击,很容易导致你的IP被封锁。根据要爬取的数据量,合理设置滚动间隔和下载间隔。 - 本地化ChromeDriver :将
chromedriver放在项目目录下并通过相对路径引用(如./chromedriver.exe),比将其加入系统PATH更利于项目迁移和版本管理。不同项目可以使用不同版本的驱动,互不干扰。 - 从失败中学习 :爬虫项目很少能一次写成就永远运行。网站改版、反爬升级是常态。当爬虫失效时,不要慌张,将其视为学习的机会。重新分析页面,理解其新的数据加载逻辑(是换了接口还是改了前端框架),这个过程能极大地提升你前端和网络协议的分析能力。
更多推荐
所有评论(0)