Skip to main content

使用混合方法抓取受 AWS WAF 保护的网站

 几天前,The Web Scraping Club 社区的一位成员询问了一些关于如何绕过 AWS WAF 保护以从 API 终端节点抓取数据的建议。

鉴于我们正在谈论抓取公共数据,我认为与您分享我研究过的解决方案可能会很有趣。

当然,以下技术必须用于合法目的,不得损害目标网站或其业务。

在深入研究解决方案之前,什么是 WAF,AWS WAF 的特点是什么?

什么是 WAF?

Web 应用程序防火墙 (WAF) 是一种专门的安全系统,旨在通过过滤和监控 Web 应用程序与 Internet 之间的 HTTP 流量来保护 Web 应用程序。它通过分析发送到 Web 应用程序的数据包和请求并根据预定义的安全规则过滤掉可能有害的请求来运行。WAF 的主要功能是防范常见的 Web 漏洞和漏洞,例如 SQL 注入、跨站点脚本 (XSS)、跨站点请求伪造 (CSRF) 和其他 OWASP 前 10 大威胁。

WAF 通常位于 Web 应用程序前面,充当客户端和服务器之间的中介。它检查传入和传出流量,允许合法流量通过,同时阻止恶意流量。此检查可以根据各种因素完成,例如 IP 地址、HTTP 标头、URL 模式和有效负载内容。

我们如何识别 AWS WAF?

虽然 Wappalyzer 无法识别这项技术,但您可以通过检查会话 cookie 轻松了解网站是否正在使用它。

如果您找到密钥 aws-waf-token,则网站正在使用 AWS WAF 是不言自明的。

根据我通过分析某些网站的行为所了解的情况,在浏览会话开始时,会向 AWS 服务器发送一个请求以验证您的浏览器配置。

正如您在有效负载中看到的那样,目前尚不清楚将发送到服务器的内容,并且需要一个逆向工程过程来了解后台发生的事情。

如果您已经关注此时事通讯一段时间,那么您已经知道我现在在说什么:这个过程很耗时并且需要不断更新,因此这是向网络爬虫销售商业解决方案的公司的任务。

如果我们的主要业务是销售数据,我们有两个选择:购买商业解决方案或使用我们拥有的工具发挥创意,使我们的抓取工具更接近人类。

事实上,与其对反机器人解决方案进行逆向工程,不如使用合法的硬件和软件堆栈模拟人类与网站交互是一种更有效的方法,能够持续更长的时间,因为它不应该受到反机器人发布的影响。

AWS WAF 的工作原理

正如我们在上一段中看到的,一旦我们访问网站,AWS WAF 就会在我们的浏览器后台引发挑战。如果配置看起来合法,我们会收到一个 cookie,证明我们已经通过了测试,并且我们可以在没有任何其他控制的情况下继续浏览,直到 cookie 弃用。

到期后,会抛出新的挑战,轮子会继续旋转。此测试的频率可能取决于网站配置,并且可能因情况而异。

正如我们几周前刚刚看到的 Bearer Token 一样,这是其他机器人保护措施的常见方法。


虽然这对网站来说是一种轻量级的方法,但由于没有持续监控访问者的活动,因此可以利用这种方法来编写一个高效的抓取工具,正如我们现在将在 Traveloka 的情况下看到的那样,Traveloka 是亚太地区的航班和酒店票价聚合器。


与往常一样,如果您想查看代码,可以访问 GitHub 存储库,可供付费读者使用。您可以在文件夹 53.AWS_WAF 中找到此示例

GitHub 存储库

如果您是其中之一但无法访问它,请写信给我 pier@thewebscraping.club 以获取它。


检查 Traveloka 网站

Traveloka 的网站具有该行业的传统架构:主页、酒店或航线的搜索栏,以及选择路线和出发时间后,不同航空公司的报价列表。

为了加载这些数据,通常前端后面有一个 API,Traveloka 也不例外。

我们有一个 POST 请求,其中包含 payload 中的路由信息和一些其他信息。

