Python爬虫入门:用Requests和BeautifulSoup抓取静态网页

Evan
Evan
发布时间:2026-09-22| 5人浏览过
原创

假设你正在跟进一个图书排行榜页面,每天需要手动打开浏览器、复制书名与价格整理到表格里。面对这类结构固定且内容直接写在 HTML 源码中的静态网页,使用 Python 编写自动化脚本是最直接的解决方案。抓取静态网页的核心路径非常清晰:先使用 Requests 库下载服务器返回的完整 HTML 文档,再交给 BeautifulSoup 库解析 DOM 树结构并提取目标数据。

1. 什么是静态网页与基础分工

所谓“静态网页”,指的是浏览器发起 HTTP GET 请求后,服务端返回的 HTML 文本中已经包含了所有需要展示的文本、链接和排版信息,无需在浏览器端执行复杂的 JavaScript 脚本二次渲染。验证一个网页是否属于静态网页的最简单方法,是在浏览器页面空白处右键点击“查看网页源代码”(快捷键 Ctrl+U 或 Cmd+Option+U),并在源码中搜索页面上可见的文字。如果源码中能直接搜到,就属于可以直接抓取的静态内容。

在这个任务中,两个核心库各司其职:Requests 充当浏览器的“网络通信通道”,负责封装 HTTP 请求头、发送网络请求并接收原始数据;BeautifulSoup 则充当“数据提取放大镜”,负责将冰冷的纯文本解析成具有层级结构的节点树,方便我们定位与提取标签内的属性和文本。

Python爬虫入门:用Requests和BeautifulSoup抓取静态网页
图 1:Requests 与服务端交互架构与响应流程

2. 准备运行环境

在编写代码前,需要确保系统中已安装 Python(建议 Python 3.8 或更高版本),并在终端或命令提示符中通过 pip 工具安装所需的第三方库。我们同时安装用于解析 HTML 的 lxml 解析器,它的底层是 C 语言实现,相较于 Python 自带的 html.parser 速度更快且容错率更高:

pip install requests beautifulsoup4 lxml

安装完成后,可以在交互式终端中执行以下语句,验证库是否能正常导入:

python -c "import requests; from bs4 import BeautifulSoup; print('环境准备就绪')"

如果控制台输出“环境准备就绪”且没有任何报错,说明基础开发依赖已经正确配置。

3. 静态爬虫操作步骤

抓取并提取静态网页数据遵循一套标准的流水线作业,从发起请求直到拿到最终纯净数据,整个过程由四个连续动作构成。

Python爬虫入门:用Requests和BeautifulSoup抓取静态网页
图 2:静态网页数据抓取的核心操作流水线

第一步:使用 Requests 获取源码

直接通过 requests.get() 发送请求时,默认的 User-Agent 会标明自身是 Python 脚本,这往往会被许多网站的防火墙直接拦截返回 403 状态码。因此,规范的做法是附带浏览器请求头:

import requests

target_url = "https://quotes.toscrape.com/"
custom_headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}

# 设置 timeout=10,避免因网络无响应导致程序无限挂起
response = requests.get(target_url, headers=custom_headers, timeout=10)

# 确保请求成功;若状态码非 200 会主动抛出异常
response.raise_for_status()

# 页面 HTML 纯文本
html_content = response.text

第二步:使用 BeautifulSoup 转换与定位节点

拿到 HTML 纯文本后,纯字符串操作(如正则查找)容易受到标签嵌套、换行和多余属性的干扰。BeautifulSoup 将这段文本解析成由节点构成的 DOM 树:

from bs4 import BeautifulSoup

soup = BeautifulSoup(html_content, "lxml")
Python爬虫入门:用Requests和BeautifulSoup抓取静态网页
图 3:BeautifulSoup DOM 树层次结构与数据提取关系

在解析对象生成后,主要通过两种选择方式提取节点:

  • 标准查找方法(find / find_all):
    • soup.find("div", class_="quote"):返回页面中匹配到的第一个 <div class="quote"> 标签对象。
    • soup.find_all("div", class_="quote"):返回一个包含全部匹配标签的列表,可直接使用 for 循环遍历。注意由于 class 是 Python 保留关键字,BeautifulSoup 统一使用 class_ 参数来指定类名。
  • CSS 选择器(select / select_one):
    • soup.select_one("div.quote"):按 CSS 选择器匹配首个元素。
    • soup.select("div.quote span.text"):支持类选择器、后代选择器与属性选择器,对于熟悉前端 CSS 语法的读者更为直观。

