GraphQL 是一种查询语言,用于从网站后端获取深度嵌套的结构化数据,类似于 MongoDB 查询。
请求通常是对某个通用 /graphql 端点的 POST,其正文如下:
但是,对于大型数据结构,这会变得低效 - 您在 POST 请求正文中发送大型查询,这(几乎总是)相同,并且仅在网站更新时发生变化; POST请求无法被缓存等。因此,开发了一个名为“持久查询”的扩展。这不是一个反抓取的秘密;而是一个秘密。您可以在此处阅读有关它的公共文档。
TLDR:客户端计算查询文本的 sha256 哈希值并仅发送该哈希值。此外,您可以将所有这些内容放入 GET 请求的查询字符串中,使其易于缓存。以下是来自 Zillow 的请求示例
如您所见,它只是有关 persistedQuery 扩展的一些元数据、查询的哈希值以及要嵌入查询中的变量。
这是来自 expedia.com 的另一个请求,以 POST 形式发送,但扩展名相同:
这主要优化了网站性能,但它给网页抓取带来了一些挑战:
- GET 请求通常更容易被阻止。
- 隐藏查询参数:我们不知道完整的查询,因此如果网站响应“未找到持久查询”错误(要求我们发送完整的查询,而不仅仅是哈希值),我们无法发送。
- 一旦网站发生了一点点变化,客户端开始请求新的查询 - 即使旧的查询可能仍然有效,服务器很快就会忘记它的 ID/散列,并且您使用此散列的请求将永远不会工作再次强调,因为您无法“提醒”服务器完整的查询文本。
因此,由于不同的原因,您可能会发现自己需要提取整个查询文本。您可以深入研究网站 JavaScript,如果幸运的话,您可能会在那里找到完整的查询文本,但通常,它是以某种方式从多个片段等动态构建的。
因此,我们想出了一个更好的方法:我们根本不碰客户端 JavaScript。相反,我们将尝试模拟客户端尝试使用服务器不知道的哈希的情况。因此,我们需要拦截浏览器发送的(有效)请求,并将哈希值修改为伪造的,然后再将其传递给服务器。
对于这个用例,存在一个完美的工具:mitmproxy,一个开源 Python 库,它可以拦截您自己的设备、网站或应用程序发出的请求,并允许您使用简单的 Python 脚本对其进行修改。
下载 mitmproxy,并准备一个 Python 脚本,如下所示:
import json def request(flow): try: dat = json.loads(flow.request.text) dat[0]["extensions"]["persistedQuery"]["sha256Hash"] = "0d9e" # any bogus hex string here flow.request.text = json.dumps(dat) except: pass
这定义了 mitmproxy 将在每个请求上运行的钩子:它尝试加载请求的 JSON 主体,将哈希修改为任意值,并将更新的 JSON 写入作为请求的新主体。
我们还需要确保将浏览器请求重新路由到 mitmproxy。为此,我们将使用名为 FoxyProxy 的浏览器扩展。它在 Firefox 和 Chrome 中均可用。
只需添加具有以下设置的路线:
现在我们可以使用以下脚本运行 mitmproxy:mitmweb -s script.py
这将打开一个浏览器选项卡,您可以在其中实时观看所有拦截的请求。
如果您转到特定路径并查看请求部分中的查询,您将看到一些垃圾值已替换了哈希值。
现在,如果您访问 Zillow 并打开我们尝试用于扩展的特定路径,然后转到响应部分,客户端会收到 PersistedQueryNotFound 错误。
Zillow 前端的反应是将整个查询作为 POST 请求发送。
我们直接从此 POST 请求中提取查询和哈希。为了确保 Zillow 服务器不会忘记此哈希,我们定期使用完全相同的查询和哈希运行此 POST 请求。这将确保即使服务器的缓存被清理或重置或网站发生更改,抓取工具也能继续工作。
结论
持久查询是 GraphQL API 的强大优化工具,通过最小化负载大小和启用 GET 请求缓存来增强网站性能。然而,它们也给网络抓取带来了重大挑战,主要是由于对服务器存储的哈希值的依赖以及这些哈希值可能无效的可能性。
使用 mitmproxy 拦截和操作 GraphQL 请求提供了一种有效的方法来显示完整的查询文本,而无需深入研究复杂的客户端 JavaScript。通过强制服务器响应 PersistedQueryNotFound 错误,我们可以捕获完整的查询负载并将其用于抓取目的。定期运行提取的查询可确保抓取器保持功能,即使发生服务器端缓存重置或网站发展也是如此。
以上是逆向工程 GraphQL persistedQuery 扩展的详细内容。更多信息请关注PHP中文网其他相关文章!

JavaScript字符串替换方法详解及常见问题解答 本文将探讨两种在JavaScript中替换字符串字符的方法:在JavaScript代码内部替换和在网页HTML内部替换。 在JavaScript代码内部替换字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 该方法仅替换第一个匹配项。要替换所有匹配项,需使用正则表达式并添加全局标志g: str = str.replace(/fi

本文讨论了在浏览器中优化JavaScript性能的策略,重点是减少执行时间并最大程度地减少对页面负载速度的影响。

将矩阵电影特效带入你的网页!这是一个基于著名电影《黑客帝国》的酷炫jQuery插件。该插件模拟了电影中经典的绿色字符特效,只需选择一张图片,插件就会将其转换为充满数字字符的矩阵风格画面。快来试试吧,非常有趣! 工作原理 插件将图片加载到画布上,读取像素和颜色值: data = ctx.getImageData(x, y, settings.grainSize, settings.grainSize).data 插件巧妙地读取图片的矩形区域,并利用jQuery计算每个区域的平均颜色。然后,使用

本文讨论了使用浏览器开发人员工具的有效JavaScript调试,专注于设置断点,使用控制台和分析性能。

本文将引导您使用jQuery库创建一个简单的图片轮播。我们将使用bxSlider库,它基于jQuery构建,并提供许多配置选项来设置轮播。 如今,图片轮播已成为网站必备功能——一图胜千言! 决定使用图片轮播后,下一个问题是如何创建它。首先,您需要收集高质量、高分辨率的图片。 接下来,您需要使用HTML和一些JavaScript代码来创建图片轮播。网络上有很多库可以帮助您以不同的方式创建轮播。我们将使用开源的bxSlider库。 bxSlider库支持响应式设计,因此使用此库构建的轮播可以适应任何

核心要点 利用 JavaScript 增强结构化标记可以显着提升网页内容的可访问性和可维护性,同时减小文件大小。 JavaScript 可有效地用于为 HTML 元素动态添加功能,例如使用 cite 属性自动在块引用中插入引用链接。 将 JavaScript 与结构化标记集成,可以创建动态用户界面,例如无需页面刷新的选项卡面板。 确保 JavaScript 增强功能不会妨碍网页的基本功能至关重要;即使禁用 JavaScript,页面也应保持功能正常。 可以使用高级 JavaScript 技术(

数据集对于构建API模型和各种业务流程至关重要。这就是为什么导入和导出CSV是经常需要的功能。在本教程中,您将学习如何在Angular中下载和导入CSV文件


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

Dreamweaver CS6
视觉化网页开发工具

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

记事本++7.3.1
好用且免费的代码编辑器

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中