
本教程旨在解决使用beautifulsoup抓取动态加载内容时的局限性。当目标数据(如隐藏的电话号码)通过javascript异步加载时,传统html解析器无法获取。文章将指导读者如何利用浏览器开发者工具识别并模拟网站后端api请求,特别是graphql请求,从而直接获取所需数据。通过python的requests库,我们将演示如何构建并发送http post请求,以高效、准确地抓取动态生成的内容。
在现代Web开发中,许多网站为了提供更流畅的用户体验,会采用JavaScript动态加载内容。这意味着当您使用像BeautifulSoup这样的HTML解析库去抓取一个页面时,您可能只会得到一个骨架HTML文档,而那些通过用户交互(例如点击按钮)或页面加载后异步加载的数据则无法直接获取。
以抓取一个隐藏在“联系”按钮后的电话号码为例。当用户点击该按钮时,JavaScript会执行一个操作,通常是向后端API发送请求,然后将返回的数据(如电话号码)插入到页面的DOM中。此时,如果仅依赖BeautifulSoup解析初始页面,您将无法找到这个电话号码,因为它尚未被渲染到HTML中。
解决动态内容抓取的关键在于识别并模拟网站向其后端API发出的请求。浏览器开发者工具是完成这项任务的强大助手。
通过分析这些信息,我们可以精确地复现浏览器与服务器之间的通信过程。
一旦我们确定了API请求的细节,就可以使用Python的requests库来模拟这些请求。
对于本例,我们发现网站使用GraphQL API。这意味着我们需要向一个特定的GraphQL端点发送一个HTTP POST请求,并在请求体中包含一个GraphQL查询语句和相应的变量。
导入 requests 库:
import requests
定义API端点: 这是您从开发者工具中识别出的请求URL。
url = "https://graphql.haraj.com.sa"
设置请求头: 至少包含一个User-Agent,以模拟浏览器行为。
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"
}构建查询参数(可选): 有些API请求URL中会包含查询参数。根据开发者工具的观察,本例中的GraphQL API在URL中包含了一些参数,但实际测试发现,即使不提供这些参数,API也能正常响应。为了教程的完整性,可以定义但留空或根据实际情况填充。
params = {
"queryName": "postContact",
"token": "",
"clientId": "",
"version": ""
}注意: 实际操作中,token和clientId等参数可能需要从原始页面或其他API请求中动态获取,或者可能不是必需的。在本例中,它们似乎不是强制性的。
构建请求负载(Payload): 这是最重要的部分,尤其是对于GraphQL API。它是一个JSON对象,包含query(GraphQL查询语句)和variables(查询所需的变量)。
payload = {
"query": "query postContact($postId: Int!) {postContact(postId: $postId){contactText}}",
"variables": {
"postId": 94697687 # 这个ID通常从原始页面URL中提取
}
}发送POST请求: 使用requests.post()方法,将URL、参数、头部和JSON负载传递进去。json=payload会自动设置Content-Type为application/json。
response = requests.post(url, params=params, headers=headers, json=payload)
处理响应:
import requests
import sys
def scrape_phone_number(post_id):
"""
通过模拟GraphQL API请求从Haraj网站抓取电话号码。
Args:
post_id (int): 帖子的ID,通常从帖子URL中提取。
Returns:
str: 提取到的电话号码,如果失败则返回None。
"""
url = "https://graphql.haraj.com.sa"
# 根据实际情况,这些参数可能需要动态获取或并非必需
params = {
"queryName": "postContact",
"token": "",
"clientId": "",
"version": ""
}
headers = {
# 建议使用完整的User-Agent字符串以更好地模拟浏览器
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"
}
payload = {
"query": "query postContact($postId: Int!) {postContact(postId: $postId){contactText}}",
"variables": {
"postId": post_id
}
}
try:
response = requests.post(url, params=params, headers=headers, json=payload)
response.raise_for_status() # 检查HTTP请求是否成功
data = response.json()
# 从JSON响应中提取电话号码
contact_text = data.get('data', {}).get('postContact', {}).get('contactText')
return contact_text
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
return None
except KeyError:
print("从API响应中解析数据失败,可能结构不符。")
return None
if __name__ == "__main__":
# 示例:从帖子URL https://haraj.com.sa/1194697687 中提取postId
example_post_id = 94697687
phone_number = scrape_phone_number(example_post_id)
if phone_number:
print(f"抓取到的电话号码是: {phone_number}")
else:
print("未能抓取到电话号码。")
sys.exit(0)
抓取到的电话号码是: 0562038953
当传统的HTML解析方法(如BeautifulSoup)无法获取动态加载的内容时,通过模拟网站的后端API请求是更强大、更直接的解决方案。利用浏览器开发者工具分析网络流量,识别API端点、请求方法、头部和负载,然后使用Python的requests库精确地复现这些请求,可以有效地抓取到隐藏在动态交互背后的数据。这种方法不仅适用于电话号码,也适用于任何通过JavaScript异步加载的数据。
以上就是从动态网站抓取隐藏电话号码的实用教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号