逐步使用Python刮擦
#网络开发人员 #python #网络安全 #scraping

刮擦应该是关于extracting content from HTML。听起来很简单,但有许多障碍。第一个是获得上述HTML。为此,我们将使用 python避免检测

可能需要绕过反机器人系统。网络刮擦而不会使用python或任何其他工具被阻止,这是在公园里散步的。

网站倾向于保护其数据和访问。防御系统可以采取许多可能的行动。与我们一起学习如何使用 Requests Playwright

注意:按大规模测试时,切勿直接使用家庭IP。一个小错误或滑倒,您将被禁止。

另外,这是出于信息目的,并确保您在授权的网站或平台上使用它。

先决条件

要使代码工作,您将需要Python 3 installed。一些系统已预装。之后,通过运行PIP安装来安装所有必要的库。

pip install requests playwright 
npx playwright install

IP率限制

最基本的安全系统是从同一IP禁止或节气门请求。这意味着常规用户不会在几秒钟内要求一百页,因此连接将被标记为危险。

import requests 

response = requests.get('http://httpbin.org/ip') 
print(response.json()['origin']) 
# xyz.84.7.83

IP率限制与API速率限制相似,但通常没有公共信息。我们可以确定我们可以安全地提出多少要求。

我们的互联网服务提供商为我们分配了我们的IP,我们可以影响或掩盖。解决方案是更改它。我们可以修改机器的IP,但可以使用不同的机器。数据中心可能具有不同的IP,尽管这不是真正的解决方案。

代理是。他们提出了传入的请求,并将其传递到最终目的地。它在那里没有处理。但这足以掩盖我们的IP并绕过块,因为目标网站将看到代理的IP。

旋转代理

即使我们不推荐它们,也有free proxies。他们可能会用于测试,但可靠。在某些示例中可以看出,我们可以使用其中一些进行测试。

现在我们有不同的IP,我们的家庭连接是安全且合理的。好的。但是,如果他们阻止代理IP怎么办?我们回到初始位置。

我们不会详细介绍免费代理。只需使用the next one on the list即可。由于它们的寿命通常很短,因此经常更改它们。

付费代理服务,另一方面提供IP旋转。我们的服务将类似地工作,但是该网站会看到不同的IP。在某些情况下,它们每次请求或每隔几分钟都旋转。无论如何,他们很难禁止。当它发生时,我们将很快获得新的IP。

import requests 

proxies = {'http': 'http://190.64.18.177:80'} 
response = requests.get('http://httpbin.org/ip', proxies=proxies) 
print(response.json()['origin']) # 190.64.18.162

我们知道这些;这意味着机器人检测服务也知道它们。一些大公司将阻止已知代理IP或数据中心的流量。对于这些情况,有一个较高的代理水平:住宅。

住宅代理更昂贵,有时是带宽限制的,但它们为我们提供了普通人使用的IP。这意味着我们的移动提供商可以明天分配IP。或昨天有一个朋友。他们与实际最终用户没有区别。

我们可以刮擦我们想要的任何东西,对吗?默认情况下,便宜的价格便宜,必要时昂贵。不,还没有。我们只通过了第一个障碍,还有一些障碍。我们必须看起来像合法的用户,以免被标记为机器人或刮刀。

用户代理标头

下一步将是检查我们的请求标题。最著名的是User-Agent(简称UA),但还有更多。 ua遵循我们将稍后再见的格式,例如,许多软件工具,例如Googlebot,都有自己的。

如果我们使用Python请求或直接卷曲,则目标网站将收到的内容。

import requests 

 

response = requests.get('http://httpbin.org/headers') 

print(response.json()['headers']['User-Agent']) 

# python-requests/2.25.1

curl http://httpbin.org/headers # { ... "User-Agent": "curl/7.74.0" ... }

许多网站都会检查UA,但这对于这样做的网站是一个巨大的危险信号。我们必须伪造它。幸运的是,大多数库都允许自定义标题。按照示例使用请求:

import requests 

 

headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"} 

response = requests.get('http://httpbin.org/headers', headers=headers) 

print(response.json()['headers']['User-Agent']) # Mozilla/5.0 ...

要获取当前的用户代理,请访问httpbin,就像代码片段所做的那样并复制它。 请求使用相同UA的所有URL也可能触发一些警报,使解决方案更加复杂。

理想情况下,我们将拥有所有当前可能的用户代理,并像对IPS一样旋转它们。由于这几乎是不可能的,我们至少可以有一些。有lists of User-Agents可供我们选择。

