如何使用Selenium Stealth进行网页抓取

如何使用Selenium Stealth进行网页抓取

您的 Selenium 网络抓取工具是否曾被屏蔽过?网站使用 Selenium 的自动化属性来检测和阻止您。但是您可以使用 Selenium Stealth 插件屏蔽您的机器人以加强它。

在本教程中,您将学习如何在 Python 中使用 Selenium 进行网络抓取 而不会被阻止。我们将向您展示如何集成 Selenium Stealth,然后查看一些替代方案。

什么是 Selenium Stealth

Selenium 最初是为了测试网站行为而开发的,现在已迅速成为一种流行的网络抓取工具。它在抓取动态网站时很有用,因为它像实际浏览器一样呈现 JavaScript,并支持类似浏览器的操作,例如单击和填写表单。

Selenium 用途广泛,能够通过 WebDriver 中间件自动化不同的浏览器,包括 Chrome、Firefox、Safari 等。但是,由于内置的​​自动化属性和命令行标志,反机器人措施可以轻松检测到它。

这就是Selenium Stealth 插件发挥关键作用的地方。通过掩盖检测泄漏,它使您能够绕过反机器人检测。

先决条件

在我们深入研究在 Python 中使用 Selenium Stealth 进行抓取之前,让我们看看基本的 Selenium 是如何被阻止的。作为目标,我们将使用OpenSea,一个具有反机器人保护的网站。

要继续学习本教程,请确保您已安装Python。然后,使用以下命令安装 Selenium:

pip install selenium

Selenium 支持大多数主流浏览器,但可以说 Chrome 是最常用的。因此,在这种情况下我们将使用 Chromium。

现在,安装WebDriver Manager,这是一个开源库,用于管理和维护 Selenium 所需的驱动程序。这样,您就不必担心下载 ChromeDriver

pip install webdriver-manager

初始化 Chrome WebDriver 实例,将服务和选项对象作为参数传递。

# create a new Chrome webdriver instance, passing in the Service and options objects
driver = webdriver.Chrome(service=service, options=options)

最后,导航到目标网站并截取屏幕截图。

# navigate to the webpage
driver.get('https://opensea.io/')

# Wait for page to load
while driver.execute_script("return document.readyState") != "complete":
    pass

# take a screenshot of the webpage
driver.save_screenshot('screenshot.png')

# close the webdriver
driver.quit()

将所有内容放在一起,您的完整代码应如下所示:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager

# create a new Service instance and specify path to Chromedriver executable
service = ChromeService(executable_path=ChromeDriverManager().install())
 
# create ChromeOptions object
options = webdriver.ChromeOptions()
options.add_argument('--headless')


# create a new Chrome webdriver instance, passing in the Service and options objects
driver = webdriver.Chrome(service=service, options=options)

# navigate to the webpage
driver.get('https://opensea.io/')
 
# take a screenshot of the webpage
driver.save_screenshot('opensea-blocked.png')
 
# close the webdriver
driver.quit()

这是我们截取的屏幕截图:

medium_nowsecure_blocked_1d5ee9da44

上面的结果表明 base Selenium 被 OpenSea 的反机器人挑战阻止了。

现在,让我们尝试使用 Stealth 插件抓取同一个网站。

如何在 Python 中使用 Selenium Stealth 进行网页抓取

以下是我们在 Python 中使用 Selenium Stealth 进行抓取的步骤:

第 1 步:安装并导入 Selenium Stealth

使用以下命令安装 Selenium Stealth:

pip install selenium-stealth

现在,像我们之前的脚本一样创建一个新的 Python 文件和一个新的服务实例。然后,从 Selenium Stealth 导入 Stealth 以及 Service 和 WebDriver 模块。

from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
from selenium_stealth import stealth

# create a new Service instance and specify path to Chromedriver executable
service = ChromeService(executable_path=ChromeDriverManager().install())

第 2 步:更改浏览器属性

您可以更改默认的浏览器属性,例如navigator.webdriver、自动化控制的功能、视口等。

为此,请创建一个 Chrome 选项对象并设置所需的不同 ChromeDriver 选项,包括无头模式。例如:

# create a ChromeOptions object
options = webdriver.ChromeOptions()

#run in headless mode
options.add_argument("--headless")

# disable the AutomationControlled feature of Blink rendering engine
options.add_argument('--disable-blink-features=AutomationControlled')

# disable pop-up blocking
options.add_argument('--disable-popup-blocking')

# start the browser window in maximized mode
options.add_argument('--start-maximized')

