Python利用Requests库实现XML文档解析并提取摘要

 更新时间:2026年03月16日 08:38:13   作者:weixin_30777913  
本文详细阐述了如何组合requests、urllib3.Retry和lxml构建一个稳定高效的XML文档抓取与摘要流水线,文中的示例代码讲解详细,有需要的小伙伴可以了解下

在网络爬虫和数据采集任务中,经常需要从各种XML源(如RSS订阅、API响应、配置文件)获取数据,并对内容进行进一步处理,例如生成摘要。为了确保程序的稳定性和效率,我们需要一个既能处理网络异常又能高效解析的解决方案。

本文详细阐述了如何组合requests、urllib3.Retry和lxml构建一个稳定高效的XML文档抓取与摘要流水线。通过配置重试策略,程序能够自动应对网络波动;利用lxml的高速解析能力,可以快速提取所需数据;摘要模块则可以根据业务需求灵活替换。该方案适用于各种需要从XML源获取信息并进行处理的场景,如新闻聚合、内容监控、数据集成等。

本文将详细介绍如何利用Python的requests库、urllib3的重试机制以及lxml库,组合实现一个文档解析并提取摘要的完整功能。

1.引言

在分布式系统和不稳定的网络环境中,HTTP请求可能会因临时故障而失败。直接使用简单的requests.get无法自动处理重试,可能导致采集任务中断。同时,XML解析需要高性能和灵活性,以便从复杂的文档结构中准确提取目标数据。本文提出的方案通过以下组件解决这些问题:

  • requests:简洁易用的HTTP客户端,负责发起请求。
  • urllib3.util.Retry:提供可配置的重试策略,包括重试次数、状态码和异常类型。
  • requests.adapters.HTTPAdapter:将重试策略挂载到requests.Session,使所有请求自动具备重试能力。
  • lxml.etree:高性能XML解析库,支持XPath等查询方式,快速提取数据。
  • 下游摘要模块:对提取的文本进行摘要处理,可根据需求替换为简单截断或复杂算法。

通过有机组合这些工具,我们可以构建一个健壮、高效的文档处理流水线。

2.组件介绍

2.1 requests 与 HTTPAdapter

requests是Python中最受欢迎的HTTP库,它封装了底层的urllib3,提供了直观的API。requests.adapters.HTTPAdapter是requests的核心适配器,负责将HTTP请求发送到服务器。我们可以通过自定义适配器来配置连接池大小、重试策略等。

2.2 urllib3.util.Retry

urllib3是requests依赖的底层库,其util.Retry类定义了重试行为。我们可以设置:

  • total:最大重试次数(包括连接和读取重试)。
  • connect:连接失败时的重试次数。
  • read:读取失败时的重试次数。
  • status_forcelist:触发重试的HTTP状态码列表(如500、502、503、504)。
  • backoff_factor:退避因子,用于计算重试间隔(间隔 = backoff_factor * (2^(重试次数-1)))。
  • allowed_methods:允许重试的HTTP方法(如GET、POST)。

2.3 lxml.etree

lxml是Python中功能最丰富、速度最快的XML/HTML处理库之一。etree.fromstring可以将字节串或字符串解析为Element对象,之后可使用XPath、CSS选择器或遍历元素的方法提取数据。它底层使用C语言库libxml2,性能极佳。

2.4 摘要模块

“下游摘要”指对提取的文本进行缩减,生成简洁的摘要。摘要算法可以是:

  • 简单截断:按句子或字符数截取开头部分。
  • 统计方法:如TextRank、词频统计。
  • 深度学习方法:如使用预训练模型(BERT、T5)生成抽象摘要。

本文示例将使用简单的句子截断,但读者可以轻松替换为任何高级摘要库。

3.原理与设计

整个流水线的核心流程如下:

  • 配置重试策略:创建urllib3.util.Retry对象,定义重试参数。
  • 创建适配器:实例化requests.adapters.HTTPAdapter,传入重试对象。
  • 挂载适配器:将适配器挂载到requests.Session的http://和https://前缀,使会话中的所有请求自动应用重试逻辑。
  • 发起请求:使用会话的get方法获取XML文档,设置超时时间。
  • 异常处理:捕获网络异常(如超时、连接错误)并记录日志。
  • 解析XML:使用lxml.etree.fromstring解析响应内容(使用response.content以字节形式处理,避免编码问题)。
  • 提取数据:通过XPath从解析树中提取需要摘要的文本。
  • 生成摘要:将提取的文本送入摘要函数,得到最终结果。
  • 返回或存储:将摘要返回给调用方或写入存储系统。

