
本教程旨在解决使用beautifulsoup抓取网页时,因内容动态加载而导致目标标签为空的问题。文章将深入探讨传统静态抓取工具的局限性,指导读者利用浏览器开发者工具识别并直接请求隐藏在xhr(xmlhttprequest)中的真实数据源,并通过python的`requests`库处理json响应,从而实现对动态内容的精准抓取。
在使用Python进行网页抓取时,BeautifulSoup库因其强大的HTML/XML解析能力而广受欢迎。然而,当目标网页的内容是通过JavaScript动态加载时,仅依赖requests.get()获取的初始HTML文档往往无法包含所有期望的数据。此时,BeautifulSoup解析到的特定标签(例如一个带有id的zuojiankuohaophpcnul>标签)可能会显示为空,即使在浏览器中查看时该标签下有丰富的内容。这是因为requests.get()只获取了服务器返回的原始静态HTML,而JavaScript在页面加载后才执行并填充了这些内容。
例如,尝试从一个动态加载内容的页面抓取id="demoFour"的<ul>标签,可能会得到一个空的<ul>标签:
import requests
from bs4 import BeautifulSoup
url = "https://www.parliament.lk/en/members-of-parliament/directory-of-members/?cletter=A"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
# 尝试查找id为demoFour的ul标签
ul_tag = soup.find('ul', id='demoFour')
print(ul_tag)
# 预期输出可能是:<ul id="demoFour"></ul>
# 实际上,在浏览器中这个ul标签下有li列表项要解决这个问题,关键在于识别并直接访问那些负责动态加载数据的幕后请求。这些请求通常是XHR(XMLHttpRequest)或Fetch API请求,它们在后台与服务器通信,获取JSON或XML格式的数据,然后由JavaScript渲染到页面上。
通过检查,我们会发现原页面中议员列表的数据并非直接嵌入HTML,而是通过一个POST请求发送到https://www.parliament.lk/members-of-parliament/directory-of-members/index2.php?option=com_members&task=all&tmpl=component&letter={letter}&wordfilter=&search_district=这样的API端点,并以JSON格式返回。
一旦找到了实际的数据API端点,我们就可以直接使用requests库向其发送请求,获取原始数据。
以下代码演示了如何通过直接调用XHR API来获取斯里兰卡议会成员的列表数据:
import requests
import string
import json # 导入json模块以更好地处理JSON数据
# 存储所有议员数据的列表
all_members_data = []
# 遍历字母A-Z,因为议员列表是按字母分类加载的
for letter in list(string.ascii_uppercase):
# 构建API请求URL。注意这里使用了POST请求
# 这个URL是通过浏览器开发者工具的XHR请求中发现的
api_url = f'https://www.parliament.lk/members-of-parliament/directory-of-members/index2.php?option=com_members&task=all&tmpl=component&letter={letter}&wordfilter=&search_district='
try:
# 发送POST请求到API端点
# 实际的网页可能会在请求头中包含其他参数,例如User-Agent,
# 如果遇到反爬,可能需要模拟更多请求头
response = requests.post(api_url)
response.raise_for_status() # 检查请求是否成功(状态码200)
# 解析JSON响应
members_json = response.json()
# 遍历返回的每个议员数据项
for member_info in members_json:
# 提取所需信息并构建字典
member_details = {
'url': f"https://www.parliament.lk/en/members-of-parliament/directory-of-members/viewMember/{member_info['mem_intranet_id']}",
'id': member_info['mem_intranet_id'],
'name': member_info['member_sname_eng']
}
all_members_data.append(member_details)
except requests.exceptions.RequestException as e:
print(f"请求字母 {letter} 时发生错误: {e}")
except json.JSONDecodeError as e:
print(f"解析字母 {letter} 的JSON响应时发生错误: {e}")
# 打印获取到的部分数据作为示例
print(json.dumps(all_members_data[:5], indent=2, ensure_ascii=False)) # 打印前5条数据,格式化输出
# 如果需要,可以将所有数据保存到文件
# with open('parliament_members.json', 'w', encoding='utf-8') as f:
# json.dump(all_members_data, f, indent=2, ensure_ascii=False)通过上述方法,我们不仅解决了最初<ul>标签为空的问题,更掌握了抓取动态网页的核心技术。这种直接与后端API交互的方式,通常比模拟浏览器行为(如使用Selenium)更高效、资源消耗更低,是处理这类抓取任务的首选方案。
以上就是如何高效抓取动态加载的网页内容:以BeautifulSoup与XHR请求为例的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号