使用Python绕过动态加载:从弹出按钮中抓取隐藏电话号码的API方法

聖光之護
发布: 2025-11-03 12:27:00
原创
961人浏览过

使用Python绕过动态加载:从弹出按钮中抓取隐藏电话号码的API方法

本文将指导读者如何使用python从动态加载的网页弹出按钮中抓取隐藏的电话号码。针对beautifulsoup无法处理javascript动态内容的局限性,我们将采用直接模拟浏览器底层api请求的方法,通过分析网络流量,重构post请求,并解析json响应,高效地获取目标数据,避免了使用重量级自动化工具如selenium的复杂性。

1. 动态内容抓取的挑战与传统方法的局限性

网络爬虫实践中,我们经常会遇到内容并非直接嵌入在初始HTML中的情况。许多现代网站利用JavaScript动态加载数据,例如通过点击按钮弹出的对话框、无限滚动页面或异步更新的内容。对于这类场景,传统的HTML解析库如BeautifulSoup仅能处理请求获得的静态HTML内容,而无法执行JavaScript来渲染或加载动态数据。

例如,当尝试抓取一个只有在点击“联系方式”或“查看电话”按钮后才显示电话号码的网站时,如果仅使用BeautifulSoup,你可能会发现按钮对应的HTML元素中并不包含电话号码,而是一个占位符或触发JavaScript函数的代码。此时,BeautifulSoup的输出将只包含按钮本身,而无法获取到点击后才出现的信息。

虽然Selenium等工具可以模拟完整的浏览器行为,包括执行JavaScript和点击元素,但对于仅需获取特定动态加载数据的情形,Selenium往往显得过于重量级,会增加额外的开销和复杂性。更高效的方法是直接识别并模拟浏览器用于获取这些动态数据的底层API请求。

2. 识别目标API请求

获取动态加载数据的关键在于理解浏览器在后台是如何获取这些数据的。通常,当用户在网页上进行交互(如点击按钮)时,浏览器会向服务器发送一个异步请求(XHR/Fetch请求),服务器返回数据(通常是JSON格式),然后JavaScript再将这些数据渲染到页面上。

立即学习Python免费学习笔记(深入)”;

码上飞
码上飞

码上飞(CodeFlying) 是一款AI自动化开发平台,通过自然语言描述即可自动生成完整应用程序。

码上飞 138
查看详情 码上飞

要识别这些API请求,你需要使用浏览器的开发者工具:

  1. 打开开发者工具: 在Chrome、Firefox等浏览器中,按下F12键或右键点击页面选择“检查”/“检查元素”。
  2. 切换到“网络”(Network)选项卡: 此选项卡会记录浏览器发出的所有HTTP请求。
  3. 清空并模拟操作: 清空网络请求记录,然后点击页面上显示隐藏电话号码的按钮(例如“التواصل”按钮)。
  4. 查找相关请求: 观察网络记录中新出现的请求。通常,这些请求的类型是XHR或Fetch。你需要查找与电话号码数据相关的请求,它们往往是POST请求,并且响应内容是JSON格式。
  5. 分析请求详情: 选中目标请求,查看其“请求头”(Request Headers)、“请求载荷”(Request Payload)或“表单数据”(Form Data)以及“响应”(Response)内容。
    • 请求URL: 这是API的实际端点。
    • 请求方法: 通常是GET或POST。对于动态内容,POST请求携带数据的情况很常见。
    • 请求头: 包含User-Agent、Content-Type等,有时需要模拟。
    • 请求载荷/请求体: 这是最关键的部分,包含了API调用所需的参数,例如本例中的postId和GraphQL查询语句。
    • 响应: 查看API返回的数据结构,确认电话号码在哪个字段中。

通过分析,你会发现本例中电话号码数据是通过向 https://graphql.haraj.com.sa 发送一个POST请求,并携带一个GraphQL查询作为请求体来获取的。

3. 使用Python模拟API请求

一旦识别出API请求的所有细节,我们就可以使用Python的requests库来模拟这个请求。

import requests
import sys

