Python实现网页数据提取完整指南

 更新时间:2026年04月23日 09:30:38   作者:船长Talk  
这篇文章主要为大家详细介绍了Python实现网页数据提取的相关方法,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下

前言

本文手把手带你用 Python requests 库 + 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,已跳过')
            continue

xpath 小课堂:

  • //:在整个文档中搜索,不限层级
  • [@class="xxx"]:按 class 属性过滤节点
  • /@href:提取属性值(而不是文本内容)
  • content.replace('<!--', '').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

**常见坑:**很多图片网站使用懒加载技术,<img> 标签的 src 只是占位符,真实地址在 data-originaldata-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_wwj

3.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_hkey_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模块常用用法实例详解

    由于平时习惯,strftime比较常用,strptime和它是反操作。这篇文章主要介绍了python模块常用用法,需要的朋友可以参考下
    2019-10-10
  • jupyter notebook实现显示行号

    jupyter notebook实现显示行号

    这篇文章主要介绍了jupyter notebook实现显示行号,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-04-04
  • python如何打印杨辉三角及输出第m行第k个数

    python如何打印杨辉三角及输出第m行第k个数

    这篇文章主要介绍了python如何打印杨辉三角及输出第m行第k个数问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • Python中__all__用法及常见误区详解

    Python中__all__用法及常见误区详解

    __all__属性是Python中用来控制模块导入行为的关键工具,它可以帮助你保持代码的整洁和封装性,防止意外地暴露内部实现细节,这篇文章主要介绍了Python中__all__用法及常见误区的相关资料,需要的朋友可以参考下
    2025-12-12
  • 利用rest framework搭建Django API过程解析

    利用rest framework搭建Django API过程解析

    这篇文章主要介绍了利用rest framework搭建Django API过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08
  • python带参数打包exe及调用方式

    python带参数打包exe及调用方式

    今天小编就为大家分享一篇python带参数打包exe及调用方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • pycharm运行pytest中文编码格式错乱解决

    pycharm运行pytest中文编码格式错乱解决

    这篇文章主要为大家介绍了pycharm运行pytest中文编码格式错乱的解决方法,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • PyTorch手写数字数据集进行多分类

    PyTorch手写数字数据集进行多分类

    这篇文章主要介绍了PyTorch手写数字数据集进行多分类,损失函数采用交叉熵,激活函数采用ReLU,优化器采用带有动量的mini-batchSGD算法,需要的朋友可以参考一下
    2022-03-03
  • pandas筛选某列出现编码错误的解决方法

    pandas筛选某列出现编码错误的解决方法

    今天小编就为大家分享一篇pandas筛选某列出现编码错误的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-11-11
  • 使用Python实现写入多类型数据至Excel文件

    使用Python实现写入多类型数据至Excel文件

    Python 凭借其丰富的生态系统,在办公自动化领域展现出显著优势,本文将介绍如何使用 Free Spire.XLS for Python 库,以程序化方式高效、可靠地将多种数据类型写入 Excel 文件,希望对大家有所帮助
    2025-12-12

最新评论