首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Python + BeautifulSoup4 爬虫入门

Python + BeautifulSoup4 爬虫入门

原创
作者头像
用户12890632
发布于 2026-11-14 21:36:20
发布于 2026-11-14 21:36:20
70
举报

BeautifulSoup4 通常简称为 bs4,它本身不负责发送网络请求,而是负责把网页的 HTML 文本解析成可以查找、遍历的对象。实际爬虫里,常用 requests 获取网页,再用 bs4 解析网页。

bs4 适合抓取 静态网页,也就是服务器直接返回完整 HTML 的页面。如果页面内容主要靠 JavaScript 动态加载,bs4 可能解析不到数据,这时需要改用接口抓取或 Playwright/Selenium。

1. 安装依赖

代码语言:javascript
复制
pip install requests beautifulsoup4 lxml

推荐使用 lxml 解析器,速度更快,容错性也更好。

2. bs4 常用方法

方法

作用

示例

find()

找第一个匹配元素

soup.find("h1")

find_all()

找所有匹配元素

soup.find_all("a")

select()

使用 CSS 选择器

soup.select(".title")

get_text()

提取文本

tag.get_text(strip=True)

.get()

获取属性值

a.get("href")

3. 完整代码示例

下面代码会抓取 Books to Scrape 这个公开练习网站的第一页书籍信息,包括书名、价格和链接。

代码语言:javascript
复制
import csv
import time
import random
import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin

BASE_URL = "http://wlt.yunhaizz.cn"
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"
    ),
}

def fetch_page(url: str) -> str | None:
    """获取网页源码,失败返回 None"""
    try:
        resp = requests.get(url, headers=HEADERS, timeout=10)
        resp.raise_for_status()
        resp.encoding = resp.apparent_encoding
        return resp.text
    except Exception as exc:
        print(f"请求失败: {url}, 错误: {exc}")
        return None

def parse_books(html: str) -> list[dict]:
    """解析一页书籍信息"""
    soup = BeautifulSoup(html, "lxml")
    books = []

    # 每本书通常位于 article.product_pod 中
    items = soup.select("article.product_pod")

    for item in items:
        title_tag = item.select_one("h3 a")
        price_tag = item.select_one(".price_color")
        link_tag = item.select_one("h3 a")

        title = title_tag.get("title", "").strip() if title_tag else ""
        price = price_tag.get_text(strip=True) if price_tag else ""
        href = link_tag.get("href", "") if link_tag else ""
        url = urljoin(BASE_URL, href) if href else ""

        books.append({
            "title": title,
            "price": price,
            "url": url,
        })

    return books

def save_to_csv(books: list[dict], filename: str = "books.csv") -> None:
    """把结果保存为 CSV"""
    if not books:
        print("没有数据可保存")
        return

    with open(filename, "w", newline="", encoding="utf-8-sig") as f:
        writer = csv.DictWriter(f, fieldnames=["title", "price", "url"])
        writer.writeheader()
        writer.writerows(books)

    print(f"已保存 {len(books)} 条数据到 {filename}")

def main():
    url = f"{BASE_URL}/catalogue/page-1.html"
    html = fetch_page(url)

    if not html:
        return

    books = parse_books(html)

    for book in books:
        print(book)

    save_to_csv(books)

    # 避免请求过快
    time.sleep(random.uniform(1, 2))

if __name__ == "__main__":
    main()

4. 运行结果示例

程序运行后,控制台会输出类似内容:

代码语言:javascript
复制
{'title': 'A Light in the ...', 'price': '£51.77', 'url': 'http://wlt.yunhaizz.cn/catalogue/a-light-in-the-...'}
{'title': 'Tipping the Velvet', 'price': '£53.74', 'url': 'http://wlt.yunhaizz.cn/catalogue/tipping-the-velvet_999/index.html'}
...
已保存 20 条数据到 books.csv

5. 注意事项

  • 不要高频请求:每次请求之间最好加入随机延迟,避免给服务器造成压力。
  • 遵守 robots.txt 和网站条款:只抓取公开数据,不绕过登录、付费墙或验证码。
  • 不要采集个人隐私信息:尤其是账号、手机号、邮箱、地址等敏感数据。
  • 动态页面需要额外处理:如果网页源码里没有目标数据,说明可能是 JS 渲染页面,bs4 无法直接解决。
  • 生产环境建议加强容错:可以加入重试机制、代理池、日志记录和数据去重。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 1. 安装依赖
  • 2. bs4 常用方法
  • 3. 完整代码示例
  • 4. 运行结果示例
  • 5. 注意事项
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档