def scrape_phone_number(post_id: int):
    """
    通过模拟API请求从Haraj网站抓取指定帖子的电话号码。

    Args:
        post_id (int): 帖子的唯一标识符。

    Returns:
        str: 提取到的电话号码,如果失败则返回None。
    """
    # GraphQL API的端点URL
    url = "https://graphql.haraj.com.sa"

    # 请求参数 (query string parameters)
    # 示例中这些参数可以为空,表示API可能对它们不敏感或有默认值
    params = {
        "queryName": "postContact",
        "token": "",
        "clientId": "",
        "version": ""
    }

    # 请求头,模拟浏览器行为
    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"
    }

    # 请求体 (payload),包含GraphQL查询和变量
    # 注意:'postId' 是动态获取电话号码的关键参数
    payload = {   
        "query": "query postContact($postId: Int!) {postContact(postId: $postId){contactText}}",
        "variables": {
            "postId": post_id
        }
    }

    try:
        # 发送POST请求,requests库会自动将payload转换为JSON格式
        response = requests.post(url, params=params, headers=headers, json=payload)

        # 检查HTTP状态码,如果不是2xx则抛出异常
        response.raise_for_status()

        # 解析JSON响应
        data = response.json()

        # 从JSON数据中提取电话号码
        contact_text = data.get('data', {}).get('postContact', {}).get('contactText')

        if contact_text:
            print(f"成功获取电话号码: {contact_text}")
            return contact_text
        else:
            print("未在响应中找到电话号码。")
            return None

    except requests.exceptions.RequestException as e:
        print(f"请求失败: {e}")
        return None
    except ValueError as e:
        print(f"JSON解析失败: {e}")
        return None

if __name__ == "__main__":
    # 示例帖子ID,这个ID通常需要从原始网页URL或HTML中提取
    # 例如,如果原始URL是 https://haraj.com.sa/1194697687,则 postId 可能是 94697687
    example_post_id = 94697687 

    phone_number = scrape_phone_number(example_post_id)
    if phone_number:
        print(f"最终提取的电话号码是: {phone_number}")
    else:
        print("未能提取电话号码。")

    sys.exit(0)
登录后复制

4. 代码解析与注意事项

  • requests.post(): 这是发送POST请求的关键函数。
    • url:API的完整URL。
    • params:对应URL中的查询字符串参数。
    • headers:自定义请求头,User-Agent是常见的模拟浏览器行为的头。
    • json:当请求体是JSON格式时,可以直接传入Python字典,requests会自动将其序列化为JSON字符串并设置Content-Type: application/json。
  • response.raise_for_status(): 这是一个良好的实践,用于检查请求是否成功(HTTP状态码为2xx)。如果请求失败,它会抛出一个requests.exceptions.RequestException异常。
  • response.json(): 将API返回的JSON响应解析成Python字典。
  • 数据提取: 通过字典的get()方法安全地访问嵌套数据,避免因键不存在而引发KeyError。
  • postId: 在这个特定的API中,postId是一个至关重要的变量。它通常需要从你最初访问的页面URL(例如https://haraj.com.sa/1194697687中的94697687部分)或其他HTML元素中动态提取。在实际应用中,你需要编写额外的代码来解析原始页面以获取这个ID。
  • 错误处理: 使用try-except块捕获可能的requests.exceptions.RequestException(网络错误、HTTP错误)和ValueError(JSON解析错误),增强代码的健壮性。
  • User-Agent: 模拟一个常见的浏览器User-Agent可以降低被网站识别为爬虫的风险。
  • API限制: 频繁或过快的API请求可能会触发网站的IP封禁或速率限制。在实际爬取时,应考虑添加延迟(time.sleep())或使用代理IP池。

5. 总结

当面对JavaScript动态加载内容的网站时,BeautifulSoup等静态HTML解析器会力不从心。此时,直接模拟浏览器底层的API请求是一种更高效、更直接的解决方案。通过熟练运用浏览器开发者工具分析网络流量,识别API端点、请求方法、请求头和请求体,我们可以精确地使用Python的requests库重构这些请求,从而绕过复杂的页面渲染过程,直接获取所需数据。这种方法不仅避免了Selenium的额外开销,也为处理各种动态网页爬取任务提供了强大的工具。

以上就是使用Python绕过动态加载:从弹出按钮中抓取隐藏电话号码的API方法的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号