编程学习网 > 编程语言 > Python > Python网络爬虫四大选择器(正则表达式、BS4、Xpath、CSS)总结!
2026
11-03

Python网络爬虫四大选择器(正则表达式、BS4、Xpath、CSS)总结!


爬虫代码里有一个地方特别容易写着写着失控,就是解析 HTML。

刚开始写爬虫的时候,很多人看到网页源码,第一反应就是正则。

一个 re.findall(),感觉天下无敌。

后来遇到动态页面、标签嵌套、属性变化,再换 BeautifulSoup。

再后来项目复杂一点,又开始用 XPath、CSS Selector。

其实这几个工具没有谁一定替代谁,我平时写爬虫时,更关注一个问题:

这个页面的数据结构稳定不稳定?我要抓的是一个字符串,还是一个节点?

选择器选错了,后面维护起来会非常痛苦。

比如一个新闻列表页面:

<div class="article">
    <h2>Python性能优化实战</h2>
    <span class="author">东哥</span>
    <p>今天排查一个线上脚本问题...</p>
</div>

目标是拿标题、作者、摘要。

不同选择器写出来完全是两种思路。


正则表达式,适合简单、固定格式的数据提取。

很多新人喜欢正则,因为它直接。

看到:

<span class="price">99.8</span>

直接:

import re
html = """
<span class="price">99.8</span>
"""
price = re.findall(r'<span class="price">(.*?)</span>', html)
print(price)

输出:

['99.8']

很爽。

但是爬虫项目里,HTML 很少这么听话。

比如价格节点改成:

<span class="price">
    99.8
</span>

中间多了换行和空格,正则可能直接失效。

再比如:

<div class="goods">
    <span class="price">99.8</span>
    <span class="old-price">199</span>
</div>

你想拿第一个价格,还得继续调整表达式。

所以我的习惯是:

正则只负责处理文本,不负责解析 HTML 结构。

比如抓取页面里的手机号、订单号、特殊编码,这种场景非常合适。

例如处理爬下来的文章内容:

import re
content = """
用户联系电话:
13800138000
"""
phones = re.findall(r'1[3-9]\d{9}', content)
print(phones)

这种事情交给正则,比引入 HTML 解析库舒服很多。


BeautifulSoup(BS4)更像一个 HTML 检查员。

它不会让你关心标签层级,只需要告诉它:

我要找什么。

安装:

pip install beautifulsoup4

简单示例:

from bs4 import BeautifulSoup
html = """
<div class="article">
    <h2>Python爬虫选择器</h2>
    <span class="author">东哥</span>
</div>
"""
soup = BeautifulSoup(html, "html.parser")
title = soup.find("h2").text
author = soup.find("span", class_="author").text
print(title)
print(author)

结果:

Python爬虫选择器
东哥

BS4 最大的优点是代码可读性高。

实际项目里面,我经常用它处理结构不是特别复杂的页面。

比如:

博客文章列表

简单资讯网站

表格数据

商品信息页

但是 BS4 有一个问题。

速度不是最快。

因为它需要把整个 HTML 转成对象树。

页面小没关系。

如果你一天跑几十万个页面,这里就需要考虑性能。


XPath 是我在复杂页面里最常用的。

原因很简单:

它定位精准。

尤其是遇到这种结构:

<div id="content">
    <ul>
        <li>
            <a href="/news/1">文章1</a>
        </li>
        <li>
            <a href="/news/2">文章2</a>
        </li>
    </ul>
</div>

我要拿所有文章链接。

XPath:

from lxml import etree
html = """
<div id="content">
    <ul>
        <li><a href="/news/1">文章1</a></li>
        <li><a href="/news/2">文章2</a></li>
    </ul>
</div>
"""
tree = etree.HTML(html)
links = tree.xpath('//div[@id="content"]//a/@href')
print(links)

输出:

['/news/1', '/news/2']

XPath 的优势:

可以按照层级找。

比如:

//div[@class="box"]/ul/li[1]/a/text()

意思是:

找到 box 下面 ul 的第一个 li 里的 a 标签文本。

页面结构复杂的时候,这种定位方式非常省时间。

我排查爬虫问题时,经常看到有人写:

//div/div/div/span

这种 XPath。

能跑,但是非常脆。

网页加一层 div,直接废。

实际项目里,我更喜欢带属性:

//div[@class='product']//span[@class='price']/text()

不要过度依赖层级。


CSS Selector 对前端开发人员比较友好。

因为和 CSS 写法接近。

比如:

<div class="product">
    <span class="name">机械键盘</span>
</div>

选择:

from bs4 import BeautifulSoup
html = """
<div class="product">
    <span class="name">机械键盘</span>
</div>
"""
soup = BeautifulSoup(html, "html.parser")
name = soup.select_one(".product .name").text
print(name)

输出:

机械键盘

常见写法:

类:

.product

ID:

#main

标签:

div span

属性:

input[type='text']

CSS Selector 最大的问题是:

复杂定位能力没有 XPath 强。

比如:

找第三个节点:

XPath:

//ul/li[3]

CSS:

ul li:nth-child(3)

也可以,但是复杂条件组合起来,XPath 更舒服。


我自己实际选择,大概是这样。

页面结构简单:

BS4。

比如:

soup.find_all("a")

够用了。

页面结构复杂:

XPath。

尤其是 Scrapy 项目。

比如:

response.xpath(
    "//div[@class='item']/a/@href"
).getall()

这种写起来很快。

数据只是文本:

正则。

比如:

re.findall(
    r'\d{4}-\d{2}-\d{2}',
    text
)

处理日期、编号非常合适。

前端结构比较规范:

CSS Selector。

比如:

soup.select(".news-item .title")

维护成本低。


还有一个实际踩坑点。

不要把选择器写死。

很多爬虫挂掉,不是因为代码错误,而是页面稍微调整了一下。

比如:

以前:

title = tree.xpath(
    "//h1[@class='title']/text()"
)

后来网站改成:

<h1 class="article-title">

全部失效。

更稳一点:

title = tree.xpath(
    "//h1[contains(@class,'title')]/text()"
)

至少兼容部分变化。


最后总结一下:

正则不是不能用,只是不要拿它硬解析 HTML。

BS4 上手最快,适合大多数简单页面。

XPath 定位能力强,复杂页面效率最高。

CSS Selector 写法舒服,适合熟悉前端的人。

真正做爬虫项目,不是谁代码短谁厉害,而是谁写的解析规则能扛住页面变化。

我一般看到一个网页,不会马上敲代码。

先打开开发者工具,看 DOM 结构。

确定数据在哪一层。

再决定用哪个选择器。

这个顺序反过来,后面基本就是不停修补。

以上就是“Python网络爬虫四大选择器(正则表达式、BS4、Xpath、CSS)总结!”的详细内容,想要了解更多Python教程欢迎持续关注编程学习网。 

扫码二维码 获取免费视频学习资料

Python编程学习

查 看2022高级编程视频教程免费获取