网页数据抓取与交互的实用指南
1. 使用 HTML 解析器抓取网站数据
在进行网页数据抓取时,虽然正则表达式在模式匹配方面表现出色,但有时使用专门用于解析 HTML 页面的解析器会更加便捷。Python 中有许多用于此目的的工具,其中最受欢迎且易于学习的是 Beautiful Soup。
1.1 安装 Beautiful Soup
-
使用 pip 安装
:运行命令
pip3 install beautifulsoup4。 -
手动安装
:下载压缩的
.tar.gz文件,解压后,通过命令行或终端运行setup.py脚本进行安装。 -
Debian/Linux 系统
:输入
sudo apt-get install python-bs4。
1.2 使用 Beautiful Soup 解析 HTML
安装完成后,就可以导入
bs4
模块并开始解析 HTML 了。以下是一个示例:
from bs4 import BeautifulSoup
from urllib.request import urlopen
my_address = "https://realpython.com/practice/dionysus.html"
html_page = urlopen(my_address)
html_text = html_page.read() # Py 3: decode
my_soup = BeautifulSoup(html_text)
接下来,可以根据需求以各种有用的方式从
my_soup
中解析数据。例如,使用
get_text()
方法提取文档中的纯文本,自动去除所有 HTML 标签:
print(my_soup.get_text())
输出结果可能会包含很多额外的空行,可以使用字符串的
replace()
方法去除。如果只需要从 HTML 文档中获取特定文本,先使用 Beautiful Soup 提取文本,再使用
find()
方法,有时比使用正则表达式更简单。
1.3 提取特定 HTML 标签信息
有时候,HTML 标签本身就是我们想要检索的数据的标识。例如,要检索页面上所有图像的链接,可以使用
find_all()
方法返回包含特定标签的所有实例的列表:
print(my_soup.find_all("img"))
虽然可能会遇到 HTML 标签编写不规范的情况,但 Beautiful Soup 会将 HTML 标签组织成
Tag
对象,我们可以轻松地从每个
Tag
对象中提取特定信息。例如,使用标准的字典表示法获取图像标签的
src
属性值:
image1, image2 = my_soup.find_all("img")
print(image1["src"])
print(image2["src"])
还可以通过
Tag
对象的名称来识别特定标签,如获取页面的标题:
print(my_soup.title)
print(my_soup.title.string)
甚至可以搜索属性匹配特定值的特定类型的标签:
print(my_soup.find_all("img", src="dionysus.jpg"))
1.4 Beautiful Soup 的局限性
尽管 Beautiful Soup 是一个优秀的工具,但它也有局限性。
lxml
虽然使用起来稍微复杂一些,但提供了与 Beautiful Soup 相同的功能,甚至更多。当你熟悉了 Beautiful Soup 的基础知识后,可以学习使用
lxml
来处理更复杂的 HTML 解析任务。
以下是使用 Beautiful Soup 解析 HTML 的流程图:
graph TD;
A[安装 Beautiful Soup] --> B[导入模块并获取 HTML];
B --> C[创建 BeautifulSoup 对象];
C --> D[使用各种方法解析数据];
D --> E[提取文本或特定标签信息];
2. 与 HTML 表单交互
通常,我们通过向网页发送请求来从互联网上检索信息,
urllib
模块在这方面表现出色。但有时我们需要向页面发送信息,例如在登录表单中提交信息,这时就需要一个实际的浏览器。Python 中有许多网页浏览器模块,其中最受欢迎且易于使用的是
MechanicalSoup
。
2.1 安装 MechanicalSoup
运行命令
pip3 install MechanicalSoup
进行安装。或者下载
.tar.gz
文件,解压后通过运行
setup.py
脚本进行安装。安装完成后,可能需要关闭并重新启动 IDLE 会话,以便
MechanicalSoup
能够加载并被识别。
2.2 使用 MechanicalSoup 打开网页
以下是使用
MechanicalSoup
创建一个新的浏览器对象并打开网页的示例:
import mechanicalsoup
my_browser = mechanicalsoup.Browser()
page = my_browser.get("https://realpython.com/practice/aphrodite.html")
print(page.soup)
2.3 自动化登录过程
如果需要向网站提交信息,例如登录页面,就需要自动化登录过程。以下是一个示例:
import mechanicalsoup
my_browser = mechanicalsoup.Browser()
login_page = my_browser.get("https://realpython.com/practice/login.php")
login_html = login_page.soup
# 选择表单并填充字段
form = login_html.select("form")[0]
form.select("input")[0]["value"] = "zeus"
form.select("input")[1]["value"] = "ThunderDude"
profiles_page = my_browser.submit(form, login_page.url) # 提交表单
print(profiles_page.url) # 确保重定向成功
print(profiles_page.soup) # 显示 HTML
通过上述步骤,我们使用浏览器的
select()
方法选择表单,通过访问 HTML
input
的
value
属性传递登录值,最后使用
submit()
方法提交表单。
2.4 获取页面链接信息
可以使用
links()
方法返回浏览器当前页面上出现的所有链接作为
Link
对象,然后遍历这些对象获取它们的地址。例如:
for link in profiles_page.soup.select("a"):
print("Address:", link["href"])
print("Text:", link.text)
以下是使用 MechanicalSoup 进行登录的操作步骤列表:
1. 创建
MechanicalSoup
浏览器对象。
2. 获取登录页面的 HTML。
3. 选择登录表单并填充用户名和密码。
4. 提交表单并检查重定向结果。
3. 实时与网站交互
有时我们希望从提供持续更新信息的网站获取实时数据。在学习 Python 编程之前,可能需要手动刷新页面来检查是否有更新内容。现在,可以使用
MechanicalSoup
浏览器的
get()
方法轻松自动化这个过程。
3.1 示例:定期检查股票报价
以定期检查 Yahoo! Finance 上 “YHOO” 股票的当前报价为例。首先,确定要检索的信息,找到包含股票价格的 HTML 标签:
import mechanicalsoup
my_browser = mechanicalsoup.Browser()
page = my_browser.get("http://finance.yahoo.com/q?s=yhoo")
html_text = page.soup
# 返回 id 为 'yfs_l84_yhoo' 的所有标签的列表
my_tags = html_text.select("#yfs_l84_yhoo")
# 提取第一个(也是唯一的)<span> 标签中的文本
my_price = my_tags[0].text
print("The current price of YHOO is: {}".format(my_price))
3.2 循环获取实时数据
为了反复获取最新的股票报价,需要创建一个循环,每次在浏览器中加载页面。但在进行之前,需要检查 Yahoo! Finance 的使用条款,确保不违反其可接受的使用政策。由于 Yahoo! 大约每分钟更新一次股票报价,我们可以在每次请求之间等待一分钟,使用 Python 的
time
模块的
sleep()
方法暂停脚本的执行:
from time import sleep
import mechanicalsoup
my_browser = mechanicalsoup.Browser()
# 在接下来的 3 分钟内每分钟获取一次股票报价
for i in range(0, 3):
page = my_browser.get("http://finance.yahoo.com/q?s=yhoo")
html_text = page.soup
# 返回 id 为 'yfs_l84_yhoo' 的所有标签的列表
my_tags = html_text.select("#yfs_l84_yhoo")
# 提取第一个标签中的文本
my_price = my_tags[0].text
print("The current price of YHOO is: {}".format(my_price))
if i < 2: # 如果不是最后一次请求,则等待一分钟
sleep(60)
以下是实时获取股票报价的流程图:
graph TD;
A[创建 MechanicalSoup 浏览器对象] --> B[获取股票页面 HTML];
B --> C[查找包含股票价格的标签];
C --> D[提取股票价格并显示];
D --> E{是否继续获取};
E -- 是 --> F[等待一分钟];
F --> B;
E -- 否 --> G[结束];
总结
通过使用 Beautiful Soup 解析 HTML 页面、MechanicalSoup 与网页表单交互以及实现实时数据获取,我们可以高效地完成网页数据抓取和交互任务。但在实际应用中,需要注意 HTML 编写不规范和网站使用条款等问题。同时,当遇到复杂的 HTML 解析任务时,可以考虑使用
lxml
等更强大的工具。
复习练习
-
使用 Beautiful Soup 抓取页面信息
-
编写一个脚本,从
profiles.html页面抓取完整的 HTML。 -
使用 Beautiful Soup 解析页面上的所有链接,通过查找名称为
a的 HTML 标签并检索每个标签的href属性值。 -
通过添加文件名的完整路径获取列表中每个页面的 HTML,并使用 Beautiful Soup 的
get_text()方法显示每个页面上的文本(不包含 HTML 标签)。
-
编写一个脚本,从
-
使用 MechanicalSoup 进行登录操作
-
使用
MechanicalSoup向位于https://realpython.com/practice/login.php的登录页面提交表单,提供正确的用户名 “zeus” 和密码 “ThunderDude”。 -
使用 Beautiful Soup 显示当前页面的标题,以确定是否已重定向到
profiles.html。 -
使用
MechanicalSoup返回登录页面,通过 “返回” 到上一页。 - 向登录表单提供不正确的用户名和密码,然后在返回的网页的 HTML 中搜索文本 “Wrong username or password!”,以确定登录过程是否失败。
-
使用
-
实时抓取股票报价
-
重复示例,抓取 “YHOO” 股票报价,并额外包含从 Yahoo! Finance 网页获取的报价的当前时间,该时间可以从网页 HTML 中实际股票价格之后不久出现的另一个
span标签内的字符串部分获取。
-
重复示例,抓取 “YHOO” 股票报价,并额外包含从 Yahoo! Finance 网页获取的报价的当前时间,该时间可以从网页 HTML 中实际股票价格之后不久出现的另一个
网页数据抓取与交互的实用指南(续)
4. 功能对比与总结
为了更清晰地了解 Beautiful Soup 和 MechanicalSoup 的特点和适用场景,下面通过表格进行对比:
| 工具名称 | 功能特点 | 适用场景 | 安装方式 |
| ---- | ---- | ---- | ---- |
| Beautiful Soup | 专门用于解析 HTML 页面,可轻松提取文本和特定标签信息,将 HTML 标签组织成 Tag 对象方便操作 | 单纯的 HTML 页面数据解析,如提取文章内容、图片链接等 | pip3 install beautifulsoup4;手动下载解压安装;Debian/Linux 系统使用 sudo apt-get install python-bs4 |
| MechanicalSoup | 可替代 urllib,能完成网页请求,还具备与网页交互的功能,如填写表单、提交信息、点击链接等 | 需要与网页进行交互的场景,如登录、提交数据等 | pip3 install MechanicalSoup;手动下载解压安装 |
5. 代码优化与注意事项
在使用上述工具进行网页数据抓取和交互时,有一些代码优化和注意事项需要关注:
5.1 异常处理
在进行网络请求和 HTML 解析时,可能会遇到各种异常,如网络连接失败、HTML 格式错误等。因此,需要添加异常处理代码,以增强程序的健壮性。以下是一个使用 MechanicalSoup 进行网页请求时添加异常处理的示例:
import mechanicalsoup
import requests
my_browser = mechanicalsoup.Browser()
try:
page = my_browser.get("https://realpython.com/practice/aphrodite.html")
html_text = page.soup
print(html_text)
except requests.exceptions.RequestException as e:
print(f"网络请求出错: {e}")
except Exception as e:
print(f"发生其他错误: {e}")
5.2 性能优化
如果需要处理大量的网页数据,性能优化就显得尤为重要。可以采用以下方法:
-
减少请求次数
:尽量合并请求,避免不必要的重复请求。
-
使用缓存
:对于一些不经常更新的数据,可以使用缓存机制,减少重复解析的时间。
-
异步请求
:使用异步编程库(如
asyncio
)进行异步请求,提高程序的并发性能。
5.3 遵守网站规则
在进行网页数据抓取时,一定要遵守网站的使用条款和
robots.txt
文件的规定,避免对网站造成不必要的负担或违反法律规定。
6. 综合应用示例
下面是一个综合应用 Beautiful Soup 和 MechanicalSoup 的示例,实现从登录页面登录后抓取目标页面信息的功能:
import mechanicalsoup
from bs4 import BeautifulSoup
# 创建 MechanicalSoup 浏览器对象
my_browser = mechanicalsoup.Browser()
# 登录页面
login_url = "https://realpython.com/practice/login.php"
login_page = my_browser.get(login_url)
login_html = login_page.soup
# 选择表单并填充字段
form = login_html.select("form")[0]
form.select("input")[0]["value"] = "zeus"
form.select("input")[1]["value"] = "ThunderDude"
# 提交表单
profiles_page = my_browser.submit(form, login_page.url)
# 检查是否登录成功
if profiles_page.url.endswith("profiles.html"):
print("登录成功!")
# 使用 Beautiful Soup 解析目标页面信息
soup = BeautifulSoup(profiles_page.text, 'html.parser')
links = soup.find_all('a')
for link in links:
print(f"链接地址: {link.get('href')},链接文本: {link.text}")
else:
print("登录失败!")
7. 总结与展望
通过本文的介绍,我们学习了如何使用 Beautiful Soup 解析 HTML 页面、使用 MechanicalSoup 与网页表单交互以及实时获取网页数据。这些工具为我们进行网页数据抓取和交互提供了强大的支持。
在未来的应用中,随着网页技术的不断发展,可能会遇到更复杂的 HTML 结构和交互方式。我们可以进一步学习和掌握更高级的工具和技术,如
Scrapy
框架,以应对更复杂的网页数据抓取需求。同时,也要始终遵守网络规则和道德规范,合法、合理地使用这些技术。
以下是综合应用的操作步骤列表:
1. 创建 MechanicalSoup 浏览器对象。
2. 获取登录页面的 HTML。
3. 选择登录表单并填充用户名和密码。
4. 提交表单并检查登录结果。
5. 如果登录成功,使用 Beautiful Soup 解析目标页面信息。
以下是综合应用的流程图:
graph TD;
A[创建 MechanicalSoup 浏览器对象] --> B[获取登录页面 HTML];
B --> C[选择表单并填充信息];
C --> D[提交表单];
D --> E{登录是否成功};
E -- 是 --> F[使用 Beautiful Soup 解析目标页面信息];
E -- 否 --> G[输出登录失败信息];
复习练习回顾
-
使用 Beautiful Soup 抓取页面信息
-
编写一个脚本,从
profiles.html页面抓取完整的 HTML。 -
使用 Beautiful Soup 解析页面上的所有链接,通过查找名称为
a的 HTML 标签并检索每个标签的href属性值。 -
通过添加文件名的完整路径获取列表中每个页面的 HTML,并使用 Beautiful Soup 的
get_text()方法显示每个页面上的文本(不包含 HTML 标签)。
-
编写一个脚本,从
-
使用 MechanicalSoup 进行登录操作
-
使用
MechanicalSoup向位于https://realpython.com/practice/login.php的登录页面提交表单,提供正确的用户名 “zeus” 和密码 “ThunderDude”。 -
使用 Beautiful Soup 显示当前页面的标题,以确定是否已重定向到
profiles.html。 -
使用
MechanicalSoup返回登录页面,通过 “返回” 到上一页。 - 向登录表单提供不正确的用户名和密码,然后在返回的网页的 HTML 中搜索文本 “Wrong username or password!”,以确定登录过程是否失败。
-
使用
-
实时抓取股票报价
-
重复示例,抓取 “YHOO” 股票报价,并额外包含从 Yahoo! Finance 网页获取的报价的当前时间,该时间可以从网页 HTML 中实际股票价格之后不久出现的另一个
span标签内的字符串部分获取。
-
重复示例,抓取 “YHOO” 股票报价,并额外包含从 Yahoo! Finance 网页获取的报价的当前时间,该时间可以从网页 HTML 中实际股票价格之后不久出现的另一个
希望通过这些复习练习,你能更好地掌握网页数据抓取和交互的技能。
网页抓取与交互实战指南
超级会员免费看
2089

被折叠的 条评论
为什么被折叠?