4. 完整实战代码

以专门用于爬虫演练的公开测试网站 quotes.toscrape.com 为例,下面的脚本将完整演示从请求网页、循环解析每一个名言区块,到提取“名言内容”、“作者”及“详情链接”的全过程。

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin

def scrape_quotes():
    base_url = "https://quotes.toscrape.com/"
    headers = {
        "User-Agent": (
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 (KHTML, like Gecko) "
            "Chrome/120.0.0.0 Safari/537.36"
        )
    }

    try:
        response = requests.get(base_url, headers=headers, timeout=10)
        response.raise_for_status()
    except requests.exceptions.RequestException as error:
        print(f"网络请求失败: {error}")
        return

    # 解析 HTML 内容
    soup = BeautifulSoup(response.text, "lxml")
    
    # 查找所有名言卡片节点
    quote_blocks = soup.find_all("div", class_="quote")
    print(f"成功定位到 {len(quote_blocks)} 条记录,开始解析:\n")

    results = []
    for item in quote_blocks:
        # 1. 提取名言文字
        text_element = item.find("span", class_="text")
        quote_text = text_element.get_text(strip=True) if text_element else "无内容"

        # 2. 提取作者姓名
        author_element = item.find("small", class_="author")
        author_name = author_element.get_text(strip=True) if author_element else "未知"

        # 3. 提取作者主页链接(属性提取)
        link_element = item.find("a", string="(about)")
        if link_element and "href" in link_element.attrs:
            relative_link = link_element["href"]
            # 将相对路径拼接为完整绝对 URL
            full_link = urljoin(base_url, relative_link)
        else:
            full_link = "无链接"

        results.append({
            "quote": quote_text,
            "author": author_name,
            "link": full_link
        })

    # 输出抓取结果
    for idx, data in enumerate(results, start=1):
        print(f"[{idx}] {data['author']}")
        print(f"    名言: {data['quote']}")
        print(f"    主页: {data['link']}")

if __name__ == "__main__":
    scrape_quotes()

将上述代码保存为 scraper_demo.py 并运行。终端会按顺序输出格式化后的数据列表:

示例输出:
成功定位到 10 条记录,开始解析:

[1] Albert Einstein
    名言: “The world as we have created it is a process of our thinking...”
    主页: https://quotes.toscrape.com/author/Albert-Einstein
[2] J.K. Rowling
    名言: “It is our choices, Harry, that show what we truly are...”
    主页: https://quotes.toscrape.com/author/J-K-Rowling

5. 常见问题与排查思路

排查建议:抓取时遇到未预期的错误,绝大多数并非代码语法问题,而是网络协商阶段或 DOM 节点变化导致的逻辑空值。
常见现象 产生原因 针对性解决方案
AttributeError: 'NoneType' object has no attribute 'get_text' find() 没有找到匹配的标签,返回了 None,直接调用方法导致报错。 在提取属性或文本前做非空判断(if element: ...),或先检查选择器是否因网页改版失效。
抓取中文内容出现乱码(如 Ã¥Â...) Requests 推测的网页编码与服务器实际编码不一致。 手动指定解码方式:在调用 response.text 前设置 response.encoding = response.apparent_encoding。
返回状态码 403 Forbidden 服务器反爬机制识别出请求未携带合法浏览器标识。 完善请求头中的 User-Agent、Referer 与 Accept-Language 等字段。
在浏览器控制台能看到数据,但代码抓取为空 该部分数据是前端通过 Ajax/Fetch 异步加载生成的,并非静态 HTML。 静态爬虫无法直接拿到动态数据。需通过浏览器的“网络 (Network)”面板抓取后端 API,或换用无头浏览器。

6. 流程总结

使用 Requests 和 BeautifulSoup 抓取静态网页是一套规律明确的工作流:先通过网络层获取准确的 HTML 文本,再通过解析层定位目标节点并清洗数据。在实际开发中,务必养成随时添加超时约束、异常防御和编码校验的习惯,以保障爬虫程序稳定运行。

Python爬虫入门:用Requests和BeautifulSoup抓取静态网页
图 4:静态网页爬虫核心规则与开发准则总结

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。