这种设计将网络容错、数据解析和业务逻辑解耦,便于维护和扩展。

4.具体实现

4.1 安装依赖

确保已安装所需库:

pip install requests lxml

urllib3通常随requests自动安装,无需单独安装。

4.2 创建带重试的Session

import requests
from requests.adapters import HTTPAdapter
from urllib3.util import Retry

def create_retry_session(retries=3, backoff_factor=0.3, status_forcelist=(500, 502, 504)):
    """
    创建一个带有重试机制的requests Session。
    :param retries: 最大重试次数
    :param backoff_factor: 退避因子
    :param status_forcelist: 触发重试的HTTP状态码
    :return: requests.Session对象
    """
    session = requests.Session()
    retry = Retry(
        total=retries,
        read=retries,
        connect=retries,
        backoff_factor=backoff_factor,
        status_forcelist=status_forcelist,
        allowed_methods=["GET"],  # 只对GET请求重试
        raise_on_status=False
    )
    adapter = HTTPAdapter(max_retries=retry)
    session.mount('http://', adapter)
    session.mount('https://', adapter)
    return session

4.3 定义摘要函数

这里实现一个简单的基于句子分割的摘要函数:

import re

def simple_summarize(text, max_sentences=2):
    """
    极简摘要:按中文或英文句号、感叹号、问号分割句子,取前max_sentences句。
    注意:实际应用中可替换为更复杂的算法。
    """
    if not text:
        return ""
    # 分割句子,保留标点
    sentences = re.split(r'(?<=[。!?!?])\s*', text.strip())
    summary = ''.join(sentences[:max_sentences])
    return summary

4.4 核心函数:获取文档、解析并摘要

def fetch_and_summarize_xml(url, xpath_for_text, max_sentences=2, timeout=10):
    """
    获取XML文档,提取指定XPath的文本,生成摘要。
    :param url: XML文档URL
    :param xpath_for_text: 用于提取待摘要文本的XPath表达式(应返回字符串列表)
    :param max_sentences: 摘要的最大句子数
    :param timeout: 请求超时时间(秒)
    :return: 摘要字符串,失败时返回None
    """
    session = create_retry_session()
    try:
        response = session.get(url, timeout=timeout)
        response.raise_for_status()  # 触发HTTPError异常(4xx或5xx)
    except requests.exceptions.RequestException as e:
        logging.error(f"请求失败: {e}")
        return None

    # 解析XML
    try:
        root = etree.fromstring(response.content)
    except etree.XMLSyntaxError as e:
        logging.error(f"XML解析失败: {e}")
        return None

    # 提取文本
    text_parts = root.xpath(xpath_for_text)
    if not text_parts:
        logging.warning("未找到匹配文本,无法生成摘要")
        return ""

    full_text = ' '.join(text_parts).strip()
    if not full_text:
        return ""

    # 生成摘要
    summary = simple_summarize(full_text, max_sentences)
    return summary

4.5 完整示例:处理RSS feed

以下示例演示如何从RSS feed中提取每篇文章的标题和描述,并为每篇文章生成摘要。假设RSS可能包含命名空间,我们使用local-name()来忽略命名空间。

import logging
from lxml import etree

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

def process_rss_item(item):
    """处理单个RSS条目,返回标题和摘要"""
    title = item.findtext('title', default='')
    description = item.findtext('description', default='')
    full_text = f"{title} {description}".strip()
    if not full_text:
        return None
    summary = simple_summarize(full_text, max_sentences=2)
    return {'title': title, 'summary': summary}

def main():
    rss_url = "https://example.com/feed.xml"  # 替换为实际RSS地址
    session = create_retry_session()

    try:
        resp = session.get(rss_url, timeout=15)
        resp.raise_for_status()
    except Exception as e:
        logging.error(f"请求RSS失败: {e}")
        return

    # 解析XML
    try:
        root = etree.fromstring(resp.content)
    except etree.XMLSyntaxError as e:
        logging.error(f"XML解析错误: {e}")
        return

    # 查找所有item元素(忽略命名空间)
    items = root.xpath("//*[local-name()='item']")
    if not items:
        # 尝试另一种路径:channel下的item
        items = root.xpath("//*[local-name()='channel']/*[local-name()='item']")

    if not items:
        logging.warning("未找到任何item元素")
        return

    for item in items:
        result = process_rss_item(item)
        if result:
            print(f"标题: {result['title']}")
            print(f"摘要: {result['summary']}")
            print("-" * 50)