curl 'https://www.traveloka.com/api/v2/flight/search/oneway' \
  -H 'accept: */*' \
  -H 'accept-language: en-US,en;q=0.9' \
  -H 'content-type: application/json' \
  -H 'cookie: selectedCurrency=EUR; currentCountry=IT; tv-repeat-visit=true; countryCode=IT; aws-waf-token=b6ac2c13-29d5-4f86-95a5-73903c784c47:DgoAhDUoz7YDAAAA:lkKEO0jAbax0/WqI1zMHelpnt/rI3wGD+t+66c+UWYsRD9lPdvjz+Z2cRCSFSeXTSA4zbzakIrab0/ckkvsPKH1dWoGYjUfDTLlsZVBcTTSJrH8KCkE9ZhdlDg5euQQzEmOu074HbFQ0GlbAc4VQsHmRk7Xe5XQvYtYz0Jc/u5grIqwbw4p01TEHKsAGEGVuRc8=; tvl=A3IvxWd/GJSwQafHmC3w6G8ICzVtxyfiYeyuSJlhufE6pzKOC7QVMHH+jpKIeDLow+AT8npt8+iEbJ1BLVsP6RiBKGEWVBZkEO1axIeYcyrnR8L6zqiyLXL0w/O6kFJLtEIhxFAMDSrD5WCsfwMHSrzME0HNmMOjNr0lQfzMUfpIaFVPwPCxQefTLSs9kReGBfi1NjCikXdEeJc6ZJJKY4sMbejHr0QQfqAFOCYNBWPh2luex9wS4XFCiVupQ6ddUB0WEfH/Fm8=~djAy; tvs=bPqvVC1YfJBQjiihg7CLqsjuzDqXHA/FddWAXUK1S2YIFIYikdiRXT+S9MUEPFWf9jwKwywLLRwG/RDWJcxWk8wgL1JyYgbN+V/RmnEGgVk16FMMqrwcGWzYU/R6IiudR24D8oM7l+aAnoMIbMxTsdLrxOUpUEDJryabfA14+t2UpzgCsa4J54MfO9eZUqAjj1N3d3ifKRvxTUX5egZK6DrLPO/cO0pLSaUvZ2PfEyQgVkqmM0/COREh02kmGCZ3OuH8m4Mca1L3SrSiWgRAdp9q3jRE0/7HhVU=~djAy; _dd_s=logs=1&id=65e1ce4a-ac32-45b2-bf1d-25b0eb10afb0&created=1717653197178&expire=1717654107146&rum=0' \
  -H 'origin: https://www.traveloka.com' \
  -H 'priority: u=1, i' \
  -H 'referer: https://www.traveloka.com/en-en/flight/fullsearch?ap=DEL.BKK&dt=16-6-2024.NA&ps=1.0.0&sc=ECONOMY' \
  -H 'sec-ch-ua: "Brave";v="125", "Chromium";v="125", "Not.A/Brand";v="24"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  -H 'sec-fetch-dest: empty' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-site: same-origin' \
  -H 'sec-gpc: 1' \
  -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36' \
  -H 'x-domain: flight' \
  -H 'x-route-prefix: en-en' \
  --data-raw '{"fields":[],"clientInterface":"desktop","data":{"currency":"EUR","isReschedule":false,"locale":"en_EN","numSeats":{"numAdults":1,"numChildren":0,"numInfants":0},"seatPublishedClass":"ECONOMY","destinationAirportOrArea":"BKK","flexibleTicket":false,"flightDate":{"year":2024,"month":6,"day":16},"sourceAirportOrArea":"DEL","newResult":true,"seqNo":null,"searchId":"e55da74a-7ee0-4ede-8f34-1824f0d47d4c","visitId":"300d87cc-99fb-4d4f-9da1-ab767ca06ab5","utmId":null,"utmSource":null,"searchSpecRoutesTotal":1,"trackingContext":{"entrySource":""},"searchSpecRouteIndex":0,"journeyIndex":0}}'

使用 Curl 和 API 端点,我推断出与我们的范围相关的 Cookie 是:

  • selectedCurrency (所选货币)

  • 当前国家

  • 电视重复访问

  • countryCode (国家代码)

  • aws-waf-令牌

  • 电视

  • TVL

前四个可以设置为固定值,而后三个在我们开始浏览网站时分配给我们的浏览器会话。

