BeautifulSoup4 通常简称为 bs4,它本身不负责发送网络请求,而是负责把网页的 HTML 文本解析成可以查找、遍历的对象。实际爬虫里,常用 requests 获取网页,再用 bs4 解析网页。
bs4 适合抓取 静态网页,也就是服务器直接返回完整 HTML 的页面。如果页面内容主要靠 JavaScript 动态加载,bs4 可能解析不到数据,这时需要改用接口抓取或 Playwright/Selenium。
pip install requests beautifulsoup4 lxml推荐使用 lxml 解析器,速度更快,容错性也更好。
方法 | 作用 | 示例 |
|---|---|---|
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") |
下面代码会抓取 Books to Scrape 这个公开练习网站的第一页书籍信息,包括书名、价格和链接。
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()程序运行后,控制台会输出类似内容:
{'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原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。