import requests 

import random 

 

user_agents = [ 

        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', 

        'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36', 

        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36', 

        'Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148', 

        'Mozilla/5.0 (Linux; Android 11; SM-G960U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Mobile Safari/537.36' 

] 

user_agent = random.choice(user_agents) 

headers = {'User-Agent': user_agent} 

response = requests.get('https://httpbin.org/headers', headers=headers) 

print(response.json()['headers']['User-Agent']) 

# Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) ...

请记住,浏览器经常更改版本,并且该列表可以在几个月内过时。如果我们要使用用户代理旋转,那么可靠的来源至关重要。我们可以手工做或使用服务提供商。

我们更近了,但是标题中仍然存在一个缺陷:反机器人系统也知道此技巧,并检查其他标题以及用户代理。

全套标题

每个浏览器甚至版本都会发送不同的标题。检查Chrome和Firefox的作​​用:

{ 

        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 

        "Accept-Encoding": "gzip, deflate, br", 

        "Accept-Language": "en-US,en;q=0.9", 

        "Host": "httpbin.org", 

        "Sec-Ch-Ua": "\"Chromium\";v=\"92\", \" Not A;Brand\";v=\"99\", \"Google Chrome\";v=\"92\"", 

        "Sec-Ch-Ua-Mobile": "?0", 

        "Sec-Fetch-Dest": "document", 

        "Sec-Fetch-Mode": "navigate", 

        "Sec-Fetch-Site": "none", 

        "Sec-Fetch-User": "?1", 
        "Upgrade-Insecure-Requests": "1", 
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36" 

}

{ 

        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 
        "Accept-Encoding": "gzip, deflate, br", 
        "Accept-Language": "en-US,en;q=0.5", 
        "Host": "httpbin.org", 
        "Sec-Fetch-Dest": "document", 
        "Sec-Fetch-Mode": "navigate", 
        "Sec-Fetch-Site": "none", 
        "Sec-Fetch-User": "?1", 
        "Upgrade-Insecure-Requests": "1", 
        "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:90.0) Gecko/20100101 Firefox/90.0" 
}

这意味着您认为这意味着什么。以前的具有五个用户代理的数组不完整。我们需要每个用户代理具有完整标题的数组。对于简洁起见,我们将显示一个带有一项的列表。已经足够长了。

在这种情况下,复制httpbin的结果不够。理想是将其直接从源复制。 Firefox,Chrome Devtools或您的浏览器等效的最简单方法。

转到“网络”选项卡,访问目标网站,右键单击请求,然后复制为curlâ。然后convert the cURL syntax to Python并将标题粘贴到列表中。

import requests 

import random 

 

headers_list = [{ 

        'authority': 'httpbin.org', 

        'cache-control': 'max-age=0', 

        'sec-ch-ua': '"Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"', 

        'sec-ch-ua-mobile': '?0', 

        'upgrade-insecure-requests': '1', 

        'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36', 

        'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 

        'sec-fetch-site': 'none', 

        'sec-fetch-mode': 'navigate', 

        'sec-fetch-user': '?1', 

        'sec-fetch-dest': 'document', 

        'accept-language': 'en-US,en;q=0.9', 

} # , {...} 

] 

headers = random.choice(headers_list) 

response = requests.get('https://httpbin.org/headers', headers=headers) 

print(response.json()['headers'])

我们可以为额外的安全性添加推荐人标头,例如Google或同一网站的内部页面。它将掩盖我们始终在没有互动的情况下直接要求URL的事实。

但是要小心,因为添加推荐人会更改更多标题。您不希望您的python请求脚本被这样的错误所阻止。

cookie

我们忽略了上面的cookies,因为它们应该得到一个单独的部分。 cookie可以帮助您绕过一些反机器人或阻止您的请求。它们是我们需要正确理解的强大工具。

例如,cookie可以跟踪用户会话,并在登录后记住该用户。网站为每个新用户分配一个cookie会话。有很多方法可以做到这一点,但是我们会尝试简化。然后,用户的浏览器将在每个请求中发送该cookie,以跟踪用户的活动。

这是怎么回事?我们使用旋转代理,因此每个请求可能与不同地区或国家 /地区具有不同的IP。反机器人可以看到并阻止该模式,因为这不是用户浏览的自然方式。

另一方面,一旦绕过反机器人解决方案,它将发送有价值的饼干。防守系统是否会检查两次是否看起来合法。查看how to bypass Cloudflare以获取更多信息。