出于测试目的,我们对请求使用相同的有效负载,因为在这种情况下更改航班的路线和日期并不重要。

第一次尝试:只用 Scrapy

让我们看看如果我们使用 Scrapy 获取数据,网站的行为如何,检查我们是否能够获得我们需要的 cookie。

在存储库的 Scrapy 文件夹中,您可以找到完整的抓取工具,我们基本上在其中为我们的请求使用一组合法的标头,加载主页,然后转到特定旅行路线的报价列表。

	HEADER={
	    "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
	    "accept-language": "en-US,en;q=0.5",
	    "cache-control": "max-age=0",
	    "priority": "u=0, i",
	    "sec-ch-ua": "\"Chromium\";v=\"124\", \"Brave\";v=\"124\", \"Not-A.Brand\";v=\"99\"",
	    "sec-ch-ua-mobile": "?0",
	    "sec-ch-ua-platform": "\"macOS\"",
	    "sec-fetch-dest": "document",
	    "sec-fetch-mode": "navigate",
	    "sec-fetch-site": "none",
	    "sec-fetch-user": "?1",
	    "sec-gpc": "1",
	    "upgrade-insecure-requests": "1",
		
	  }


	LOCATIONS = location_file.readlines()
	def start_requests(self):
		for i, url in enumerate(self.LOCATIONS):

			yield Request(url, callback=self.get_flights, headers=self.HEADER,  dont_filter=True)
	
	def get_flights_page(self, response):
		url='https://www.traveloka.com/en-en/flight/fullsearch?ap=DEL.BKK&dt=16-6-2024.NA&ps=1.0.0&sc=ECONOMY'
		yield Request(url, callback=self.read_token, headers=self.HEADER,  dont_filter=True)
		

	def read_cookies(self, response):
		print("End of scraper. No cookies get and cannot use the API")

虽然我们没有因为获取这些页面的 HTML 而被阻止,但这非常没有用。在选件页面代码中,没有有关不同票价的信息,因为它们是从 API 调用响应动态加载的。

此外,我们没有获得任何可用于调用 API 的有趣 cookie,因此此爬虫无处可去。我们需要改变我们的方法。

第二次尝试:Scrapy + Playwright

要从 Traveloka 抓取旅行票价,我们需要获取 API 终端节点所需的 Cookie,尤其是 aws-waf-token,并在我们的 post 请求中使用它们。

既然这些 cookie 是在我们第一次浏览网站时分配的,为什么我们不使用 Playwright 来收集它们,然后在 Scrapy POST 调用中注入它们呢?

通过这种方式,我们可以使用一个 Headful 解决方案来发出一个请求,然后使用 Scrapy 及其处理并行性的能力来创建一个能够在几分钟内处理数百个请求的高效抓取器。

事实上,一旦我们获得 aws-waf-token,至少对于 Traveloka,这将在四天内有效,因此我们可能只使用一个令牌来满足我们的所有抓取需求。

但是我们如何将 Playwright 和 Scrapy 混合在同一个 spider 中呢?

嗯,这是scrapy-Playwright库的任务,你可以在仓库的目录53.AWS-WAF/Scrapy-Playwright 中找到完整的代码,只有付费读者才能使用

使用 pip 安装 scrapy-Playwright 库很简单,就像它在 Scrapy spider 中的集成一样。

在 settings.py 文件中添加这些行 就足以在需要时在 scraper 中调用 Playwright。


DOWNLOAD_HANDLERS = {
    "http": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler",
    "https": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler",
}

TWISTED_REACTOR = "twisted.internet.asyncioreactor.AsyncioSelectorReactor"

PLAYWRIGHT_BROWSER_TYPE = "firefox"

PLAYWRIGHT_LAUNCH_OPTIONS = {
    "headless": False,
    "timeout": 20 * 1000,  # 20 seconds
}

此外,修改 scraper 也非常简单,并且在文档中有很好的描述

def start_requests(self):
	for i, url in enumerate(self.LOCATIONS):
			yield Request(url, callback=self.get_flights_page, headers=self.HEADER,  dont_filter=True, meta={"playwright": True, "playwright_include_page": True,'playwright_page_methods': [PageMethod('wait_for_timeout', 5000)]})
	
