4、Python爬虫基础:Requests库的使用、BeautifulSoup解析HTML、XPath与CSS选择器、数据提取实战
好,咱们进入爬虫实战环节。说实话,很多新手一上来就想着搞分布式、搞反爬,其实没必要。你想想看,一个连网页都拿不下来的人,谈什么反爬?
这一章,我带你从零开始,把爬虫最核心的四个技能点打扎实。分别是:发请求、解析页面、定位元素、提取数据。嗯,就这么简单,但足够你应付80%的日常需求了。
4.1 Requests库:你的网络触手
Requests 是 Python 里最优雅的 HTTP 库,没有之一。我当年用 urllib 的时候,每次写请求都要手动拼接参数、处理编码,烦得要死。后来换了 Requests,感觉整个世界都清净了。
4.1.1 安装与基本请求
pip install requests
装好之后,发一个 GET 请求有多简单?看代码:
import requests
url = "https://httpbin.org/get"
response = requests.get(url)
print(response.status_code) # 200
print(response.text) # 响应内容(字符串)
print(response.json()) # 如果返回JSON,直接解析成字典
我个人习惯,每次写完请求先打印 status_code。为什么?因为很多问题出在请求本身,比如 URL 写错了、服务器拒绝了。看一眼状态码,心里就有底了。
response.encoding = 'utf-8'。我在爬某个老网站时遇到过,它返回的响应头里编码声明是错的,手动指定一下就正常了。
4.1.2 带参数的请求
很多时候,我们需要在 URL 后面加参数。比如搜索、翻页。Requests 处理这个特别优雅:
params = {
"q": "Python爬虫",
"page": 1
}
response = requests.get("https://httpbin.org/get", params=params)
print(response.url) # 自动拼接成完整URL
你想想看,如果手动拼接,还得处理特殊字符的转义。用 params 参数,这些脏活累活 Requests 全帮你干了。
4.1.3 请求头与超时
有些网站会检查请求头,比如 User-Agent。不加的话,可能直接返回 403 拒绝访问。我刚开始学爬虫时就吃过这个亏,死活拿不到数据,后来发现是没伪装成浏览器。
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
response = requests.get(url, headers=headers, timeout=5)
timeout 参数!我曾经写过一个爬虫,没设超时,结果某个请求卡住了,整个程序就挂在那里不动了。设个 5 秒、10 秒,既保护自己,也减轻对方服务器压力。
4.2 BeautifulSoup:HTML 解析利器
拿到网页源码之后,下一步就是解析它。BeautifulSoup 是我用得最多的解析库,因为它对新手特别友好。说白了,它就是把混乱的 HTML 变成一棵清晰的树,你想摘哪个节点就摘哪个。
4.2.1 安装与基本用法
pip install beautifulsoup4 lxml
注意,我建议同时安装 lxml 解析器。BeautifulSoup 默认用 Python 内置的解析器,速度慢,而且容错性差。lxml 是 C 语言写的,快得多。
from bs4 import BeautifulSoup
html = "<html><body><h1>Hello, World!</h1></body></html>"
soup = BeautifulSoup(html, "lxml")
print(soup.h1.text) # 输出:Hello, World!
看到了吗?直接 soup.h1 就能拿到标签。BeautifulSoup 会自动补全缺失的标签,容错性极强。嗯,这一点在实际项目中特别有用,因为很多网站的 HTML 写得并不规范。
4.2.2 常用方法
我整理了一张表,把最常用的几个方法列出来,你直接照着用就行:
| 方法 | 作用 | 示例 |
|---|---|---|
find() |
找到第一个匹配的标签 | soup.find('div', class_='content') |
find_all() |
找到所有匹配的标签,返回列表 | soup.find_all('a') |
select() |
用 CSS 选择器定位 | soup.select('.item a') |
.text |
获取标签内的文本内容 | soup.h1.text |
.get() |
获取标签的属性值 | soup.a.get('href') |
find_all 或 select 定位到包含数据的容器,再逐个提取里面的文本和属性。千万别想着一步到位,拆开来做,逻辑更清晰。
4.3 XPath 与 CSS 选择器:精准定位
BeautifulSoup 的 find 方法虽然好用,但遇到复杂的嵌套结构时,写起来就有点啰嗦了。这时候,XPath 和 CSS 选择器就派上用场了。
4.3.1 XPath 基础
XPath 是一种在 XML/HTML 文档中查找信息的语言。它的语法很强大,但咱们只需要掌握几个核心的:
from lxml import etree
html = "<html><body><div class='item'><a href='link1'>链接1</a></div></body></html>"
tree = etree.HTML(html)
# 绝对路径
result = tree.xpath('/html/body/div/a/text()') # ['链接1']
# 相对路径 + 属性过滤
result = tree.xpath('//div[@class="item"]/a/@href') # ['link1']
# 通配符
result = tree.xpath('//*[@class="item"]') # 所有class为item的元素
我个人习惯用 // 开头,因为不用关心具体的层级结构,直接按属性或标签名找就行了。你想想看,一个网页可能有几十层嵌套,用绝对路径写起来多累啊。
4.3.2 CSS 选择器
如果你熟悉前端,CSS 选择器可能更顺手。BeautifulSoup 和 lxml 都支持:
# 用 BeautifulSoup 的 select 方法
soup.select('.item a') # class为item下的所有a标签
soup.select('#main > p') # id为main的直接子元素p
soup.select('a[href^="http"]') # href以http开头的a标签
# 用 lxml 的 cssselect 方法
from lxml.cssselect import CSSSelector
sel = CSSSelector('.item a')
results = sel(tree)
嗯,这里有个小建议:能用 CSS 选择器就别用 XPath。为什么?因为 CSS 选择器更简洁,可读性更好。除非你需要用到 XPath 的高级功能,比如按文本内容定位、按位置索引等。
4.4 数据提取实战:从理论到代码
光说不练假把式。咱们拿一个真实的场景来练手:爬取一个新闻列表页,提取标题、链接和发布时间。
4.4.1 完整代码示例
import requests
from bs4 import BeautifulSoup
# 1. 发请求
url = "https://example.com/news"
headers = {"User-Agent": "Mozilla/5.0"}
response = requests.get(url, headers=headers, timeout=5)
response.encoding = 'utf-8'
# 2. 解析页面
soup = BeautifulSoup(response.text, "lxml")
# 3. 定位数据容器
news_list = soup.select('.news-list .item')
# 4. 提取数据
for news in news_list:
title = news.find('h2').text.strip()
link = news.find('a').get('href')
date = news.find('.date').text.strip()
print(f"标题:{title} | 链接:{link} | 日期:{date}")
这个流程,说白了就是四步走:请求 → 解析 → 定位 → 提取。我做了这么多年爬虫,不管多复杂的项目,底层逻辑都是这四步。
4.4.2 常见问题与处理
- 拿不到数据? 先打印
response.text看看,是不是被反爬了,或者页面是动态加载的。 - 提取结果为空? 检查选择器是否写对了。我建议先在浏览器开发者工具里验证一下选择器。
- 数据有空白或换行? 用
.strip()清理一下。我每次提取文本都会加这个,已成习惯。
4.5 本章小结
这一章,咱们把爬虫最基础也最重要的四个工具过了一遍。Requests 负责拿数据,BeautifulSoup 负责解析,XPath 和 CSS 选择器负责定位,最后把数据提取出来。你想想看,是不是很简单?
下一章,我会带你深入爬虫的进阶技巧,包括处理动态页面、模拟登录、使用代理等。嗯,到时候你会发现,爬虫的世界远比你想象的精彩。
response.text 看看,再一步步调试。相信我,写出来之后你会很有成就感。