cookie会帮助我们的python请求脚本以避免检测机器人吗?还是他们会伤害我们并使我们被阻止?答案在于我们的实施。

对于简单的情况,不发送cookie可能最有效。无需维护会话。

对于更高级的案例和反机器软件,会话cookie可能是访问和刮擦最终内容的唯一方法。始终考虑会话请求和IP必须匹配。

如果我们希望在XHR调用后在浏览器中生成的内容,也会发生同样的情况。我们需要使用无头浏览器。初始加载后,JavaScript将尝试使用XHR调用来获取一些内容。我们可以在受保护的站点上没有cookie进行电话。

我们将如何使用无头浏览器,特别是剧作家来避免检测?继续阅读!

无头浏览器

浏览器解决JavaScript挑战之后,某些反机器人系统只会显示内容。我们可以使用Python请求来模拟这样的浏览器行为。我们需要一个具有JavaScript执行的浏览器来运行并通过挑战。

SeleniumPuppeteer和剧作家是最常用和已知的库。出于绩效原因避免它们是可取的,并且它们会使刮擦速度较慢。但是有时候没有其他选择。

我们将看到如何参加剧作家。下面的摘要显示了一个简单的脚本,访问了打印已发送标题的页面。输出仅显示用户代理,但是由于它是一个真正的浏览器,因此标头将包含整个集合(接受,接受编码等)。

import json 

from playwright.sync_api import sync_playwright 

with sync_playwright() as p: 

        for browser_type in [p.chromium, p.firefox, p.webkit]: 

                browser = browser_type.launch() 
                page = browser.new_page() 
                page.goto('https://httpbin.org/headers') 
                jsonContent = json.loads(page.inner_text('pre')) 
                print(jsonContent['headers']['User-Agent']) 
                browser.close() 

# Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/93.0.4576.0 Safari/537.36 

# Mozilla/5.0 (X11; Linux x86_64; rv:90.0) Gecko/20100101 Firefox/90.0 

# Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Safari/605.1.15

这种方法带有自己的问题:看看用户代理。 Chromium One包括无头Chrome ,它将告诉目标网站是无头浏览器。他们可能会采取行动。

回到标题部分:我们可以添加自定义标题,以覆盖默认的标题。用本摘要中的一行替换该行,然后粘贴有效的用户代理:

koude9_page(extra_http_headers={'User-Agent': '...'})

这只是带有无头浏览器的入门级。无头检测本身就是一个领域,许多人正在努力。有些可以检测到它,有些则避免被阻止。例如,您可以使用实际的浏览器和无头浏览器访问Pixelscan。要被视为一致,您需要努力工作。

查看下面的屏幕截图,与剧作家一起访问Pixelscan时拍摄。看到UA吗?我们伪造的那个是正确的,但是他们可以通过检查导航器JavaScript API来检测到我们躺着的。

我们可以通过user_agent,剧作家将在JavaScript和我们的标题中设置用户代理。很好!

page = koude9_page(user_agent='...')

您可以轻松地将Playwright stealth添加到脚本中,以使其更高级的情况,从而使检测更加困难。它处理标题和浏览器JavaScript API之间的不一致之处。

总而言之,拥有100%的覆盖范围很复杂,但是您大多数时候都需要它。网站总是可以进行更复杂的检查:WebGL,触摸事件或电池状态。

除非您试图刮擦需要bypassing an anti-bot solution, like Akamai的网站,否则您将不需要这些额外的功能。对于这些情况,额外的努力将是强制性的。老实说,要求。

地理极限或地理障碍

您是否曾经尝试过从美国以外观看CNN?

称为geo-blocking。只有来自美国内部的连接才能现场观看CNN。我们可以使用Virtual Private Network (VPN)绕过它。然后,我们可以照常浏览,但是由于VPN。

,该网站将看到本地IP。

用地理障碍物刮擦网站时也会发生同样的情况。代理有一个等效的:地理分配的代理。一些代理提供商允许我们从国家列表中进行选择。通过激活该激活,我们将仅从美国获得本地IP。

行为模式

阻止IP和用户代理已经不够了。如果不是几分钟,它们就变得难以控制和陈旧。如果我们使用干净的IP和实际用户代理执行请求,我们主要是安全的。

涉及更多因素,但大多数请求应有效。

但是,大多数现代反机器软件都使用机器学习和行为模式,而不仅仅是静态标记(IP,UA,Geolocation)。这意味着如果我们始终以相同顺序执行相同的动作

,我们将被检测到。
  1. 转到主页。
  2. 单击“商店”按钮。
  3. 向下滚动。
  4. 转到第2页。

