• Python爬虫(四)—深入学习Selenium


    前言

    以下关于Selenium的内容讲解,强烈推荐深入了解的查看官方文档。

    英文版:Selenium、 https://selenium-python.readthedocs.io/

    Selenium介绍安装

    • 介绍
      selenium 是一套完整的web应用程序测试系统,包含了测试的录制(selenium IDE),编写及运行(Selenium Remote Control)和测试的并行处理(Selenium Grid)。Selenium的核心Selenium Core基于JsUnit,完全由JavaScript编写,因此可以用于任何支持JavaScript的浏览器上。
      selenium可以模拟真实浏览器,自动化测试工具,支持多种浏览器,爬虫中主要用来解决JavaScript渲染问题。
    • 安装使用 selenium
      virtualenv 来创建隔离的Python环境。
      pip install selenium
    • 选择下载浏览器驱动
      下载以下driver后,放到Python虚拟环境的 Scripts 文件夹下。
    浏览器下载地址
    Chromehttps://sites.google.com/a/chromium.org/chromedriver/downloads
    Edgehttps://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
    Firefoxhttps://github.com/mozilla/geckodriver/releases
    Safarihttps://webkit.org/blog/6900/webdriver-support-in-safari-10/
    • PhantomJS
      PhantomJS是一个而基于WebKit的服务端JavaScript API,支持Web而不需要浏览器支持,其快速、原生支持各种Web标准:Dom处理,CSS选择器,JSON等等。PhantomJS可以用用于页面自动化、网络监测、网页截屏,以及无界面测试。速度比Selenium快很多,最后进行讲解。

    Selenium 的基本使用

    • 声明浏览器对象、访问页面
    from selenium import webdriver
    
    browser = webdriver.Chrome()
    
    browser.get("http://www.baidu.com")
    print(browser.page_source)
    browser.close()
    
    • 查找单元素
      • 获取方式
        以下通过三种不同的方式去获取响应的元素,第一种是通过id的方式,第二个中是CSS选择器,第三种是xpath选择器,结果都是相同的。
    from selenium import webdriver
    
    browser = webdriver.Chrome()
    
    browser.get("http://www.taobao.com")
    input_first = browser.find_element_by_id("q")
    input_second = browser.find_element_by_css_selector("#q")
    input_third = browser.find_element_by_xpath('//*[@id="q"]')
    print(input_first)
    print(input_second)
    print(input_third)
    browser.close()
    

    CSS选择器、xpath选择器 可以直接采用chrome浏览器的右击复制,如下图:

    chrome快捷复制节点.png

    • 查找元素方法
      • find_element_by_name
      • find_element_by_id
      • find_element_by_xpath
      • find_element_by_link_text
      • find_element_by_partial_link_text
      • find_element_by_tag_name
      • find_element_by_class_name
      • find_element_by_css_selector
        以上方法也可以通过By.NAME等进行获取。如以下代码
    from selenium import webdriver
    
    from selenium.webdriver.common.by import By
    
    browser = webdriver.Chrome()
    
    browser.get("http://www.taobao.com")
    
    # 匹配的元素的ID
    # input_first_By_ID = browser.find_element_by_id('q')
    # 以下类似,都有两种方式。
    input_first_By_ID = browser.find_element(By.ID, "q")
    
    # 匹配的元素的xpath定位器
    input_first_By_XPATH = browser.find_element(By.XPATH, "//*[@id="q"]")
    
    # 匹配的元素的name属性
    input_first_By_NAME = browser.find_element(By.NAME, "q")
    
    # 匹配的元素的文本
    input_first_LINK_TEXT = browser.find_element(By.LINK_TEXT, "领淘金币抵钱")
    
    # 匹配的元素的标签名称,例如:h1,a,span
    input_first_CSS_SELECTOR = browser.find_element(By.CSS_SELECTOR, "#q")
    
    print(input_first_CSS_SELECTOR)
    browser.close()
    """
    <selenium.webdriver.remote.webelement.WebElement (session="4ee277c466be7248d4c7e078cbf927db", element="0.09114132600392044-1")>
    """
    
    • 多元素查找
      与以上类似,只不过在以上的方法 find_element_by_css_selector -> find_elements_by_css_selector ,加一个s。

      并且在输出的时候是以list的形式返回,例如以上的输出修改为:
      [<selenium.webdriver.remote.webelement.WebElement (session=“cdbd8f4c90c313c9e94519414365f552”, element=“0.40080093360381364-1”)>]

    疑问查看:WebDriver API https://selenium-python.readthedocs.io/api.html

    from selenium import webdriver
    from selenium.webdriver import ActionChains
    
    browser = webdriver.Chrome()
    
    url = "http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable"
    browser.get(url)
    browser.switch_to.frame('iframeResult')
    source = browser.find_element_by_css_selector('#draggable')
    target = browser.find_element_by_css_selector('#droppable')
    actions = ActionChains(browser)
    actions.drag_and_drop(source, target)
    actions.perform()
    
    • 元素交互操作:输入、清空、点击
      对于获取的元素调用交互方法,主要是元素值的输入、清空、点击等操作。
      以下代码运行为:程序自动打开Chrome浏览器并打开淘宝输入ipad,然后删除,重新输入MakBook pro,并点击搜索。
    from selenium import webdriver
    import time
    
    browser = webdriver.Chrome()
    browser.get("http://www.taobao.com")
    input_str = browser.find_element_by_id('q')
    input_str.send_keys("ipad")
    time.sleep(1)
    input_str.clear()
    input_str.send_keys("MakBook pro")
    button = browser.find_element_by_class_name('btn-search')
    button.click()
    time.sleep(3)
    browser.close()
    

    chromeOptions

    chromeOptions 是一个配置 chrome 启动是属性的类。通过这个类,我们可以为chrome配置如下参数(这个部分可以通过selenium源码看到)

    • 添加实验性质的设置参数 add_experimental_option
      代码如下:
    # 实例化一个启动参数对象
    options = webdriver.ChromeOptions()
    # 设置浏览器窗口大小
    options.add_experimental_option("prefs", {"profile.managed_default_content_settings.images": 2})
    # 启动浏览器
    browser = webdriver.Chrome(chrome_options=chrome_options)
    

    常用的参数如下:

    1. 设置为开发者模式 (‘excludeSwitches’, [‘enable-automation’)
    2. 不加载图片,加快访问速度 (“prefs”, {“profile.managed_default_content_settings.images”: 2})
    3. 模拟手机打开网页 (‘mobileEmulation’, {‘deviceName’: ‘Apple iPhone 4’})
    4. 关闭保存密码提示
    options = webdriver.ChromeOptions() 
    prefs = {} 
    # 设置这两个参数就可以避免密码提示框的弹出
    prefs['credentials_enable_service'] = False 
    prefs['profile.password_manager_enabled'] = False 
    options.add_experimental_option('prefs', prefs) 
    browser = webdriver.Chrome(chrome_options=options)
    
    启动参数作用
    –user-agent="设置请求头的User-Agent
    –window-size=1366,768设置浏览器分辨率(窗口大小)
    –headless无界面运行(无窗口)
    –start-maximized最大化运行(全屏窗口)
    –incognito隐身模式(无痕模式)
    –disable-javascript禁用javascript
    –disable-infobars禁用浏览器正在被自动化程序控制的提示
    • 添加扩展应用 (add_extension, add_encoded_extension)
    • 设置 chrome 二进制文件位置 (binary_location)
    • selenium源码
      在目录 envLibsite-packagesseleniumwebdriverchromeoptitions.py 下。
    class Options(object):
        KEY = "goog:chromeOptions"
    
        def __init__(self):
            self._binary_location = ''
            self._arguments = []
            self._extension_files = []
            self._extensions = []
            self._experimental_options = {}
            self._debugger_address = None
            self._caps = DesiredCapabilities.CHROME.copy()
    

    执行JavaScript

    • 调用js方法
      下面的例子是通过登录知乎然后通过js翻到页面底部,并弹框提示。
    from selenium import webdriver
    
    browser = webdriver.Chrome()
    browser.get("http://www.zhihu.com/explore")
    browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
    browser.execute_script('alert("To Bottom")')
    
    • 获取元素属性、文本值
      可以通过 get_attribute(‘class’) 获取元素的class属性、href属性、文本值等。
    from selenium import webdriver
    
    browser = webdriver.Chrome()
    url = 'https://www.zhihu.com/explore'
    browser.get(url)
    logo = browser.find_element_by_id('zh-top-link-logo')
    print(logo)
    print(logo.get_attribute('class'))  # zu-top-link-logo
    print(logo.text)  # 知乎
    
    • 获取ID,位置,标签名
    from selenium import webdriver
    
    browser = webdriver.Chrome()
    url = 'https://www.zhihu.com/explore'
    browser.get(url)
    input = browser.find_element_by_class_name('zu-top-add-question')
    print(input.id)
    print(input.location)
    print(input.tag_name)
    print(input.size)
    """
    0.8051799500933536-1
    {'x': 758, 'y': 7}
    button
    {'height': 32, 'width': 66}
    """
    

    Frame

    涉及到切入到frame中以及切出来的问题,常用的是switch_to.from()和switch_to.parent_frame(),如以下代码:

    import time
    from selenium import webdriver
    from selenium.common.exceptions import NoSuchElementException
    
    browser = webdriver.Chrome()
    url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
    browser.get(url)
    
    browser.switch_to.frame('iframeResult')
    
    source = browser.find_element_by_css_selector('#draggable')
    print(source)
    try:
        logo = browser.find_element_by_class_name('logo')
    except NoSuchElementException:
        print('NO LOGO')
    
    browser.switch_to.parent_frame()
    
    logo = browser.find_element_by_class_name('logo')
    print(logo)
    print(logo.text)
    

    等待 Waits

    以下内容基本摘自:https://selenium-python.readthedocs.io/waits.html

    • 显式等待
      WebDriverWait与ExpectedCondition相结合是一种可以实现的方法。EC.presence_of_element_located()是确认元素是否已经出现。
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    driver = webdriver.Firefox()
    driver.get("http://somedomain/url_that_delays_loading")
    try:
        element = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.ID, "myDynamicElement"))
        )
    finally:
        driver.quit()
    

    在抛出TimeoutException之前等待最多10秒,除非它发现元素在10秒内返回。默认情况下,WebDriverWait每500毫秒调用一次ExpectedCondition,直到它成功返回。对于所有其他ExpectedCondition类型,ExpectedCondition类型的布尔返回true或非null返回值成功返回。

    • 常用的判断条件如下
    预期条件目的
    title_is标题是某内容
    title_contains标题包含某内容
    presence_of_element_located元素加载出,传入定位元组,如(By.ID,‘p’)
    visibility_of_element_located元素可见,传入定位元组
    visibility_of可见,传入元素对象
    presence_of_all_elements_located所有元素加载出
    text_to_be_present_in_element某个元素文本包含某文字
    text_to_be_present_in_element_value某个元素值包含某文字
    frame_to_be_available_and_switch_to_itframe加载并切换
    invisibility_of_element_located元素不可见
    element_to_be_clickable元素可点击
    staleness_of判断一个元素是否仍在DOM,可判断页面是否已经刷新
    element_to_be_selected元素可选择,传元素对象
    element_located_to_be_selected元素可选择,传入定位元组
    element_selection_state_to_be传入元素对象以及状态,相等返回True,否则返回False
    element_located_selection_state_to_be传入定位元组以及状态,相等返回True,否则返回False
    alert_is_present是否出现Alert
    • 自定义等待条件
      如果以前的便捷方法都不符合您的要求,您还可以创建自定义等待条件。可以使用带有__call__方法的类创建自定义等待条件,该方法在条件不匹配时返回False。示例 : 略…
    • 隐式等待
      到了一定的时间发现元素还没有加载,则继续等待我们指定的时间,如果超过了我们指定的时间还没有加载就会抛出异常,如果没有需要等待的时候就已经加载完毕就会立即执行。
    from selenium import webdriver
    
    browser = webdriver.Chrome()
    browser.implicitly_wait(10)
    browser.get('https://www.zhihu.com/explore')
    input = browser.find_element_by_class_name('zu-top-add-question')
    print(input)
    

    其他操作

    • 浏览器的前进和后退
      • 后退:back()
      • 前进:forward()
    import time
    from selenium import webdriver
    
    browser = webdriver.Chrome()
    browser.get('https://www.baidu.com/')
    browser.get('https://www.taobao.com/')
    browser.get('https://www.python.org/')
    browser.back()
    time.sleep(1)
    browser.forward()
    browser.close()
    
    • cookie操作
      • get_cookies()
      • delete_all_cookes()
      • add_cookie()
    from selenium import webdriver
    
    browser = webdriver.Chrome()
    browser.get('https://www.zhihu.com/explore')
    print(browser.get_cookies())
    
    browser.add_cookie({'name': 'name', 'domain': 'www.zhihu.com', 'value': 'zhaofan'})
    
    print(browser.get_cookies())
    browser.delete_all_cookies()
    print(browser.get_cookies())
    
    • 选项卡管理
      通过执行js命令实现新开选项卡window.open()
      不同的选项卡是存在列表里browser.window_handles
      通过browser.window_handles[0]就可以操作第一个选项卡
    import time
    from selenium import webdriver
    
    browser = webdriver.Chrome()
    browser.get('https://www.baidu.com')
    browser.execute_script('window.open()')
    print(browser.window_handles)
    browser.switch_to_window(browser.window_handles[1])
    browser.get('https://www.taobao.com')
    time.sleep(1)
    browser.switch_to_window(browser.window_handles[0])
    browser.get('https://python.org')
    
    from selenium import webdriver
    from selenium.common.exceptions import TimeoutException, NoSuchElementException
    
    browser = webdriver.Chrome()
    try:
        browser.get('https://www.baidu.com')
    except TimeoutException:
        print('Time Out')
    try:
        browser.find_element_by_id('hello')
    except NoSuchElementException:
        print('No Element')
    finally:
        browser.close()
    

    selenium 模拟手机

    有些操作,需要模拟手机才能继续进行,例如微信的公众号、服务号。直接上代码,模拟手机型号等属性。

    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    
    mobile_emulation = {"deviceName": "Pixel 2 XL",
                        }
    options = Options()
    options.add_experimental_option("mobileEmulation", mobile_emulation)
    driver = webdriver.Chrome(chrome_options=options)
    ...
    

    PhantomJS

    from selenium import webdriver
    
    browser = webdriver.PhantomJS()
    
    browser.get("http://www.baidu.com")
    print(browser.page_source)
    browser.close()
    

    由于selenium对phantomjs不再支持,因此会警告:UserWarning: Selenium support for PhantomJS has been deprecated, please use headless versions of Chrome or Firefox instead

    个人博客:Loak 正 - 关注人工智能及互联网的个人博客
    文章地址:Python爬虫(四)—深入理解Selenium

  • 相关阅读:
    JavaScript 数组中 length 属性【每日一段代码100】
    连续往上滚动jquery代码
    关于<img>标签的几个问题
    前端页面制作常见问题及解决方案
    JavaScript random() 方法【每日一段代码96】
    JavaScript split() 方法【每日一段代码99】
    JavaScript boolean 对象检查逻辑值【每日一段代码94】
    CSS 属性总结
    JavaScript max() 方法【每日一段代码97】
    JavaScript sort() 方法数组排序文字【每日一段代码92】
  • 原文地址:https://www.cnblogs.com/l0zh/p/13739738.html
Copyright © 2020-2023  润新知