共计 2367 个字符,预计需要花费 6 分钟才能阅读完成。
在前一节中,我们学习了如何使用 BeautifulSoup 解析网页结构,提取标签、属性和文本内容。今天,我们将迈出重要一步——使用 requests 与 BeautifulSoup 结合,构建一个完整的网页爬虫,自动抓取网页数据。
一、什么是网页爬虫
网页爬虫(Web Crawler)是用来自动访问网页并提取有用信息的程序。比如,你可以编写一个爬虫自动获取新闻网站的标题、商品网站的价格,或博客中的最新文章。
Python 提供了强大的网络与解析库,使得编写爬虫程序变得非常简单且灵活。
二、基本爬虫结构
一个最基础的爬虫流程一般包括以下步骤:
- 发送请求,获取网页内容;
- 解析网页,提取所需数据;
- 保存结果,存入文件或数据库。
示例:
import requests
from bs4 import BeautifulSoup
# 第一步:获取网页内容
url = "https://news.ycombinator.com/"
response = requests.get(url)
html = response.text
# 第二步:解析网页
soup = BeautifulSoup(html, "lxml")
# 第三步:提取目标数据
titles = soup.select(".titleline a")
for idx, title in enumerate(titles[:10], start=1):
print(f"{idx}. {title.text} -> {title['href']}")
这段代码可以从 Hacker News 首页提取出前 10 条新闻标题及其链接。
三、设置请求头防止被屏蔽
有些网站会检查请求来源,如果检测到是爬虫(如缺少浏览器标识的请求头),可能会返回错误或空内容。
我们可以通过在请求中添加请求头(headers)来模拟浏览器访问:
headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"
}
response = requests.get(url, headers=headers)
这样可以让请求更接近真实的浏览器访问行为。
四、异常处理与状态码检查
在爬取网页时,我们需要检查网页是否成功返回,以防止程序异常终止。
try:
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
except requests.RequestException as e:
print(" 请求失败:", e)
通过 raise_for_status() 方法,可以在网页返回 404 或 500 错误时抛出异常。
五、抓取多页内容
很多网站内容分布在多个页面,我们可以通过构造循环爬取所有页面。
示例(爬取前 3 页新闻标题):
for page in range(1, 4):
page_url = f"https://news.ycombinator.com/?p={page}"
response = requests.get(page_url, headers=headers)
soup = BeautifulSoup(response.text, "lxml")
titles = soup.select(".titleline a")
print(f" 第 {page} 页新闻:")
for title in titles:
print("-", title.text)
这种分页爬取方式非常常见,比如论坛、新闻网站、电商商品列表等。
六、保存数据到文件
为了便于后续分析或展示,我们可以将抓取的数据保存到文本或 CSV 文件中。
import csv
with open("news.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow([" 标题 ", " 链接 "])
for title in titles:
writer.writerow([title.text, title["href"]])
这样就能把结果存储成可读性强的文件。
七、添加延时与反爬策略
为了避免频繁请求导致被封禁,我们可以添加访问间隔。
import time
for page in range(1, 4):
print(f" 正在抓取第 {page} 页...")
# 抓取逻辑
time.sleep(2) # 延时 2 秒
此外,也可以使用 random.uniform(1,3) 来设置随机间隔,更接近人类行为。
八、封装成函数
为了让代码结构更清晰,我们可以把爬虫封装成函数:
def get_news(page_count=3):
headers = {"User-Agent": "Mozilla/5.0"}
for page in range(1, page_count + 1):
url = f"https://news.ycombinator.com/?p={page}"
res = requests.get(url, headers=headers)
soup = BeautifulSoup(res.text, "lxml")
for title in soup.select(".titleline a"):
yield title.text, title["href"]
for title, link in get_news():
print(title, "->", link)
通过 yield 生成器的方式,我们可以边抓取边处理数据,节省内存。
九、小结
在本节中,我们完成了一个功能完整的网页爬虫,掌握了以下内容:
- 使用
requests获取网页内容; - 使用
BeautifulSoup解析网页结构; - 提取目标标签与属性;
- 保存结果到文件;
- 处理异常与多页数据。
在下一节中,我们将进一步扩展这一知识,学习如何将爬取的数据保存为 JSON 格式,以及如何进行简单的数据可视化分析,让爬虫成果更具实用价值。