# disable extensions
options.add_argument('--disable-extensions')

# disable sandbox mode
options.add_argument('--no-sandbox')

# disable shared memory usage
options.add_argument('--disable-dev-shm-usage')

此外,将该navigator.webdriver属性设置为未定义。为此,创建一个新的驱动程序实例并调用driver.execute_script()下面代码中的函数。

#create a new driver instance
driver = webdriver.Chrome(service=Service, options=options)

# Change the property value of the navigator for webdriver to undefined
driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")

属性现在被屏蔽了。

第 3 步:轮换用户代理

Selenium Stealth 启用其他功能,例如旋转用户代理。为此,首先导入random,然后定义用户代理字符串列表。

//...
import random

user_agents = [
    # Add your list of user agents here
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15',
]

从您的列表中选择一个随机用户代理,然后使用 将其添加到浏览器选项中options.add_argument

user_agent = random.choice(user_agents)

options.add_argument(f'user-agent={user_agent}')

您还可以使用 设置用户代理execute_cdp_cmd

driver.execute_cdp_cmd('Network.setUserAgentOverride', {"userAgent": user_agent})

完毕!您每次都会请求不同的 UA。

第 4 步:隐身刮擦

现在我们已经用 Selenium Stealth 强化了我们的 Python 抓取器,是时候看看我们是否可以抓取之前阻止我们的页面了。

首先,使用指定的选项和服务模块初始化 Chrome 驱动程序。

driver = webdriver.Chrome(service=Service("chromedriver.exe"), options=options)

然后,通过应用函数启用隐身模式stealth,如下面的代码所示。

stealth(driver,
        languages=["en-US", "en"],
        vendor="Google Inc.",
        platform="Win32",
        webgl_vendor="Intel Inc.",
        renderer="Intel Iris OpenGL Engine",
        fix_hairline=True,
        )

最后,导航到目标网站,等待页面加载,然后截图。

#navigate to opensea
driver.get('https://opensea.io/')

# Wait for page to load
while driver.execute_script("return document.readyState") != "complete":
    pass

# Take screenshot
driver.save_screenshot("opensea.png")

# Close browser
driver.quit()

将所有这些放在一起,这是我们完整的代码:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
from selenium_stealth import stealth
import random

# create a new Service instance and specify path to Chromedriver executable
service = ChromeService(executable_path=ChromeDriverManager().install())

# Step 2: Change browser properties
# create a ChromeOptions object
options = webdriver.ChromeOptions()

#run in headless mode
options.add_argument("--headless")

# disable the AutomationControlled feature of Blink rendering engine
options.add_argument('--disable-blink-features=AutomationControlled')
 
# disable pop-up blocking
options.add_argument('--disable-popup-blocking')
 
# start the browser window in maximized mode
options.add_argument('--start-maximized')
 
# disable extensions
options.add_argument('--disable-extensions')
 
# disable sandbox mode
options.add_argument('--no-sandbox')
 
# disable shared memory usage
options.add_argument('--disable-dev-shm-usage')


# Set navigator.webdriver to undefined
# create a driver instance
driver = webdriver.Chrome(service=service, options=options)

# Change the property value of the navigator for webdriver to undefined
driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")



# Step 3: Rotate user agents 
user_agents = [
    # Add your list of user agents here
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15',
]

# select random user agent
user_agent = random.choice(user_agents)

# pass in selected user agent as an argument
options.add_argument(f'user-agent={user_agent}')


# Step 4: Scrape using Stealth
#enable stealth mode
stealth(driver,
        languages=["en-US", "en"],
        vendor="Google Inc.",
        platform="Win32",
        webgl_vendor="Intel Inc.",
        renderer="Intel Iris OpenGL Engine",
        fix_hairline=True,
        )

# navigate to opensea
driver.get("https://opensea.io/")
 
# Wait for page to load
while driver.execute_script("return document.readyState") != "complete":
    pass
 
# Take screenshot
driver.save_screenshot("opensea.png")
 
# Close browser
driver.quit()

这是我们将获得的屏幕截图:

medium_image3_060c57fa24

恭喜,您已经成功避免了Selenium 检测

Selenium Stealth 和替代品的局限性

虽然 Selenium Stealth 在绕过 OpenSea 等方面做了很多工作,但它无法绕过一些高级反机器人检测技术。

让我们在NowSecure上尝试我们的 Selenium Stealth 脚本,该网页使用反机器人挑战测试您的请求,如果成功则提示“您通过了”消息。