if __name__ == "__main__":
    main()

4.6 处理命名空间的说明

许多XML(如RSS 2.0)带有默认命名空间,例如:

<rss version="2.0" xmlns="http://purl.org/rss/1.0/">

此时直接使用//item无法匹配,因为元素名在命名空间内。解决方案:

  • 使用local-name()://*[local-name()=‘item’] 匹配所有本地名为item的元素。
  • 注册命名空间前缀:使用etree.register_namespace或xpath的namespaces参数。

示例:

namespaces = {'rss': 'http://purl.org/rss/1.0/'}
items = root.xpath('//rss:item', namespaces=namespaces)

5.扩展与优化

5.1 更复杂的摘要算法

若需要高质量摘要,可集成第三方库:

  • sumy:提供多种摘要算法(LSA、TextRank、LexRank等)。
  • transformers:使用Hugging Face的预训练模型生成抽象摘要。

示例(使用transformers):

from transformers import pipeline

summarizer = pipeline("summarization", model="facebook/bart-large-cnn")

def summarize_with_transformers(text):
    result = summarizer(text, max_length=50, min_length=10, do_sample=False)
    return result[0]['summary_text']

5.2 配置化

将重试参数、XPath表达式、摘要方式等抽取为配置文件,提高灵活性。

5.3 错误处理与日志

除了网络异常和解析异常,还应考虑:

  • 响应内容为空或非XML格式。
  • XPath返回空列表。
  • 摘要函数处理超长文本。

使用logging模块记录关键步骤和异常,便于问题排查。

5.4 性能调优

连接池:HTTPAdapter默认维护连接池,可通过pool_connections和pool_maxsize参数调整。

流式解析:对于超大XML,可使用iterparse逐块解析,避免内存爆炸。

到此这篇关于Python利用Requests库实现XML文档解析并提取摘要的文章就介绍到这了,更多相关Python Requests解析XML内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python单例模式实例分析

    Python单例模式实例分析

    这篇文章主要介绍了Python单例模式,以实例形式分析了Python单例模式的具体使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-01-01
  • Python实现上下文管理器的示例代码

    Python实现上下文管理器的示例代码

    这篇文章主要为大家详细介绍了Python中实现上下文管理器的具体方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下
    2023-07-07
  • python实现控制电脑鼠标和键盘,登录QQ的方法示例

    python实现控制电脑鼠标和键盘,登录QQ的方法示例

    这篇文章主要介绍了python实现控制电脑鼠标和键盘,登录QQ的方法,涉及Python基于Button,Controller,Key模块针对键盘、鼠标的控制相关操作技巧,需要的朋友可以参考下
    2019-07-07
  • 用Python每天自动给女友免费发短信

    用Python每天自动给女友免费发短信

    大家好,本篇文章主要讲的是用Python每天自动给女友免费发短信,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • 解决python 执行shell命令无法获取返回值的问题

    解决python 执行shell命令无法获取返回值的问题

    这篇文章主要介绍了解决python 执行shell命令无法获取返回值的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Django实现网页分页功能

    Django实现网页分页功能

    这篇文章主要介绍了Django实现网页分页功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-10-10
  • 详解使用django-mama-cas快速搭建CAS服务的实现

    详解使用django-mama-cas快速搭建CAS服务的实现

    这篇文章主要介绍了详解使用django-mama-cas快速搭建CAS服务的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • 用代码帮你了解Python基础(2)

    用代码帮你了解Python基础(2)

    这篇文章主要用代码帮你了解Python基础,使用列表,元组和条件判断的示例代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • Python PyQt5实现拖放效果的原理详解

    Python PyQt5实现拖放效果的原理详解

    这篇文章主要为大家详细介绍了Python PyQt5中拖放效果的实现原理与实现代码,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2022-11-11
  • MediaPipe API实现骨骼识别功能分步讲解流程

    MediaPipe API实现骨骼识别功能分步讲解流程

    MediaPipe是用于构建多模态(例如视频、音频或任何时间序列数据)、跨平台(即eAndroid、IOS、web、边缘设备)应用ML管道的框架。这篇文章主要介绍了MediaPipe API实现骨骼识别功能分步流程
    2022-09-09

最新评论