目录前言
一、环境准备
二、整体思路
三、详细代码讲解
3.1 获取页面 HTML(伪装 Header)
3.2 多页 URL 生成3.3 用 xpath 提取标题页链接3.4 提取图片真实地址并下载3.5 断点续传模块3.6 自动文件夹管理3.7 图片下载函数3.8 时间戳工具函数
四、完整代码
五、使用方法
六、常见问题
小结前言本文手把手带你用 Pythonrequests库 +xpath写一个可以批量抓取网页图片的爬虫,支持:多级页面递归爬取(翻页 → 标题页 → 图片)
断点续传(history 模块,下载过的图片自动跳过)
自动新建文件夹(每满 490 张自动新建一个文件夹,方便导入百度云)
异常自动重试,错误写入日志完整代码在文末,直接可运行。
一、环境准备
# 安装依赖# 公主号:船长Talk pip install requests lxml
二、整体思路
爬虫流程分 4 步:getHTML(pages):生成多页 URL,逐页爬取htmlTex(url):请求页面,获取 HTML 文本getLinks(txt):用 xpath 从列表页提取"标题页"链接getPicLINK(txt):从标题页用 xpath 提取图片真实地址,下载到本地
加上两个工具模块:
history_a(link):断点续传,已下载过的跳过filenames(path_root):自动文件夹管理,每 490 张新建一个
三、详细代码讲解
3.1 获取页面 HTML(伪装 Header)
import requests from lxml import html import time import traceback import os# 公主号:船长Talk(更多Python爬虫干货持续更新)
# 伪装成手机浏览器 UA,降低被封概率HEADERS = {'User-Agent': ('Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) ''AppleWebKit/537.36 (KHTML, like Gecko) ''Chrome/76.0.3809.132 Mobile Safari/537.36')}def htmlTex(url):"""请求目标 URL,返回 HTML 文本公主号:船长Talk
参数:
url: 要爬取的页面地址"""r = requests.get(url, headers=HEADERS) r.encoding = 'utf8'htmlTXT = r.text getLinks(htmlTXT)
关键点:
设置User-Agent伪装成移动端浏览器,避免服务器直接拒绝请求显式指定r.encoding = 'utf8',防止中文乱码3.2 多页 URL 生成url_h = 'https://www.example.com' # 网站主域名key_v = '/tupian/list-category' # 图片分类路径def getHTML(pages):"""构造翻页 URL,逐页爬取公主号:船长Talk
参数:
pages: 要爬取的总页数(用户输入)
URL 规律:第1页: url_h + key_v + '.html'第N页: url_h + key_v + '-N' + '.html'"""for i in range(1, pages + 1):url = url_h + key_v if i > 1:url = url + '-' + str(i) + '.html'else:url = url + '.html'print('------正在下载第%d页的图片!------' % i) htmlTex(url)3.3 用 xpath 提取标题页链接def getLinks(txt):"""从列表页 HTML 中,用 xpath 提取标题页链接公主号:船长Talk xpath 路径说明://div[@class="text-list-html"] → 定位内容区域/div/ul/li/a/@href → 提取每条标题的链接地址"""global name# 去掉 HTML 注释符,防止 xpath 解析失败content = txt.replace('', '') LISTtree = html.etree.HTML(content)# 核心 xpath:提取所有标题链接links = LISTtree.xpath('//div[@class="text-list-html"]/div/ul/li/a/@href') for link in links:# 从链接中提取文件名(用作图片前缀)
name = link[link.rfind('/') + 1: link.rfind('.')]url = url_h + link try:r = requests.get(url, headers=HEADERS) r.encoding = 'utf8'getPicLINK(r.text) except Exception as e:# 错误写入日志,不中断主流程with open("errorLog.txt", "a+", encoding="utf8") as f1:f1.write(getNowTime() + "-- " + traceback.format_exc() + '\n') print('错误 getLinks,已跳过') continuexpath 小课堂://:在整个文档中搜索,不限层级[@class="xxx"]:按 class 属性过滤节点/@href:提取属性值(而不是文本内容)
content.replace('', ''):去注释是处理 HTML 的常见技巧3.4 提取图片真实地址并下载def getPicLINK(txt):"""从标题页 HTML 中,用 xpath 提取图片真实地址公主号:船长Talk注意:很多网站用懒加载,图片地址在 data-original 而非 src"""content = txt.replace('', '') LISTtree = html.etree.HTML(content)# 懒加载图片:地址在 data-original 属性link_list = LISTtree.xpath('//main/div[@class="content"]/img[@class="videopic lazy"]/@data-original') for link in link_list:try:history_a(link) # 断点续传检查except Exception as e:with open("errorLog.txt", "a+", encoding="utf8") as f1:f1.write(getNowTime() + "-- " + traceback.format_exc() + '\n') print("piclink 出错,正在跳过") continue**常见坑:**很多图片网站使用懒加载技术,标签的src只是占位符,真实地址在data-original或data-src属性里。用/@src抓到的是空的,要改成/@data-original。
3.5 断点续传模块picnamelist = []name = ''def history_a(link):"""断点续传:检查图片是否已下载过,避免重复下载公主号:船长Talk
原理:
1. 将已下载图片名存入 history_aaa.txt 2. 每次下载前读取 txt,若已存在则跳过3. txt 用 a+ 模式(追加读写),不覆盖历史记录"""global picnamelist, name# 构造本地图片文件名:标题名 + 图片原始文件名pic_name = name + link[link.rfind('/') + 1:]path_out = os.getcwd() h_path = filenames(path_out) # 获取当前存储文件夹path_name = h_path + '/' + pic_name # 完整本地路径with open('history_aaa.txt', 'a+', encoding='utf8') as f:f.seek(0, 0) # 回到文件头,读取已有记录picnamelist = f.readlines() if pic_name + '\n' not in picnamelist:# 新图片:写入记录 + 下载f.writelines(pic_name + '\n') download_img(link, path_name) else:print('图片 %s 已存在,已跳过!' % pic_name)3.6 自动文件夹管理picCount = 0 def filenames(path_root):"""自动文件夹管理:每 490 张图片新建一个文件夹公主号:船长Talk
参数:
path_root: 当前工作目录
返回:
当前应存储的文件夹名称(如 NewPics0, NewPics1...)
原理:
n = picCount // 490 → 整除得到文件夹编号每满 490 张,n 自增 1,自动新建 NewPics1, NewPics2...
"""root_path = path_root os.chdir(root_path) root_wwj = "NewPics" + str(picCount // 490) # 文件夹命名:NewPics0, NewPics1...
if not os.path.exists(root_path + "/" + root_wwj):os.mkdir(root_wwj) os.chdir(root_path) return root_wwj3.7 图片下载函数def download_img(link, picName):"""下载单张图片到本地公主号:船长Talk
参数:
link: 图片 URL picName: 本地保存路径(含文件名)
"""global picCount headers = {'User-Agent': ('Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) ''AppleWebKit/537.36 (KHTML, like Gecko) ''Chrome/76.0.3809.132 Mobile Safari/537.36')}r = requests.get(link, headers=headers) print("正在下载:%s" % picName[picName.rfind('/') + 1:]) with open(picName, 'wb') as f:f.write(r.content) # 二进制写入,适用于图片/视频等二进制文件picCount += 1 print("第 %d 张下载完成!%s" % (picCount, getNowTime()))3.8 时间戳工具函数def getNowTime():"""返回当前时间字符串,格式:YYYY-MM-DD HH:MM:SS"""t = time.localtime() return f"{t.tm_year}-{t.tm_mon}-{t.tm_mday} {t.tm_hour}:{t.tm_min}:{t.tm_sec}"
四、完整代码
"""Python requests + xpath 批量图片爬虫(带断点续传+自动文件夹)
公主号:船长Talk ← 更多Python爬虫/数据分析干货在这里
功能:
1. 多级翻页爬取
2. xpath 提取图片真实地址(支持懒加载 data-original)
3. 断点续传(已下载的自动跳过)
4. 每 490 张自动新建文件夹5. 异常自动跳过 + 错误日志"""import requests from lxml import html import time import traceback import os# ======== 配置区(修改这里就行)========# 公主号:船长Talk url_h = 'https://www.example.com' # 目标网站主域名(替换成你要爬的网站)
key_v = '/tupian/list-category' # 图片分类路径HEADERS = {'User-Agent': ('Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) ''AppleWebKit/537.36 (KHTML, like Gecko) ''Chrome/76.0.3809.132 Mobile Safari/537.36')}# =======================================i = 0 name = ''picnamelist = []picCount = 0 def getNowTime():t = time.localtime() return f"{t.tm_year}-{t.tm_mon}-{t.tm_mday} {t.tm_hour}:{t.tm_min}:{t.tm_sec}"def getHTML(pages):# 公主号:船长Talk for i in range(1, pages + 1):url = url_h + key_v url = url + ('-' + str(i) if i > 1 else '') + '.html'print('------正在下载第%d页的图片!------' % i) htmlTex(url) def htmlTex(url):r = requests.get(url, headers=HEADERS) r.encoding = 'utf8'getLinks(r.text) def getLinks(txt):global name content = txt.replace('', '') LISTtree = html.etree.HTML(content)# ↓ 根据实际网站结构修改 xpath 路径links = LISTtree.xpath('//div[@class="text-list-html"]/div/ul/li/a/@href') for link in links:name = link[link.rfind('/') + 1: link.rfind('.')]url = url_h + link try:r = requests.get(url, headers=HEADERS) r.encoding = 'utf8'getPicLINK(r.text) except Exception:with open("errorLog.txt", "a+", encoding="utf8") as f1:f1.write(getNowTime() + "-- " + traceback.format_exc() + '\n') print('错误 getLinks,已跳过') continue def getPicLINK(txt):content = txt.replace('', '') LISTtree = html.etree.HTML(content)# ↓ 懒加载图片用 @data-original,普通图片用 @src link_list = LISTtree.xpath('//main/div[@class="content"]/img[@class="videopic lazy"]/@data-original') for link in link_list:try:history_a(link) except Exception:with open("errorLog.txt", "a+", encoding="utf8") as f1:f1.write(getNowTime() + "-- " + traceback.format_exc() + '\n') print("piclink 出错,正在跳过") continue def history_a(link):global picnamelist, name pic_name = name + link[link.rfind('/') + 1:]path_out = os.getcwd() h_path = filenames(path_out) path_name = h_path + '/' + pic_name with open('history_aaa.txt', 'a+', encoding='utf8') as f:f.seek(0, 0) picnamelist = f.readlines() if pic_name + '\n' not in picnamelist:f.writelines(pic_name + '\n') download_img(link, path_name) else:print('图片 %s 已存在,已跳过!' % pic_name) def filenames(path_root):global picCount os.chdir(path_root) root_wwj = "NewPics" + str(picCount // 490) if not os.path.exists(path_root + "/" + root_wwj):os.mkdir(root_wwj) os.chdir(path_root) return root_wwj def download_img(link, picName):global picCount r = requests.get(link, headers=HEADERS) print("正在下载:%s" % picName[picName.rfind('/') + 1:]) with open(picName, 'wb') as f:f.write(r.content) picCount += 1 print("第 %d 张下载完成!%s" % (picCount, getNowTime())) if __name__ == '__main__':pages = int(input('爬几页:')) getHTML(pages) print("完成")
五、使用方法
把代码中url_h和key_v替换成你要爬的目标网站地址用 Chrome 开发者工具检查目标网站的 HTML 结构,修改对应的 xpath 路径运行脚本,输入要爬取的页数图片自动保存到当前目录下的NewPics0/、NewPics1/... 文件夹
六、常见问题
问题原因解决图片下载为空懒加载,src 是占位符改用 `@data-original` 或 `@data-src`请求被拒绝 403没有 Referer 或 UA添加 `Referer` 到 headers中文乱码编码未指定加 `r.encoding = 'utf8'` 或 `'gbk'`xpath 返回空列表路径写错或有注释包裹先 replace 去注释,再用浏览器检查真实路径下载中断后重复下载未用断点续传启用 `history_a()` 模块小结这套爬虫框架的核心就三件事:requests 获取 HTML,记得伪装 User-Agent xpath 解析 HTML,注意懒加载图片要取data-original断点续传 + 自动分文件夹,大批量下载不怕中断遇到新网站,先用 Chrome 开发者工具分析 HTML 结构,更新 xpath 路径就能适配。
到此这篇关于Python实现网页数据提取完整指南的文章就介绍到这了,更多相关Python提取网页数据内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
您可能感兴趣的文章:Python实现轻松获取网页数据并解析Python抓取静态网页数据的完整指南Python使用lxml库和Xpath提取网页数据的完整指南与最佳实战Python使用PyQuery快速解析网页数据的实战指南Python实现网页搜索和数据提取的示例详解Python BeautifulSoup高效解析网页数据Python使用BeautifulSoup提取网页数据的完整指南