将我们之前的目标 URL 替换为nowsecure.nl,我们有以下代码:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
from selenium_stealth import stealth
import random

# create a new Service instance and specify path to Chromedriver executable
service = ChromeService(executable_path=ChromeDriverManager().install())


# Step 2: Change browser properties
# create a ChromeOptions object
options = webdriver.ChromeOptions()

#run in headless mode
options.add_argument("--headless")

# disable the AutomationControlled feature of Blink rendering engine
options.add_argument('--disable-blink-features=AutomationControlled')
 
# disable pop-up blocking
options.add_argument('--disable-popup-blocking')
 
# start the browser window in maximized mode
options.add_argument('--start-maximized')
 
# disable extensions
options.add_argument('--disable-extensions')
 
# disable sandbox mode
options.add_argument('--no-sandbox')
 
# disable shared memory usage
options.add_argument('--disable-dev-shm-usage')


# Set navigator.webdriver to undefined
# create a driver instance
driver = webdriver.Chrome(service=Service, options=options)

# Change the property value of the navigator for webdriver to undefined
driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")



# Step 3: Rotate user agents 
user_agents = [
    # Add your list of user agents here
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15',
]

# select random user agent
user_agent = random.choice(user_agents)

# pass in selected user agent as an argument
options.add_argument(f'user-agent={user_agent}')

# set user agent using execute_cpd_cmd
driver.execute_cdp_cmd('Network.setUserAgentOverride', {"userAgent": user_agent})


# Step 4: Scrape using Stealth
#enable stealth mode
stealth(driver,
        languages=["en-US", "en"],
        vendor="Google Inc.",
        platform="Win32",
        webgl_vendor="Intel Inc.",
        renderer="Intel Iris OpenGL Engine",
        fix_hairline=True,
        )

# navigate to nowsecure
driver.get("https://nowsecure.nl/")
 
# Wait for page to load
while driver.execute_script("return document.readyState") != "complete":
    pass
 
# Take screenshot
driver.save_screenshot("nowsecure.png")
 
# Close browser
driver.quit()

这是我们得到的截图:

medium_image1_265ffcd83b

上面的屏幕截图证明 Selenium Stealth 是不够的,并且不能对抗高级 Cloudflare 保护。

您可以查看如何使用 Selenium 绕过 Cloudflare,以获取有关如何绕过它的详细说明。

另一个可以帮助您避免使用 Selenium 进行检测的 Python 库是Undetected ChromeDriver。它比 Selenium Stealth 维护得更好,但也有类似的局限性,因为它不适用于许多网站。

这就提出了一个问题:什么有效?

幸运的是,无论复杂程度如何,ZenRows 库都提供了绕过反机器人检测的终极解决方案。让我们看看它对 NowSecure 的作用,Selenium Stealth 在这里失败了。

免费领取1000次ZenRows API网页爬取
pip install zenrows

接下来,导入 ZenRows 客户端并使用您的 API 密钥创建一个新实例。

from zenrows import ZenRowsClient

#Create a new zenrowsClient instance 
client = ZenRowsClient("APIKey")

指定您的目标 URL 并设置必要的参数。要绕过反机器人措施,您必须将antibot和参数设置为。premium_proxyjs_rendertrue

url = "https://nowsecure.nl/"
params = {"js_render":"true","antibot":"true","premium_proxy":"true"}

最后,GET使用预定义参数发出请求。您的完整代码应如下所示:

from zenrows import ZenRowsClient
 
#create new zenrowsclient instance
client = ZenRowsClient("Your_API_Key")

url = "https://nowsecure.nl/"
#define the necessary parameters
params = {"js_render":"true","antibot":"true","premium_proxy":"true"}
 
#make a get request 
response = client.get(url, params=params)
 
print(response.text)

结果如下:

medium_image4_1ca11a0931

结论

Selenium 是一种流行的网络抓取和自动化工具,但其默认属性使网站很容易检测到并拒绝您访问。作为一种快速修复,Selenium Stealth 掩盖了此类属性的存在,让您可以在雷达下飞行。

但是,该插件甚至无法对抗高级检测技术。幸运的是,ZenRows 是一个不断发展的网络抓取解决方案,它提供了方便的方法来绕过最复杂的反机器人措施。

常见问题

Selenium可以被追踪吗?

是的,网站可以使用反机器人措施通过分析导航器属性、用户代理、鼠标移动等不同参数来跟踪 Selenium。这样,网站就可以识别像 Selenium 这样的自动浏览器。

类似文章