几天后,启动相同的脚本可能会导致每个请求都被阻止。许多人可以执行相同的动作,但是机器人具有使它们显而易见的东西:速度。

使用软件,我们将依次执行每个步骤,而实际用户将花一秒钟,然后单击,使用鼠标轮子慢慢向下滚动,将鼠标移至链接,然后单击。

也许没有必要伪造所有这些,但是要知道可能的问题并知道如何面对它们。

我们必须考虑我们想要的东西。也许我们不需要第一个请求,因为我们只需要第二页。我们可以将其用作切入点,而不是主页。

并保存一个请求。它可以扩展到每个域的数百个URL。无需访问每个页面;向下滚动,单击下一页,然后重新开始。

要刮擦搜索结果,一旦我们识别了分页的URL模式,我们只需要两个数据点:每个页面的项目数量和项目。大多数时候,该信息都存在于首页或请求。

import requests 
from bs4 import BeautifulSoup 

response = requests.get('https://scrapeme.live/shop/') 
soup = BeautifulSoup(response.content, 'html.parser') 
pages = soup.select('.woocommerce-pagination a.page-numbers:not(.next)') 
print(pages[0].get('href')) # https://scrapeme.live/shop/page/2/ 
print(pages[-1].get('href')) # https://scrapeme.live/shop/page/48/

一个请求向我们表明有48页。我们现在可以排队。与其他技术混合在一起,我们将从此页面上刮擦内容并添加其余47。要通过绕过反机器人系统来刮擦它们,我们可以:

  • 洗牌订单以避免模式检测。
  • 使用不同的IP和用户代理,因此每个请求看起来都是新的。
  • 在某些电话之间添加延迟。
  • 随机使用Google作为推荐人。

我们可以编写一些混合所有这些片段,但是现实生活中最好的选择是使用所有这些工具,例如Scrapypyspidernode-crawler(Node.js)(Node.js)或Colly(GO)。

摘要的想法是单独理解每个问题。但是,对于大规模的现实生活项目,独立处理所有内容都太复杂了。

CAPTCHA

即使是最好的准备请求也可以被抓住并显示CAPTCHA。如今,解决验证码可以实现使用抗验码和2captcha等解决方案,但浪费时间和金钱。 最好的解决方案是避免它们。第二好的是忘记该请求和重试。

例外很明显:在第一次访问时总是显示验证码的站点。如果没有办法绕过它,我们必须解决它。

然后,使用会话cookie避免再次受到挑战

这听起来可能违反直觉,但是等待第二秒,然后用不同的IP和集合器恢复相同的请求要比求解验证码要快。自己尝试一下,并告诉我们有关体验的信息。

成为一个好的互联网公民

我们可以使用多个网站进行测试,但是在大规模进行相同操作时要小心。尝试成为一个好的互联网公民,不会导致DDOS。限制每个域的交互。亚马逊每秒可以处理数千个请求,但并非所有目标站点都可以。

我们总是在谈论“只读”浏览模式。访问页面并阅读其内容。切勿提交表格或以恶意意图执行主动行动。

如果我们采用更活跃的方法,其他几个因素将重要:写作速度,鼠标移动,导航而无需单击,同时浏览许多页面等。预防机器人预防软件特别具有积极性,具有主动动作。由于安全原因应该应该。

我们会讨论这部分,但是这些行动将为他们提供阻止请求的新理由。同样,好公民不会尝试大量登录。我们谈论的是刮擦,而不是恶意活动。

有时网站会使数据收集更加困难,也许不是故意的。但是,借助现代前端工具,CSS课程可能每天都会改变,破坏彻底准备的脚本。有关更多详细信息,请阅读我们先前在how to scrape data in Python上的条目。

结论

我们喜欢您记住低悬挂的水果:

  1. IP旋转代理。
  2. 挑战目标的住宅代理。
  3. 全套标头,包括用户代理。
  4. 当需要JavaScript挑战时,请与剧作家进行绕过机器人检测,也许添加隐形模块。
  5. 避免使用可能将您标记为机器人的图案。还有更多,也许我们没有封面。但是有了这些技术,您应该能够大规模爬行和刮擦。毕竟,如果您知道如何进行网络刮擦而不会被python阻止。

如果您发现这篇文章令人兴奋,请在Learnhub Blog上找到更多令人兴奋的帖子;我们编写从Cloud computingFrontend DevCybersecurityAIBlockchain的所有技术。

这是由ZenRows撰写的,由Leaernhub Blog编辑。

资源