Python利用Requests庫(kù)實(shí)現(xiàn)XML文檔解析并提取摘要
在網(wǎng)絡(luò)爬蟲(chóng)和數(shù)據(jù)采集任務(wù)中,經(jīng)常需要從各種XML源(如RSS訂閱、API響應(yīng)、配置文件)獲取數(shù)據(jù),并對(duì)內(nèi)容進(jìn)行進(jìn)一步處理,例如生成摘要。為了確保程序的穩(wěn)定性和效率,我們需要一個(gè)既能處理網(wǎng)絡(luò)異常又能高效解析的解決方案。
本文詳細(xì)闡述了如何組合requests、urllib3.Retry和lxml構(gòu)建一個(gè)穩(wěn)定高效的XML文檔抓取與摘要流水線(xiàn)。通過(guò)配置重試策略,程序能夠自動(dòng)應(yīng)對(duì)網(wǎng)絡(luò)波動(dòng);利用lxml的高速解析能力,可以快速提取所需數(shù)據(jù);摘要模塊則可以根據(jù)業(yè)務(wù)需求靈活替換。該方案適用于各種需要從XML源獲取信息并進(jìn)行處理的場(chǎng)景,如新聞聚合、內(nèi)容監(jiān)控、數(shù)據(jù)集成等。
本文將詳細(xì)介紹如何利用Python的requests庫(kù)、urllib3的重試機(jī)制以及l(fā)xml庫(kù),組合實(shí)現(xiàn)一個(gè)文檔解析并提取摘要的完整功能。
1.引言
在分布式系統(tǒng)和不穩(wěn)定的網(wǎng)絡(luò)環(huán)境中,HTTP請(qǐng)求可能會(huì)因臨時(shí)故障而失敗。直接使用簡(jiǎn)單的requests.get無(wú)法自動(dòng)處理重試,可能導(dǎo)致采集任務(wù)中斷。同時(shí),XML解析需要高性能和靈活性,以便從復(fù)雜的文檔結(jié)構(gòu)中準(zhǔn)確提取目標(biāo)數(shù)據(jù)。本文提出的方案通過(guò)以下組件解決這些問(wèn)題:
- requests:簡(jiǎn)潔易用的HTTP客戶(hù)端,負(fù)責(zé)發(fā)起請(qǐng)求。
- urllib3.util.Retry:提供可配置的重試策略,包括重試次數(shù)、狀態(tài)碼和異常類(lèi)型。
- requests.adapters.HTTPAdapter:將重試策略?huà)燧d到requests.Session,使所有請(qǐng)求自動(dòng)具備重試能力。
- lxml.etree:高性能XML解析庫(kù),支持XPath等查詢(xún)方式,快速提取數(shù)據(jù)。
- 下游摘要模塊:對(duì)提取的文本進(jìn)行摘要處理,可根據(jù)需求替換為簡(jiǎn)單截?cái)嗷驈?fù)雜算法。
通過(guò)有機(jī)組合這些工具,我們可以構(gòu)建一個(gè)健壯、高效的文檔處理流水線(xiàn)。
2.組件介紹
2.1 requests 與 HTTPAdapter
requests是Python中最受歡迎的HTTP庫(kù),它封裝了底層的urllib3,提供了直觀(guān)的API。requests.adapters.HTTPAdapter是requests的核心適配器,負(fù)責(zé)將HTTP請(qǐng)求發(fā)送到服務(wù)器。我們可以通過(guò)自定義適配器來(lái)配置連接池大小、重試策略等。
2.2 urllib3.util.Retry
urllib3是requests依賴(lài)的底層庫(kù),其util.Retry類(lèi)定義了重試行為。我們可以設(shè)置:
- total:最大重試次數(shù)(包括連接和讀取重試)。
- connect:連接失敗時(shí)的重試次數(shù)。
- read:讀取失敗時(shí)的重試次數(shù)。
- status_forcelist:觸發(fā)重試的HTTP狀態(tài)碼列表(如500、502、503、504)。
- backoff_factor:退避因子,用于計(jì)算重試間隔(間隔 = backoff_factor * (2^(重試次數(shù)-1)))。
- allowed_methods:允許重試的HTTP方法(如GET、POST)。
2.3 lxml.etree
lxml是Python中功能最豐富、速度最快的XML/HTML處理庫(kù)之一。etree.fromstring可以將字節(jié)串或字符串解析為Element對(duì)象,之后可使用XPath、CSS選擇器或遍歷元素的方法提取數(shù)據(jù)。它底層使用C語(yǔ)言庫(kù)libxml2,性能極佳。
2.4 摘要模塊
“下游摘要”指對(duì)提取的文本進(jìn)行縮減,生成簡(jiǎn)潔的摘要。摘要算法可以是:
- 簡(jiǎn)單截?cái)啵喊淳渥踊蜃址麛?shù)截取開(kāi)頭部分。
- 統(tǒng)計(jì)方法:如TextRank、詞頻統(tǒng)計(jì)。
- 深度學(xué)習(xí)方法:如使用預(yù)訓(xùn)練模型(BERT、T5)生成抽象摘要。
本文示例將使用簡(jiǎn)單的句子截?cái)啵x者可以輕松替換為任何高級(jí)摘要庫(kù)。
3.原理與設(shè)計(jì)
整個(gè)流水線(xiàn)的核心流程如下:
- 配置重試策略:創(chuàng)建urllib3.util.Retry對(duì)象,定義重試參數(shù)。
- 創(chuàng)建適配器:實(shí)例化requests.adapters.HTTPAdapter,傳入重試對(duì)象。
- 掛載適配器:將適配器掛載到requests.Session的http://和https://前綴,使會(huì)話(huà)中的所有請(qǐng)求自動(dòng)應(yīng)用重試邏輯。
- 發(fā)起請(qǐng)求:使用會(huì)話(huà)的get方法獲取XML文檔,設(shè)置超時(shí)時(shí)間。
- 異常處理:捕獲網(wǎng)絡(luò)異常(如超時(shí)、連接錯(cuò)誤)并記錄日志。
- 解析XML:使用lxml.etree.fromstring解析響應(yīng)內(nèi)容(使用response.content以字節(jié)形式處理,避免編碼問(wèn)題)。
- 提取數(shù)據(jù):通過(guò)XPath從解析樹(shù)中提取需要摘要的文本。
- 生成摘要:將提取的文本送入摘要函數(shù),得到最終結(jié)果。
- 返回或存儲(chǔ):將摘要返回給調(diào)用方或?qū)懭氪鎯?chǔ)系統(tǒng)。
這種設(shè)計(jì)將網(wǎng)絡(luò)容錯(cuò)、數(shù)據(jù)解析和業(yè)務(wù)邏輯解耦,便于維護(hù)和擴(kuò)展。
4.具體實(shí)現(xiàn)
4.1 安裝依賴(lài)
確保已安裝所需庫(kù):
pip install requests lxml
urllib3通常隨requests自動(dòng)安裝,無(wú)需單獨(dú)安裝。
4.2 創(chuàng)建帶重試的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)):
"""
創(chuàng)建一個(gè)帶有重試機(jī)制的requests Session。
:param retries: 最大重試次數(shù)
:param backoff_factor: 退避因子
:param status_forcelist: 觸發(fā)重試的HTTP狀態(tài)碼
:return: requests.Session對(duì)象
"""
session = requests.Session()
retry = Retry(
total=retries,
read=retries,
connect=retries,
backoff_factor=backoff_factor,
status_forcelist=status_forcelist,
allowed_methods=["GET"], # 只對(duì)GET請(qǐng)求重試
raise_on_status=False
)
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)
return session
4.3 定義摘要函數(shù)
這里實(shí)現(xiàn)一個(gè)簡(jiǎn)單的基于句子分割的摘要函數(shù):
import re
def simple_summarize(text, max_sentences=2):
"""
極簡(jiǎn)摘要:按中文或英文句號(hào)、感嘆號(hào)、問(wèn)號(hào)分割句子,取前max_sentences句。
注意:實(shí)際應(yīng)用中可替換為更復(fù)雜的算法。
"""
if not text:
return ""
# 分割句子,保留標(biāo)點(diǎn)
sentences = re.split(r'(?<=[。???!?])\s*', text.strip())
summary = ''.join(sentences[:max_sentences])
return summary
4.4 核心函數(shù):獲取文檔、解析并摘要
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表達(dá)式(應(yīng)返回字符串列表)
:param max_sentences: 摘要的最大句子數(shù)
:param timeout: 請(qǐng)求超時(shí)時(shí)間(秒)
:return: 摘要字符串,失敗時(shí)返回None
"""
session = create_retry_session()
try:
response = session.get(url, timeout=timeout)
response.raise_for_status() # 觸發(fā)HTTPError異常(4xx或5xx)
except requests.exceptions.RequestException as e:
logging.error(f"請(qǐng)求失敗: {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("未找到匹配文本,無(wú)法生成摘要")
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中提取每篇文章的標(biāo)題和描述,并為每篇文章生成摘要。假設(shè)RSS可能包含命名空間,我們使用local-name()來(lái)忽略命名空間。
import logging
from lxml import etree
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def process_rss_item(item):
"""處理單個(gè)RSS條目,返回標(biāo)題和摘要"""
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" # 替換為實(shí)際RSS地址
session = create_retry_session()
try:
resp = session.get(rss_url, timeout=15)
resp.raise_for_status()
except Exception as e:
logging.error(f"請(qǐng)求RSS失敗: {e}")
return
# 解析XML
try:
root = etree.fromstring(resp.content)
except etree.XMLSyntaxError as e:
logging.error(f"XML解析錯(cuò)誤: {e}")
return
# 查找所有item元素(忽略命名空間)
items = root.xpath("http://*[local-name()='item']")
if not items:
# 嘗試另一種路徑:channel下的item
items = root.xpath("http://*[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"標(biāo)題: {result['title']}")
print(f"摘要: {result['summary']}")
print("-" * 50)
if __name__ == "__main__":
main()
4.6 處理命名空間的說(shuō)明
許多XML(如RSS 2.0)帶有默認(rèn)命名空間,例如:
<rss version="2.0" xmlns="http://purl.org/rss/1.0/">
此時(shí)直接使用//item無(wú)法匹配,因?yàn)樵孛诿臻g內(nèi)。解決方案:
- 使用local-name()://*[local-name()=‘item’] 匹配所有本地名為item的元素。
- 注冊(cè)命名空間前綴:使用etree.register_namespace或xpath的namespaces參數(shù)。
示例:
namespaces = {'rss': 'http://purl.org/rss/1.0/'}
items = root.xpath('//rss:item', namespaces=namespaces)
5.擴(kuò)展與優(yōu)化
5.1 更復(fù)雜的摘要算法
若需要高質(zhì)量摘要,可集成第三方庫(kù):
- sumy:提供多種摘要算法(LSA、TextRank、LexRank等)。
- transformers:使用Hugging Face的預(yù)訓(xùn)練模型生成抽象摘要。
示例(使用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 配置化
將重試參數(shù)、XPath表達(dá)式、摘要方式等抽取為配置文件,提高靈活性。
5.3 錯(cuò)誤處理與日志
除了網(wǎng)絡(luò)異常和解析異常,還應(yīng)考慮:
- 響應(yīng)內(nèi)容為空或非XML格式。
- XPath返回空列表。
- 摘要函數(shù)處理超長(zhǎng)文本。
使用logging模塊記錄關(guān)鍵步驟和異常,便于問(wèn)題排查。
5.4 性能調(diào)優(yōu)
連接池:HTTPAdapter默認(rèn)維護(hù)連接池,可通過(guò)pool_connections和pool_maxsize參數(shù)調(diào)整。
流式解析:對(duì)于超大XML,可使用iterparse逐塊解析,避免內(nèi)存爆炸。
到此這篇關(guān)于Python利用Requests庫(kù)實(shí)現(xiàn)XML文檔解析并提取摘要的文章就介紹到這了,更多相關(guān)Python Requests解析XML內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解python ThreadPoolExecutor異常捕獲
本文主要介紹了詳解python ThreadPoolExecutor異常捕獲,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01
如何使用django-treebeard實(shí)現(xiàn)樹(shù)類(lèi)型存儲(chǔ)與編輯
這篇文章主要介紹了使用django-treebeard實(shí)現(xiàn)樹(shù)類(lèi)型存儲(chǔ)與編輯的宣相關(guān)操作代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-08-08
Python?Pandas使用merge函數(shù)進(jìn)行數(shù)據(jù)合并的操作代碼
在數(shù)據(jù)處理和分析中,經(jīng)常需要將不同數(shù)據(jù)源的數(shù)據(jù)進(jìn)行合并,以便進(jìn)行更深入的分析和挖掘,Python的Pandas庫(kù)提供了豐富的函數(shù)來(lái)進(jìn)行數(shù)據(jù)合并操作,其中merge()函數(shù)是其中之一,本文將深入探討Python?Pandas中的merge()函數(shù)的用法,需要的朋友可以參考下2025-12-12
Python數(shù)據(jù)結(jié)構(gòu)與算法中的隊(duì)列詳解(1)
這篇文章主要為大家詳細(xì)介紹了Python的隊(duì)列,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03
Python參數(shù)解析器configparser簡(jiǎn)介
configparser是python自帶的配置參數(shù)解析器,可以用于解析.config文件中的配置參數(shù),ini文件中由sections(節(jié)點(diǎn))-key-value組成,這篇文章主要介紹了Python參數(shù)解析器configparser,需要的朋友可以參考下2022-12-12
Python實(shí)現(xiàn)的尋找前5個(gè)默尼森數(shù)算法示例
這篇文章主要介紹了Python實(shí)現(xiàn)的尋找前5個(gè)默尼森數(shù)算法,簡(jiǎn)單講述了默尼森數(shù)的概念,并結(jié)合實(shí)例形式分析了Python求解默尼森數(shù)算法的相關(guān)操作技巧,需要的朋友可以參考下2018-03-03
如何在keras中添加自己的優(yōu)化器(如adam等)
這篇文章主要介紹了在keras中實(shí)現(xiàn)添加自己的優(yōu)化器(如adam等)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-06-06