def get_flights_page(self, response):
	url='https://www.traveloka.com/en-en/flight/fullsearch?ap=DEL.BKK&dt=16-6-2024.NA&ps=1.0.0&sc=ECONOMY'
	yield Request(url, callback=self.read_cookies, headers=self.HEADER,  dont_filter=True, meta={"playwright": True, "playwright_include_page": True,'playwright_page_methods': [PageMethod('wait_for_timeout', 5000)]})
		

我们在 Scrapy 请求中的 meta 字典中添加参数

"playwright": True, 

使用 Playwright 而不是传统的 Scrapy 请求。

这将打开浏览器的窗口(我们在 settings.py 文件中选择的浏览器),并浏览器到所选 URL。

此外,我们还提供了选项

"playwright_include_page": True,'playwright_page_methods': [PageMethod('wait_for_timeout', 5000)]

,以便响应在 meta 参数中包含 Playwright Page 对象。

事实上,在接下来的步骤中,我们将使用此语法从响应中读取 cookie,以便我们可以在下一个 Scrapy 请求中使用它们。

async def read_cookies(self, response):
		page = response.meta["playwright_page"]
		cookies = await page.context.cookies()
		#print(cookies)
		await page.close()
		aws_waf_token=''
		tvl=''
		tvs=''
		for cookie in cookies:
			if cookie['name']== 'aws-waf-token':
				aws_waf_token=cookie['value']
			if cookie['name']== 'tvl':
				tvl=cookie['value']
			if cookie['name']== 'tvs':
				tvs=cookie['value']

您可以在存储库中找到完整的代码,如果您无法访问它,请在 pier@thewebscraping.club 写信给我,因为我需要手动授予您访问权限。

最后的考虑

用于 AWS WAF 的这种技术很有趣,可用于类似的使用案例,例如受 Akamai 保护的网站,在通过初始质询后,我们会得到一个 Cookie,该 Cookie 为我们在整个网站上开了一段时间的绿灯。

爬虫的初始 Playwright 部分是最重要的部分,因为反机器人会测试这些请求。Scrapy-Playwright 允许我们添加代理或通过 CDP 连接到反检测浏览器,以使第一步与真实步骤更加难以区分。

一旦我们得到 cookie,我们就可以使用 Scrapy 来扩展我们的数据收集,直到它们的过期日期。这个spider的一个改进可能是错误处理程序:当Scrapy开始返回错误时,我们可以通过再次加载Playwright页面并获取新的cookie来重新启动整个循环。

我希望这篇文章,即使很简单,也能帮助您完成当前或下一个抓取项目,我很高兴听到您的反馈。

Comments

Popular posts from this blog

10 Best Web Scraping Tools in 2025

Have you ever considered the methods used by businesses to collect large amounts of data for market research, price monitoring, sentiment analysis and lead generation? The answer is web scraping. Web scraping tools extract data from digital channels and transform it into easily readable information that can be analysed and manipulated. This information is crucial for businesses to target prospects and customers with relevant messages. However, web scraping is not without its challenges. It is becoming increasingly common for websites to employ sophisticated anti-scraping measures in order to block data extraction. It is therefore essential to select the appropriate tool for the task in hand. It is important to note that all local data protection and data usage laws must be adhered to. Use web scraping for legitimate purposes and contribute to making the Internet a less spammy place for all of us. We have compiled a list of the ten most suitable web scraping tools, highlighting their re...

