找回密码
立即注册
搜索
发回帖 发新帖

6368

积分

0

好友

805

主题
发表于 昨天 21:22 | 查看: 8| 回复: 0

爬虫代码里,真正让人纠结的往往不是请求发不出去。

requests.get() 写完,页面拿到了,剩下的问题基本都会落到一个地方:

这一堆 HTML,我到底怎么把想要的数据抠出来?

刚开始写爬虫的时候,我也是正则一把梭。

看到页面源码:

<div class="product">
  <h2>机械键盘</h2>
  <span class="price">299</span>
</div>

第一反应:"这不就是几个标签嘛,正则搞一下。"

结果线上跑一晚上,第二天发现采集数量少了一半。

原因很简单,网页结构稍微变一下,正则表达式直接失效。

后来慢慢发现,爬虫里的选择器没有绝对好坏,更多是看场景。

简单文本,用正则。结构化 HTML,用 BS4。层级复杂,XPath。前端页面喜欢动态加 class,CSS 选择器反而更舒服。

下面把这几个常用方式逐一捋一下。

一、正则表达式:快,但别拿它解析整棵 DOM

正则最大的优势就是快。

比如抓接口返回的数据:

订单编号:A20260928001
金额:399
状态:已支付

这种文本,没有什么 HTML 层级,用正则非常合适。

比如需要提取订单编号:

import re

text = """
订单编号:A20260928001
金额:399
状态:已支付
"""

order_id = re.search(r'订单编号:(\w+)', text)

if order_id:
    print(order_id.group(1))

输出:

A20260928001

这个场景正则很舒服。

但是很多新人喜欢这样:

html = """
<div>
    <span class="name">Python教程</span>
</div>
"""

name = re.findall(
    r'<span class="name">(.*?)</span>',
    html
)

看起来没问题。但真实网站里经常这样:

<span class="name">
    Python教程
</span>

多一个换行,凉。

再比如:

<span class="name" data-id="1">
    Python教程
</span>

属性顺序变一下,又凉。

所以我的习惯是:正则负责抓规律,不负责理解 HTML。 不要让正则去干 DOM 解析的活。简单文本场景用正则就够了,真要去解析结构化页面,下面几个工具更靠谱。

二、BeautifulSoup:处理普通网页,我最常用

BS4 最大的优点就是简单。网页结构清楚的时候,它写起来很舒服。

安装:

pip install beautifulsoup4

比如抓商品名称和价格:

from bs4 import BeautifulSoup

html = """
<div class="item">
    <h3>无线耳机</h3>
    <span class="price">199</span>
</div>

<div class="item">
    <h3>机械键盘</h3>
    <span class="price">299</span>
</div>
"""

soup = BeautifulSoup(html, "html.parser")

for item in soup.find_all("div", class_="item"):
    title = item.find("h3").text.strip()
    price = item.find(
        "span",
        class_="price"
    ).text.strip()
    print(title, price)

结果:

无线耳机 199
机械键盘 299

这个写法比较接近人的阅读方式:先找到商品节点,再进去找字段,维护起来也简单。

不过 BS4 有一个问题:当页面层级非常深的时候,代码容易套娃。

比如:

div
  └── section
       └── ul
            └── li
                 └── a
                      └── span

你可能会写:

data.find("section")\
    .find("ul")\
    .find("li")\
    .find("a")\
    .find("span")

写到后面自己都不想看。这种时候我一般换 XPath。

三、XPath:复杂页面的利器

XPath 本质是通过路径定位节点。浏览器开发者工具里复制 XPath,很多时候可以直接用。

比如:

<div id="content">
  <ul>
    <li>
      <a>
        Python爬虫
      </a>
    </li>
  </ul>
</div>

XPath 写法:

from lxml import etree

html = """
<div id="content">
    <ul>
        <li>
            <a>
                Python爬虫
            </a>
        </li>
    </ul>
</div>
"""

tree = etree.HTML(html)

result = tree.xpath(
    '//div[@id="content"]//a/text()'
)

print(result)

输出:

['Python爬虫']

XPath 有几个地方特别好用。

模糊匹配:

tree.xpath(
    '//div[contains(@class,"product")]'
)

取属性:

tree.xpath('//img/@src')

根据文本找:

tree.xpath(
    '//a[contains(text(),"Python")]'
)

实际工作中,如果遇到电商列表页、新闻列表页这种结构复杂的页面,我基本优先考虑 XPath,因为它的表达能力更强。

四、CSS 选择器:前端开发喜欢,爬虫也很好用

CSS 选择器其实和浏览器里的写法一样。如果你熟悉前端,这个上手非常快。

例如:

<div class="article">
  <h1>Python爬虫入门</h1>
</div>

使用 CSS:

from bs4 import BeautifulSoup

html = """
<div class="article">
    <h1>
        Python爬虫入门
    </h1>
</div>
"""

soup = BeautifulSoup(html, "html.parser")

title = soup.select_one(".article h1")

print(title.text.strip())

输出:

Python爬虫入门

几个常用写法:

class 选择器:

.box

id 选择器:

#main

标签后代:

div span

属性选择:

input[type="text"]

CSS 选择器最大的优势就是短。

很多时候 XPath 写一长串:

//div[@class='list']/ul/li/a/span

CSS 只需要:

.list li a span

看起来舒服很多。

不过 CSS 也有缺点。一些复杂定位,比如"找第三个 li 里面,文本包含 xxx 的节点",XPath 会更直接。

我自己项目里的选择顺序

如果只是抓接口返回的数据,直接正则。

比如:

import re

def parse_token(response):
    match = re.search(
        r'"token":"(.*?)"',
        response
    )
    return match.group(1) if match else None

页面 HTML 比较规整,用 BS4:

soup.select_one(".title")

页面结构复杂,用 XPath:

tree.xpath(
    '//div[contains(@class,"news")]/a/@href'
)

需要快速写,用 CSS:

soup.select(".item .name")

没有哪个选择器能吃遍所有场景。我见过不少爬虫项目,最大的问题不是不会写,而是一开始工具就选错了。拿正则硬拆 HTML,后面维护成本非常高——今天页面还能跑,过两个月换个模板,可能整个采集任务直接废掉。

最后给一个简单判断:

场景 推荐
提取固定格式文本 正则
普通 HTML 页面 BS4
页面层级复杂 XPath
熟悉前端选择规则 CSS

写爬虫,真正省时间的不是多会几个库,而是看到页面结构以后,知道什么时候该换工具。选对正则处理纯文本、用 BS4 搞定规整 HTML、遇到深层级页面换 XPath、前端动态 class 多的时候上 CSS 选择器,整个采集流程会顺畅不少。选择器只是手里的扳手,别拿螺丝刀去拧所有螺丝。更多爬虫实战技巧和项目经验,也可以到云栈社区和技术人一起交流。




上一篇:开源iPhone-use:Codex通过USB操控真实iPhone的安装指引与架构解析
下一篇:GLM-5.3-Flash 8卡AMD MI308X实测:并发、MTP加速与长文本极限
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-10-13 02:06 , Processed in 0.092229 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表