• 100天精通Python——第47天:selenium自动化操作浏览器


    在这里插入图片描述

    每篇前言

    • 🏆🏆作者介绍:Python领域优质创作者、华为云享专家、阿里云专家博主、2021年CSDN博客新星Top6

    • 🔥🔥本文已收录于Python全栈系列专栏《100天精通Python从入门到就业》
    • 📝​📝​此专栏文章是专门针对Python零基础小白所准备的一套完整教学,从0到100的不断进阶深入的学习,各知识点环环相扣
    • 🎉🎉订阅专栏后续可以阅读Python从入门到就业100篇文章还可私聊进两百人Python全栈交流群(手把手教学,问题解答); 进群可领取80GPython全栈教程视频 + 300本计算机书籍:基础、Web、爬虫、数据分析、可视化、机器学习、深度学习、人工智能、算法、面试题等。
    • 🚀🚀加入我一起学习进步,一个人可以走的很快,一群人才能走的更远!

    在这里插入图片描述
    在这里插入图片描述

    一、Selenium框架环境搭建

    Selenium 是一个用于测试 Web 应用程序的框架,该框架测试直接在浏览器中运行,就像真实用户操作一样。在爬虫领域 selenium 同样是一把利器,能够解决大部分的网页的反爬问题。Selenium 可以根据我们的指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是否发生。

    1. 下载模块

    1. window电脑点击win键+ R,输入:cmd

    在这里插入图片描述

    2. 安装selenium,输入对应的pip命令pip install selenium

    2. 安装浏览器驱动WebDriver

    Selenium 库里有个叫 WebDriver 的 API。WebDriver 有点儿像可以加载网站的浏览器,但是它也可以像 BeautifulSoup 或者其他 Selector 对象一样用来查找页面元素,与页面上的元素进行交互 (发送文本、点击等),以及执行其他动作。

    Chrome浏览器驱动下载地址:http://chromedriver.storage.googleapis.com/index.html

    Firefox浏览器驱动下载地址:https://github.com/mozilla/geckodriver/releases/

    Edge浏览器驱动下载地址::https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/#downloads

    PhantomJS安装教程(无界面浏览器,它会把网站加载到内存并执行页面上的 JavaScript,因为不会展示图形界面,所以运行起来比完整的浏览器要高效):PhantomJS浏览器下载安装、配置环境变量及使用教程

    注意需要下对应浏览器版本的驱动,下载安装步骤如下:

    • 1. 确定浏览器的版本:
      在这里插入图片描述

    • 2. 找到最相近的那个点击,下载对应的Chrome驱动版本
      在这里插入图片描述

    • 3. 选择合适的操作系统
      在这里插入图片描述

    • 4. 安装包解压后放进Python安装路径下

      在这里插入图片描述

    二、基础操作

    1. 打开浏览器

    操作 Chrome 浏览器:

    from selenium import webdriver
    
    # 浏览器的初始化
    browser = webdriver.Chrome()
    # 发送请求
    browser.get('https://www.baidu.com/')
    
    # 打印页面的标题
    print(browser.title)
    
    # 退出模拟浏览器
    browser.quit()  # 一定要退出!不退出会有残留进程
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    操作 Firefox 浏览器:

    from selenium import webdriver
    
    # 浏览器的初始化
    browser = webdriver.Firefox()
    # 发送请求
    browser.get('https://www.baidu.com/')
    
    # 打印页面的标题
    print(browser.title)
    
    # 退出模拟浏览器
    browser.quit()  # 一定要退出!不退出会有残留进程
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    操作 Edge 浏览器:

    from selenium import webdriver
    
    # 浏览器的初始化
    browser = webdriver.Edge()
    # 发送请求
    browser.get('https://www.baidu.com/')
    
    # 打印页面的标题
    print(browser.title)
    
    # 退出模拟浏览器
    browser.quit()  # 一定要退出!不退出会有残留进程
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    操作 PhantomJS 浏览器:

    from selenium import webdriver
    
    # 初始化浏览器
    browser = webdriver.PhantomJS()
    # 发送请求
    browser.get('https://www.baidu.com/')
    
    # 打印页面的标题
    print(browser.title)
    
    # 退出模拟浏览器
    browser.quit()  # 一定要退出!不退出会有残留进程
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2. 无界面模式

    Headless 模式是 Chrome 浏览器的无界面形态,可以在不打开浏览器的前提下,使用所有 Chrome 支持的特性运行我们的程序

    from selenium import webdriver
    
    # 1. 实例化配置对象
    chrome_options = webdriver.ChromeOptions()
    # 2. 配置对象添加开启无界面命令
    chrome_options.add_argument('--headless')
    # 3. 配置对象添加禁用gpu命令
    chrome_options.add_argument('--disable-gpu')
    # 4. 实例化带有配置对象的browser 对象
    browser = webdriver.Chrome(chrome_options=chrome_options)
    
    browser.get('https://www.baidu.com/')
    
    # 查看请求的数据
    print(browser.page_source)  # 查看渲染后的数据,就可以Xpath进行解析获取数据了
    print(browser.get_cookies())  # 查看请求页面后的cookies值
    print(browser.current_url)  # 查看请求url
    
    # 关闭页面
    browser.close()
    # 关闭浏览器
    browser.quit()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    3. 元素定位

    通过selenium的基本使用可以简单操作浏览器了,接下来我们再来学习下定位元素的其他方法

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('--headless')
    browser = webdriver.Chrome(chrome_options=chrome_options)
    url = 'https://www.xxx.com/'
    browser.get(url)
    html_str = browser.page_source
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    假设访问地址某网址,返回 html_str 为如下内容:

    <div class="panel">
        <div class="panel-heading">
            <h4>Hello</h4>
        </div>
        <div class="panel_body">
            <ul class="list" id="list-1" name="element">
                <li class="element">Foo</li>
                <li class="element">Bar</li>
                <li class="element">Jay</li>
            </ul>
            <ul class="list list-small" id="list-2">
                <li class="element">Foo</li>
                    <a href="https://www.baidu.com">百度官网</a>
                <li class="element">Bar</li>
            </ul>
        </div>
    </div> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    1.根据 id 属性值获取元素列表

    from selenium.webdriver.common.by import By
    
    # 获取第一个元素
    browser.find_element(by=By.ID, value="list-1")
    # 获取多个元素
    browser.find_elements(by=By.ID, value="list-1")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2. 根据 class 获取元素列表:

    # 获取第一个元素
    browser.find_element(by=By.CLASS_NAME, value="element")
    # 获取多个元素
    browser.find_elements(by=By.CLASS_NAME, value="element")
    
    • 1
    • 2
    • 3
    • 4

    3. 根据Xpath获取元素列表:

    # 返回标签为li,id为element的所有元素
    browser.find_element(by=By.XPATH, value="//li[@id='element']")
    browser.find_elements(by=By.XPATH, value="//li[@id='element']")
    
    • 1
    • 2
    • 3

    4. 根据标签的文本获取元素列表(精确定位)

    # 获取一个元素
    browser.find_element(by=By.LINK_TEXT, value="Foo")
    # 获取多个元素
    browser.find_elements(by=By.LINK_TEXT, value="Foo")
    
    • 1
    • 2
    • 3
    • 4

    5. 根据标签包含的文本获取元素列表(模糊定位)

    # 获取一个元素
    browser.find_element(by=By.PARTIAL_LINK_TEXT, value="Fo")
    # 获取多个元素
    browser.find_elements(by=By.PARTIAL_LINK_TEXT, value="Fo")
    
    • 1
    • 2
    • 3
    • 4

    6. 根据标签名获取元素列表:

    # 获取一个元素
    browser.find_element(by=By.TAG_NAME, value="li")
    # 获取多个元素
    browser.find_elements(by=By.TAG_NAME, value="li")
    
    • 1
    • 2
    • 3
    • 4

    4. 元素操作

    1. 获取文本(通过定位获取的标签对象的text属性,获取文本内容)element.text

    ret = browser.find_element_by_class_name('element')
    print(ret[0].text)
    
    • 1
    • 2

    2. 获取属性值(通过定位获取的标签对象的get_ attribute 函数,传入属性名,来获取属性的值)

    ret = browser.find_element_by_tag_name('a')
    print(ret[0].get_attribute('href'))
    
    • 1
    • 2

    5. 前进后退

    # 前进
    browser.forward()
    
    # 后退 
    browser.back()
    
    • 1
    • 2
    • 3
    • 4
    • 5

    6. 执行js

    selenium可以让浏览器执行我们规定的js代码:browser.execute_script(js)

    from selenium import webdriver
    
    browser = webdriver.Chrome()
    url = 'https://www.baidu.com/'
    browser.get(url)
    
    js = 'window.scrol1To(O,document.body.scrollHeight)'  # js语句
    browser.execute_script(js) # 执行js的方法
    
    browser.quit()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    7.页面等待

    现在的网页越来越多采用了 Ajax 技术,这样程序便不能确定何时某个元素完全加载出来了。如果实际页面等待时间过长导致某个dom元素还没出来,但是你的代码直接使用了这个WebElement,那么就会抛出NullPointer的异常。

    为了避免这种元素定位困难而且会提高产生 ElementNotVisibleException 的概率。所以 Selenium 提供了两种等待方式,一种是隐式等待,一种是显式等待。

    隐式等待是等待特定的时间,显式等待是指定某一条件直到这个条件成立时继续执行。

    隐式等待(常用)

    隐式等待针对的是元素定位,隐式等待设置了一个时间,在一段时间内判断元素是否定位成功,如果完成了,就进行下一步。在设置的时间内没有定位成功,则会报超时加载

    from selenium import webdriver
    
    driver = webdriver.Chrome()
    driver.implicitly_wait(10) # 隐式等待10秒
    driver.get('https://www.baidu.com/')
    myDynamicElement = driver.find_element_by_id("input")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    显式等待(了解)

    显式确定等待指定某个元素,然后设置最长等待时间。如果在这个时间还没有找到元素,那么便会抛出异常了。

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    # WebDriverWait 库,负责循环等待
    from selenium.webdriver.support.ui import WebDriverWait
    # expected_conditions 类,负责条件出发
    from selenium.webdriver.support import expected_conditions as EC
    
    driver = webdriver.Chrome()
    driver.get('https://www.baidu.com/')
    try:
        # 页面一直循环,直到 id="input" 出现
        element = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.ID, "input"))
        )
    finally:
        driver.quit()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    三、进阶操作

    1. 使用代理ip

    selenium控制浏览器也是可以使用代理ip的。

    from selenium import webdriver
    import time
    
    # 1. 实例化配置对象
    options = webdriver.ChromeOptions()
    # 2. 配置对象添加使用代理ip的命令
    options.add_argument('--proxy-server=http://ip地址')  # 代理IP:端口号
    # 3. 实例化带有配置对象的driver对象
    driver = webdriver.Chrome(chrome_options=options)
    driver.get("https://www.baidu.com")
    
    # 获取页面内容
    print(driver.page_source)
    
    # 延迟3秒后关闭当前窗口,如果是最后一个窗口则退出
    time.sleep(3)
    driver.close()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2. 修改请求头

    selenium可以修改请求头,伪装不同浏览器

    from selenium import webdriver
    import time
    
    agent = 'Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1'
    # 1. 实例化配置对象
    options = webdriver.ChromeOptions()
    # 2. 配置对象修改请求头
    options.add_argument('--user-agent=' + agent)
    # 3. 实例化带有配置对象的driver对象
    driver = webdriver.Chrome(chrome_options=options)
    driver.get("https://www.baidu.com")
    
    # 获取页面内容
    print(driver.page_source)
    
    # 延迟3秒后关闭当前窗口,如果是最后一个窗口则退出
    time.sleep(3)
    driver.close()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    3. 隐藏浏览器指纹特征

    selenium 操作浏览器,有几十个特征可以被网站检测到,轻松的识别出你是爬虫。

    正常情况手动打开浏览器,输入网址https://bot.sannysoft.com/
    在这里插入图片描述

    selenium 无界面模式打开浏览器:

    from selenium import webdriver
    
    
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('--headless')
    chrome_options.add_argument('--disable-gpu')
    driver = webdriver.Chrome(chrome_options=chrome_options)
    
    driver.get('https://bot.sannysoft.com/')
    
    # 对当前页面进行截图
    driver.save_screenshot('1.png')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    生成图片:
    在这里插入图片描述

    很明显就已经被网站发现是爬虫了!

    解决浏览器指纹特征关键,实际就是一个 stealth.min.js 文件,通过Python执行这个js文件可以隐藏浏览器指纹

    stealth.min.js文件下载地址:关注文末公众号,回复:隐藏浏览器指纹

    添加请求头 + 执行 stealth.min.js 文件进行隐藏浏览器指纹:

    from selenium import webdriver
    
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('--headless')
    chrome_options.add_argument('--disable-gpu')
    # 添加请求头伪装浏览器
    chrome_options.add_argument(
        'user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36')
    driver = webdriver.Chrome(chrome_options=chrome_options)
    
    with open('stealth.min.js') as f:
        js = f.read()
    
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
        "source": js
    })
    
    driver.get('https://bot.sannysoft.com/')
    driver.save_screenshot('2.png')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    运行结果:
    在这里插入图片描述

    通过执行 stealth.min.js 进行隐藏浏览器指纹,已经和正常访问一样了!

    四、书籍推荐

    书籍展示:《人工智能原理与实践 》

    在这里插入图片描述


    【书籍内容简介】

    • 涵盖人工智能和数据科学各个重要体系,通过算法中最重要的理论推导和精华分析+六大典型AI和数据科学应用场景,深入浅出地讲解和展示机器学习应用的具体流程。
      全面:涵盖人工智能和数据科学各个重要体系经典:世界名校AI专业深造,国际大行实战经验系统:重要理论和公式层层推导,阐述深入浅出实战:六大典型AI和数据科学应用场景,透彻分析和代码实现
  • 相关阅读:
    SpringBoot:第一章JavaConfig、@ImportResource、@PropertyResource等总结(动力)
    低代码是什么?用它来开发系统有什么优势呢?
    靶场上新:Openfire身份认证绕过
    【Linux升级之路】0_Linux入门 | 环境搭建 | 使用常识 | 用户管理
    十、数据结构——树结构实际应用
    python二次开发CATIA:新建Part文档
    优秀的测试/开发程序员,是怎样修炼的?步步为营地去执行......
    For-else:Python中一个奇怪但有用的特性
    JMeter-BeanShell预处理程序和BeanShell后置处理程序的应用
    2.KDTree相关
  • 原文地址:https://blog.csdn.net/yuan2019035055/article/details/125772198