尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Python爬虫必备:用lxml和XPath快速抓取网页数据的5个实战技巧

Python爬虫必备:用lxml和XPath快速抓取网页数据的5个实战技巧 Python爬虫实战用lxml和XPath解决5个数据抓取难题当我们需要从网页中提取结构化数据时lxml库配合XPath语法无疑是Python生态中最强大的组合之一。不同于简单的示例演示本文将聚焦实际爬虫项目中常见的5个痛点场景通过电商价格抓取、新闻标题提取等真实案例展示如何高效解决动态class匹配、多属性筛选等技术难题。1. 动态class的精准匹配策略电商网站经常使用动态生成的class属性来防止爬虫比如classproduct-item-12345这样的随机字符串。直接匹配完整class显然不可行这时就需要使用XPath的contains()函数from lxml import html import requests # 抓取京东商品列表页 url https://search.jd.com/Search?keyword手机 response requests.get(url) tree html.fromstring(response.text) # 使用contains匹配部分class名 products tree.xpath(//div[contains(class, product-item-)]) for product in products: price product.xpath(.//strong[classprice]/text())[0] print(f价格: {price})更复杂的场景下可以组合多个条件# 同时匹配class包含product且data-type为item的元素 products tree.xpath(//div[contains(class,product) and data-typeitem])提示当class属性包含多个值时使用contains()比直接匹配更可靠因为class的顺序可能变化但部分名称保持不变。2. 多属性联合筛选技巧新闻网站的文章列表项通常会有多个特征属性这时就需要使用多条件筛选。以新浪新闻为例# 新浪新闻列表页示例 news_list tree.xpath( //div[classnews-item and data-sudaclicknews_content] ) # 更复杂的多属性筛选 important_news tree.xpath( //div[classnews-item and data-levelA and not(contains(style,display:none))] )对于需要同时满足多个属性的元素可以使用and连接多个条件。表格展示了常见多属性组合场景场景XPath示例说明必须属性[A and B]同时具有A和B属性排除属性[not(disabled)]排除有disabled属性的元素值范围[price100]数值型属性筛选文本组合[text()[contains(.,特价)]]文本内容包含特定关键词3. 相对路径定位的妙用当需要基于某个基准元素查找其子元素时相对路径能大幅提高定位精度。以知乎回答内容抓取为例answers tree.xpath(//div[classAnswerItem]) for answer in answers: # 相对于当前answer元素查找 author answer.xpath(.//a[classAuthorInfo-name]/text())[0] content answer.xpath(.//div[classRichContent-inner]//text()) print(f{author}: {.join(content)[:50]}...)关键点在于路径开头的点号(.)它表示从当前节点而非根节点开始查找。对比以下两种写法# 错误写法会从根节点重新查找 author answer.xpath(//a[classAuthorInfo-name]/text()) # 正确写法从answer节点开始查找 author answer.xpath(.//a[classAuthorInfo-name]/text())4. 文本提取的优化方案原始HTML中的文本经常被各种标签分割直接提取会导致内容碎片化。以下是几种优化方案方案一合并文本碎片# 提取所有文本节点并合并 content .join(tree.xpath(//div[idarticle]//text()))方案二保留段落结构paragraphs tree.xpath(//div[idarticle]/p) for p in paragraphs: print(.join(p.xpath(.//text())))方案三处理特殊空白字符import re text .join(tree.xpath(//div[classcontent]//text())) clean_text re.sub(r\s, , text).strip()对于包含换行和缩进的复杂文本可以使用normalize-space()函数# 自动处理多余空白字符 clean_text tree.xpath(normalize-space(//div[classcontent]))5. 健壮的异常处理机制实际爬虫项目中网页结构变化是常态。完善的异常处理能让爬虫更健壮from lxml.etree import XMLSyntaxError def safe_extract(tree, xpath, defaultNone): try: result tree.xpath(xpath) return result[0] if result else default except (IndexError, XMLSyntaxError) as e: print(fXPath提取失败: {e}) return default # 使用示例 price safe_extract(tree, //span[classprice]/text(), 0)对于可能缺失的字段可以预先检查product { name: safe_extract(tree, .//h3/text()), price: safe_extract(tree, .//span[contains(class,price)]/text()), stock: 有货 if tree.xpath(.//button[not(contains(class,disabled))]) else 缺货 }针对不同的异常情况建议采用分级处理策略元素不存在返回默认值或跳过网络请求失败重试机制页面结构变化触发告警通知反爬限制自动切换代理或暂停最后分享一个实战技巧在编写XPath时可以先用浏览器开发者工具测试表达式。Chrome的Copy XPath功能虽然方便但生成的路径往往过于脆弱建议手动优化为更简洁的相对路径。
返回列表