如何使用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()
上面的结果表明 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()
恭喜,您已经成功避免了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()
上面的屏幕截图证明 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_proxy
js_render
true
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)
结论
Selenium 是一种流行的网络抓取和自动化工具,但其默认属性使网站很容易检测到并拒绝您访问。作为一种快速修复,Selenium Stealth 掩盖了此类属性的存在,让您可以在雷达下飞行。
但是,该插件甚至无法对抗高级检测技术。幸运的是,ZenRows 是一个不断发展的网络抓取解决方案,它提供了方便的方法来绕过最复杂的反机器人措施。
常见问题
Selenium可以被追踪吗?
是的,网站可以使用反机器人措施通过分析导航器属性、用户代理、鼠标移动等不同参数来跟踪 Selenium。这样,网站就可以识别像 Selenium 这样的自动浏览器。