Python爬虫-Selenium库解决滑动验证与webdriver被发现的问题

1、前言

Selenium是一个自动化测试工具,也可以用于Web爬取。它可以控制浏览器并模拟人类操作,从而避免被反爬虫检测。

2、环境准备

2.1、安装selenium库

可以直接通过命令安装

pip install selenium

或者使用IDE安装

2.2、安装chromedriver

Selenium支持多种浏览器,包括ie、Firefox、Chrome等等。不同的浏览器与Selenium之间进行通信的载体不同,ChromeDriver就是Chrome浏览器与Selenium进行通信的载体。

下载地址如下:

1、http://chromedriver.storage.googleapis.com/index.html

2、https://npm.taobao.org/mirrors/chromedriver/

安装与自己的Chrome浏览器对应的版本,版本查看方式如下:

浏览器中输入chrome://version/

我下载的下图这个版本,小版本之间有差异影响不会很大

解压出来后将chromedriver.exe放到和代码相同的路径,当然你可以自己随便放到一个地方,然后在电脑环境变量里添加这个路径就行,如果不想修改环境变量,则可以直接在代码里指定路径

chrome_driver = './chromedriver.exe'
driver = webdriver.Chrome(executable_path=chrome_driver)

3、Selenium使用

前程无忧网为例,搜索职位内容为大数据

通过网页源代码调试可以获取url地址如下:https://we.51job.com/api/job/search-pc?api_key=51job&keyword=%E5%A4%A7%E6%95%B0%E6%8D%AE&searchType=2&function=&industry=&jobArea=000000&jobArea2=&landmark=&metro=&salary=&workYear=&degree=&companyType=&companySize=&jobType=&issueDate=&sortType=0&pageNum=1&requestId=&pageSize=500&source=1&accountId=&pageCode=sou%7Csou%7Csoulb

&keyword=%E5%A4%A7%E6%95%B0%E6%8D%AE,表示大数据,修改这个参数可以爬取不同的职位
页码信息:&pageNum=1,修改此参数可以实现翻页
职位显示数量信息:&pageSize=20,可以使得每一页内容更多

如何获取的该地址参考文章:Python爬虫-Ajax网页爬取过程


手动打开该网页后,发现有滑动访问验证

这个时候便需要用到Selenium库了。

3.1、解决滑动验证

首先要知道这个滑块的位置,以及它的长度


通过下面代码自动化进行滑块验证:

from selenium import webdriver
from selenium.webdriver import ActionChains

import time

def main():
    url = 'https://we.51job.com/api/job/search-pc?api_key=51job&keyword=%E5%A4%A7%E6%95%B0%E6%8D%AE&searchType=2&function=&industry=' \
          '&jobArea=000000&jobArea2=&landmark=&metro=&salary=&workYear=&degree=&companyType=&companySize=&jobType=&issueDate=' \
          '&sortType=0&pageNum=1&requestId=&pageSize=500&source=1&accountId=&pageCode=sou%7Csou%7Csoulb'


    chrome_driver = './chromedriver.exe'
    driver = webdriver.Chrome(executable_path=chrome_driver)

    driver.get(url)

    time.sleep(1)
    # 找到需要滑动的滑块元素
    slider = driver.find_element_by_xpath('//div[@class="nc_bg"]')

    # 创建操作链
    action_chains = ActionChains(driver)

    # 将鼠标移动到滑块上
    action_chains.move_to_element(slider)

    # 模拟按下鼠标左键并保持不松开
    action_chains.click_and_hold()

    # 移动鼠标使滑块达到目标位置
    action_chains.move_by_offset(300, 0)

    # 松开鼠标左键
    action_chains.release()

    # 执行操作链
    action_chains.perform()

    time.sleep(10)

    html = driver.page_source
    driver.quit()
    print(html)

if __name__ == '__main__':
    main()


此时发现验证失败。

3.2、解决webdriver被发现

最开始出现验证失败时怀疑是代码操作时速度太快、轨迹不对,但是最后试过人为在程序打开那个页面去滑动验证也不行,所以应该是网站检测出来了webdriver

因为使用Selenium时,它在运行过程中会暴露出一些预定义的JavaScript变量(特征字符串),如window.navigator.webdriver,在非Selenium环境下为false,在Selenium环境下为true

非Selenium环境:

Selenium环境

解决方法如下:

chrome_driver = './chromedriver.exe'

options = webdriver.ChromeOptions()

options.add_experimental_option('useAutomationExtension', False)
options.add_experimental_option('excludeSwitches', ['enable-automation'])
options.add_argument("--disable-blink-features=AutomationControlled")

driver = webdriver.Chrome(chrome_options=options,executable_path=chrome_driver)

# webdriver防屏蔽
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
    "source": """
       Object.defineProperty(navigator, 'webdriver', {
         get: () => false
       })
     """
})