2025年10种最佳网络爬虫

  您是否考虑过企业使用方法来收集大量数据以进行市场研究、价格监控、情绪分析和潜在客户生成? 答案是网络抓取。Web 抓取工具从数字渠道中提取数据并将其转换为易于阅读的信息,以供分析和操作。这些信息对于企业向潜在客户和客户提供相关信息至关重要。 然而,网络抓取并非没有挑战。网站采用复杂的反抓取措施来阻止数据提取变得越来越普遍。因此,为手头的任务选择合适的工具至关重要。 请务必注意,必须遵守所有当地数据保护和数据使用法律。将 Web 抓取用于合法目的,并有助于使 Internet 成为我们所有人的垃圾邮件较少的地方。 我们编制了一份十种最合适的网络抓取工具列表,突出了它们各自的优缺点,以帮助您选择最适合您需求的工具。🚀 选择网络抓取工具时的主要考虑因素是什么? 最有效的网络抓取工具是那些能够适应不断变化的数字环境的工具。在我们继续列出前 10 名之前,重要的是要强调一些需要寻找的关键功能。 易用性: 是任何数据提取工具的关键考虑因素。 在方法方面,有两个主要选项:无代码或可视化抓取。提供直观界面并专为点击式数据提取而设计的工具更适合初学者和非技术用户。 低代码: 对于更有经验的用户,允许通过编码进行灵活的 Web 爬虫设置和爬虫 API 自定义的框架可能更可取。 静态与动态: 该工具应该能够处理使用 JavaScript 或 AJAX 构建的网站,其中内容是动态加载的。 数据结构提取:  该工具应该能够以结构化的 Excel 格式(如 CSV)或原始 HTML 格式提取数据。 它还应该具有可扩展性并表现良好。 它应该能够使用云服务。基于云的数据抓取工具提供强大的基础设施和可扩展性,使其成为大型项目的理想选择。 多线程或并发: 该工具应该能够同时抓取多个页面,从而加快数据采集速度。 数据处理和存储:  虽然提取正确的数据是关键步骤,但这只是成功的一半。提供数据清理、转换和结构化功能的工具对于简化数据管理非常宝贵。 提供云存储的平台允许用户在线存储来自其 Web 抓取工具的所有数据,从而为数据提供集中且安全的数据存储库。这允许用户远程访问数据,从而降低数据存储成本。 其他注意事项:  为避免网站阻塞,建议使用提供轮换 IP 地址的工具。 无头浏览器:  这些是没有图形用户界面的 Web 浏览器,允许您模拟和自动化 Web ...

如何创建用于抓取 Telegram 频道的机器人

近年来,Telegram 已成为最受欢迎的通信、社区建设和共享内容平台之一。其独特的公共频道、私人群组和机器人结构使其成为研究人员、营销人员和开发人员的宝贵数据源。 我个人参加了几个 Telegram 群组,有些只是为了好玩,比如 Matched Betting 群组(不,我不这样做,我只是对它背后的数学感到好奇)到本地和全球新闻频道。 在本文中,我们将介绍抓取 Telegram 的基本要素,从设置您的第一个抓取工具到提取公共群组中的消息,再到检索其成员的信息。 寻找最有效的网站抓取方法是我们在咨询任务中提供的服务之一,此外还有旨在提高抓取操作的成本效率和可扩展性的项目。想了解更多?让我们取得联系。 为什么选择 Scrape Telegram? Telegram 是公开可用数据的宝库。您可以倾听社区中发生的事情,以了解 品牌如何被感知或用于 OSINT 目的,甚至可以为您的 AI 模型收集数据。 在开始之前,请记住,抓取 Telegram 需要明确的道德和法律框架。坚持使用可公开访问的数据并遵守平台的规则。 电报标志 了解 Telegram 的生态系统 在开始编写我们的爬虫之前,了解 Telegram 的结构至关重要: 公共频道: 对拥有 Telegram 帐户的任何人开放。它们主要用于广播消息。 公共群组: 成员可以在其中发布消息的讨论交互式空间。 私人频道/组: 访问需要邀请或批准。未经同意抓取这些是不道德的,并且可能是非法的。 机器人: 可以使用 Telegram 的 Bot API 以编程方式与之交互的自动化帐户。 本文将重点介绍如何抓取合法访问的公共频道和群组,尤其是在您不存储个人数据的情况下。 抓取电报的工具和技术 要抓取 Telegram,您有多种工具可供选择: 电报 API :  Telegram 提供了一个官方 API,允许您以编程方式与其平台进行交互。这是最可靠和可扩展的抓取方法。 Telethon : 一个 Python 库,可简化与 Telegram API 的交互。 Pyrogram : 另一个类似于 Telethon 的 Python 库,但具有一些附加功能。 BeautifulSoup/Selenium: 这些用于抓取 Telegram 的 Web 界面,但它们的效率较低且更容易出现自动化块问题。 我们将重点介绍如何将 Tele...