useAutomationExtensionFalseexcludeSwitches['enable-automation']。这些选项旨在防止Chrome检测到自动化测试,并阻止它弹出警告框或限制自动化操作。

execute_cdp_cmd通过执行CDP命令(Chrome DevTools协议)来向页面注入JavaScript代码,该代码会覆盖navigator.webdriver属性,以隐藏浏览器正在运行自动化测试的标志。

options.add_argument("--disable-blink-features=AutomationControlled")
该行代码会将禁用Chrome自动化控制功能的选项添加到ChromeOptions对象中,并在创建ChromeDriver实例时应用该选项,以确保自动化测试可以稳定地运行而不被检测到。

3.3、最终效果

完整代码如下:

from selenium import webdriver
from selenium.webdriver import ActionChains

import time

def main():
    url = 'https://we.51job.com/api/job/search-pc?api_key=51job&keyword=%E5%A4%A7%E6%95%B0%E6%8D%AE&searchType=2&function=&industry=' \
          '&jobArea=000000&jobArea2=&landmark=&metro=&salary=&workYear=&degree=&companyType=&companySize=&jobType=&issueDate=' \
          '&sortType=0&pageNum=1&requestId=&pageSize=500&source=1&accountId=&pageCode=sou%7Csou%7Csoulb'


    chrome_driver = './chromedriver.exe'

    options = webdriver.ChromeOptions()

    options.add_experimental_option('useAutomationExtension', False)
    options.add_experimental_option('excludeSwitches', ['enable-automation'])
    options.add_argument("--disable-blink-features=AutomationControlled")

    driver = webdriver.Chrome(chrome_options=options,executable_path=chrome_driver)

    # webdriver防屏蔽
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
        "source": """
           Object.defineProperty(navigator, 'webdriver', {
             get: () => false
           })
         """
    })

    driver.get(url)

    time.sleep(1)
    # 找到需要滑动的滑块元素
    slider = driver.find_element_by_xpath('//div[@class="nc_bg"]')

    # 创建操作链
    action_chains = ActionChains(driver)

    # 将鼠标移动到滑块上
    action_chains.move_to_element(slider)

    # 模拟按下鼠标左键并保持不松开
    action_chains.click_and_hold()

    # 移动鼠标使滑块达到目标位置
    action_chains.move_by_offset(300, 0)

    # 松开鼠标左键
    action_chains.release()

    # 执行操作链
    action_chains.perform()

    time.sleep(10)

    html = driver.page_source
    driver.quit()
    print(html)

if __name__ == '__main__':
    main()

如果不想要程序去打开浏览器界面,希望操作全部后台执行,可以使用静默模式

from selenium import webdriver
from selenium.webdriver import ActionChains
import time

def main():
    url = 'https://we.51job.com/api/job/search-pc?api_key=51job&keyword=%E5%A4%A7%E6%95%B0%E6%8D%AE&searchType=2&function=&industry=' \
          '&jobArea=000000&jobArea2=&landmark=&metro=&salary=&workYear=&degree=&companyType=&companySize=&jobType=&issueDate=' \
          '&sortType=0&pageNum=1&requestId=&pageSize=500&source=1&accountId=&pageCode=sou%7Csou%7Csoulb'

    options = webdriver.ChromeOptions()

    # selenium静默执行(无浏览器界面)
    options.add_argument('headless')

    options.add_experimental_option('useAutomationExtension', False)
    options.add_experimental_option('excludeSwitches', ['enable-automation'])
    options.add_argument("--disable-blink-features=AutomationControlled")

    chrome_driver = './chromedriver.exe'
    driver = webdriver.Chrome(chrome_options=options,executable_path=chrome_driver)

    # webdriver防屏蔽
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
        "source": """
        Object.defineProperty(navigator, 'webdriver', {
          get: () => false
        })
      """
    })

    driver.get(url)

    time.sleep(1)
    # 找到需要滑动的滑块元素
    slider = driver.find_element_by_xpath('//div[@class="nc_bg"]')

    # 创建操作链
    action_chains = ActionChains(driver)

    # 将鼠标移动到滑块上
    action_chains.move_to_element(slider)

    # 模拟按下鼠标左键并保持不松开
    action_chains.click_and_hold()

    # 移动鼠标使滑块达到目标位置
    action_chains.move_by_offset(300, 0)

    # 松开鼠标左键
    action_chains.release()

    # 执行操作链
    action_chains.perform()

    time.sleep(10)

    html = driver.page_source
    driver.quit()
    print(html)

if __name__ == '__main__':
    main()

这样所有的操作都会在后台运行。

posted @ 2023-06-15 16:58  h云淡风轻  阅读(3004)  评论(1编辑  收藏  举报