zoukankan      html  css  js  c++  java
  • Python 爬虫 selenium 笔记

    1. selenium 安装, 与文档

    pip install selenium
    

    Selenium with Python中文翻译文档

    selenium官网英文文档

    2. selenium 的第一个示例

    #!/usr/bin/env python3
    from selenium import webdriver  # 浏览器驱动对象
    from selenium.webdriver.common.keys import Keys
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as ec
    from selenium.webdriver.support.wait import WebDriverWait
    
    # 1. 实例化 并启动 浏览器
    phantom = webdriver.Chrome(executable_path=r'chromedriver.exe')
    
    url = "https://www.baidu.com"
    
    try:
        # 2. 访问 url
        phantom.get(url)
    
        # 3. 在获取的页面中, 找出 id 为 kw 的元素
        req = phantom.find_element_by_id('kw')
    
        # 4. 向 元素 中添加一个值
        req.send_keys("Python")
    
        # 5. 添加之后, 敲回车
        req.send_keys(Keys.ENTER)
    
        # 6. 浏览器等待 10 秒, 等待 content_left 元素加载出来
        wait = WebDriverWait(phantom, 10)
        wait.until(ec.presence_of_element_located((By.ID, 'content_left')))
    
        print(phantom.current_url)    # 打印 输出结果的url 
        print(phantom.get_cookies())  # 打印 输出结果中的 cookies
        print(phantom.page_source)    # 打印 输出结果的网页
    finally:
        phantom.close()
    

    3. 声明浏览器对象

    3.1. 传统浏览器

    from selenium import webdriver
    
    
    # 1. 谷歌浏览器
    driver = webdriver.Chrome(executable_path=r"chromedriver.exe")
    
    # 2. 火狐 浏览器
    driver2 = webdriver.Firefox(firefox_profile=r"驱动所在路径")
    
    # 3. PhantomJS 浏览器
    driver3 = webdriver.PhantomJS(executable_path=r"驱动所在路径")
    
    # 4. IE 浏览器
    driver4 = webdriver.Edge(executable_path=r"驱动所在路径")
    
    # 5. Safari 浏览器
    driver5 = webdriver.Safari(executable_path=r"驱动所在路径")
    
    

    3.2. 谷歌无界面版浏览器

    https://blog.csdn.net/hldh214/article/details/76682283
    

    网址

    https://developers.google.cn/web/updates/2017/04/headless-chrome

    代码

    from selenium import webdriver
    import time
    
    option = webdriver.ChromeOptions()
    option.add_argument('headless')
    driver = webdriver.Chrome(chrome_options=option)
    
    # ----   操作 -----
    driver.get('https://www.baidu.com/')
    
    print(driver.title)  # 显示 页面的 title
    req = driver.find_element_by_id('kw').send_keys('测试')
    time.sleep(0.5)
    
    req2 = driver.find_element_by_xpath('//*[@id="su"]')
    req2.click()
    time.sleep(2)
    html = driver.page_source
    
    # 将网页截图
    driver.save_screenshot('renren.png')
    
    # 关闭浏览器
    # driver.quit()
    driver.close()
    

    下面我们以谷歌浏览器进行演示, 其他浏览器的操作步骤完全相同

    4. 访问网页

    from selenium import webdriver
    
    driver = webdriver.Chrome(executable_path=r"chromedriver.exe")
    driver.get("https://www.taobao.com")
    print(driver.page_source)  # 打印网页
    

    4.1. webdriver 的基础属性

    driver.page_source  	打印 html
    
    
    driver.text			打印标签内容, 包括子标签的所有内容
    
    driver.close()  	关闭当前窗口
    
    driver.quit()  	 	退出驱动并关闭所有关联的窗口
    
    

    4.2. 获取的一个标签的各种属性

    获取的如 属性id文本位置标签名属性大小,等

    示例代码

    #!/usr/bin/env python3
    from selenium import webdriver
    
    option = webdriver.ChromeOptions()
    option.add_argument('headless')
    
    browser = webdriver.Chrome(chrome_options=option)
    
    url = "https://www.zhihu.com/explore"
    browser.get(url)
    logo = browser.find_element_by_id('zh-top-link-logo')
    print(logo)
    
    # 获取 标签的 class 属性
    logo_class = logo.get_attribute("class")
    print(logo_class)
    
    # 获取文本
    print(logo.text)
    
    # 获取 id, 获取的是 selenium 的 id
    print("获取 id: ", logo.id)
    
    # 获取位置, 相当于与左上角的 x, y 轴位置
    print("获取位置: ", logo.location)
    
    # 获取标签名, 是什么标签
    print("获取标签名: ", logo.tag_name)
    
    # 获取 大小, 大小值得是标签的宽高
    print("获取 大小: ", logo.size)
    
    browser.quit()
    

    结果

    <selenium.webdriver.remote.webelement.WebElement (session="3d003d3cafd379f0ebed23abf85a00bd", element="0.18254839841692982-1")>
    zu-top-link-logo
    知乎
    获取 id:  0.18254839841692982-1
    获取位置:  {'y': 0, 'x': 6}
    获取标签名:  a
    获取 大小:  {'width': 61, 'height': 45}
    

    5. 查找单个元素

    按照指定方法查找元素, 只查找第一个

    3)获取标签属性 [9. 获取元素属性](#9. 获取元素属性)

    5.1. 方法一: find_element_by_*

    from selenium import webdriver
    
    driver = webdriver.Chrome(executable_path=r"chromedriver.exe")
    driver.get("https://www.taobao.com")
    
    # 1. 根据 id 找元素
    input_first = driver.find_element_by_id('q')
    
    # 2. 根据 css 找元素
    input_second = driver.find_element_by_css_selector("#q")
    
    # 3. 根据 xpath 找元素
    input_third = driver.find_element_by_xpath('//*[@id="q"]')
    
    print(input_first, input_second, input_third)
    
    driver.close()
    

    其他查找方法

    driver.find_element_by_name()        # 根据 标签 name 值 查找
    driver.find_element_by_xpath()       # 通过 xpath  找元素
    driver.find_element_by_link_text()    # 通过 link  找元素
    driver.find_element_by_partial_link_text()    # 用链接文本定位超链接
    driver.find_element_by_tag_name()          #  标签名定位
    driver.find_element_by_class_name()     # 通过 class 名 找元素, class 定位
    driver.find_element_by_css_selector()    # css 选择器定位
    
    
    解释与示例
    	https://python-selenium-zh.readthedocs.io/zh_CN/latest/4.元素定位/
    

    5.2. 方法二: find_element(By.ID, '...')

    可以通过   find_element()
    
    
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    
    driver = webdriver.Chrome(executable_path=r"chromedriver.exe")
    driver.get("https://www.taobao.com")
    
    input_first = driver.find_element(by=By.ID, value="q")
    input_second = driver.find_element(by=By.CSS_SELECTOR, value="#q")
    input_third = driver.find_element(by=By.XPATH, value='//*[@id="q"]')
    
    print(input_first, input_second, input_third)
    
    driver.close()
    
    """
    by 的其他选项:
        By.ID :   id
        By.XPATH :   xpath
        By.LINK_TEXT :   link text  链接文本
        By.PARTIAL_LINK_TEXT :   partial link text   部分链接文本
        By.NAME :   name   Name 属性名
        By.TAG_NAME :   tag name  标签名
        By.CLASS_NAME :   class name  , class名称
        By.CSS_SELECTOR :   css selector  , CSS选择器
    """
    
    
    结果与 方法一相同
    

    6. 查找多个元素

    与 5 的区别

    ​ 1)find_element_* 变成了 find_elements_*

    ​ 2)筛选的条件

    ​ 3)获取标签属性 [9. 获取元素属性](#9. 获取元素属性)

    6.1. 方法一: 使用 find_elements_* 的方式

    from selenium import webdriver
    # from selenium.webdriver.common.by import By
    
    driver = webdriver.Chrome(executable_path=r"chromedriver.exe")
    driver.get("https://www.taobao.com")
    
    list1 = driver.find_elements_by_css_selector('.service-bd li')  # 显示的格式是列表, 格式还是对象
    print(list1)
    
    list2 = [i.text for i in list1]  # i.text 显示比标签内容
    print(list2)
    
    driver.close()
    

    其他查找方法

    driver.find_elements_by_name()        # 根据 标签 name 值 查找
    driver.find_elements_by_xpath()       # 通过 xpath  找元素
    driver.find_elements_by_link_text()    # 通过 link  找元素
    driver.find_elements_by_partial_link_text()    # 用链接文本定位超链接
    driver.find_elements_by_tag_name()          #  标签名定位
    driver.find_elements_by_class_name()     # 通过 class 名 找元素, class 定位
    driver.find_elements_by_css_selector()    # css 选择器定位
    
    
    解释与示例
    	https://python-selenium-zh.readthedocs.io/zh_CN/latest/4.元素定位/
    

    6.2. 方法二: find_elements(By.ID, '...')

    可以通过   find_element()
    
    
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    
    driver = webdriver.Chrome(executable_path=r"chromedriver.exe")
    driver.get("https://www.taobao.com")
    
    list1 = driver.find_elements(by=By.CSS_SELECTOR, value=".service-bd li")  # 格式是个列表
    print(list1)
    
    list2 = [i.text for i in list1]  # i.text 显示比标签内容
    print(list2)
    
    driver.close()
    
    """
    by 的其他选项:
        By.ID :   id
        By.XPATH :   xpath
        By.LINK_TEXT :   link text  链接文本
        By.PARTIAL_LINK_TEXT :   partial link text   部分链接文本
        By.NAME :   name   Name 属性名
        By.TAG_NAME :   tag name  标签名
        By.CLASS_NAME :   class name  , class名称
        By.CSS_SELECTOR :   css selector  , CSS选择器
    """
    
    
    结果与 方法一相同
    

    7. 元素交互操作

    7.1. 对获取的元素调用交互方法

    #!/usr/bin/env python3
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    import time
    
    driver = webdriver.Chrome(executable_path=r"chromedriver.exe")
    driver.get("https://www.taobao.com")
    input_first = driver.find_element(By.ID, "q")  # 找出输入框
    
    # 1. 向找出的输入框, 添加值
    input_first.send_keys("iPad")
    
    # 2. 等待 1.3 秒
    time.sleep(1.3)
    
    # 3. 清除文本框的文本内容, 
    # 	上一次写入的内容没有进行搜索, 只是将文本框清空在添加而已
    input_first.clear()
    
    # 4. 在 文本框上写入 新值
    input_first.send_keys("MacBook Pro 2017")
    
    # 5. 找到搜索按钮
    button = driver.find_element(By.CLASS_NAME, 'btn-search')
    
    # 6. 点击 找到的 搜索按钮
    button.click()
    

    其他操作,点击这里

    7.2. 动作链

    ​ 将动作附加到动作连中串行执行

    #!/usr/bin/env python3
    from selenium import webdriver
    from selenium.webdriver import ActionChains
    
    
    driver = webdriver.Chrome(executable_path=r"chromedriver.exe")
    url = "http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable"
    
    driver.get(url)
    
    # 1. 指定一个 iframe 标签, frame 的参数是 iframe 标签的 id 属性
    #   作用是切换 到 指定的 iframe 中, 如果不切换则无法找到
    driver.switch_to.frame("iframeResult")
    
    # 2. 获取到要移动的 元素
    source = driver.find_element_by_xpath('//div[@id="draggable"]')
    
    # 3. 获取到一低昂到的元素
    target = driver.find_element_by_xpath('//div[@id="droppable"]')
    
    # 4. 实例化动作链
    actions = ActionChains(driver)
    
    # 5. 调用 drag_and_drop 方法用来拖拽, 指定将 source 拖拽到  target
    actions.drag_and_drop(source, target)
    
    # 6. 指定动链
    actions.perform()
    
    

    关于动作链的其他操作如,

    actions.click(on_element=None)   点击一个元素
    actions.click_and_hold(on_element=None)    	点击按住不动
    actions.context_click(on_element=None)    	右键
    actions.double_click(on_element=None) 		双击
    actions.drag_and_drop_by_offset()			按住元素后向 x轴 y轴偏移多少
    ....
    

    其他的, 点击这里

    8. 执行 JavaScript

    执行自己写的 JavaScript ,因为有些时候,不方便使用 api 的方式进行操作, 所以使用自己写 JavaScript 的方式进行执行

    利用 webdriver 对象的 execute_script( js 代码),实现

    from selenium import webdriver
    
    driver = webdriver.Chrome(executable_path=r"chromedriver.exe")
    url = "http://www.zhihu.com/explore"
    
    driver.get(url)
    
    # 1. 执行 JS 文件 将网页拉倒最低端
    driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')
    
    # 2. JS 弹框
    driver.execute_script('alert("To Bottom")')
    

    9. 获取中属性

    9.1. 获取元素属性

    #!/usr/bin/env python3
    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)
    
    # 获取 标签的 class 属性
    logo_class = logo.get_attribute("class")
    print(logo_class)
    
    

    9.2. 获取文本值

    使用 browser.text 属性

    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.text)
    browser.quit()
    

    9.3. 获取其他属性

    获取的如 属性id文本位置标签名属性大小,等

    点击 [4.2. 获取的一个标签的各种属性](#4.2. 获取的一个标签的各种属性)

    10. frame

    10.1. 解释

    ​ 1)frame 就相当于在网页中相当于一个独立的网页

    ​ 2)在父级网页中, 想要获取子级的网页的标签必须要切换到子级才能查找

    10.2. 示例代码

    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)
    
    
    # 切换到 id = iframeResult 的 frame 中
    browser.switch_to.frame('iframeResult')
    
    # 获取 元素
    source = browser.find_element_by_css_selector("#draggable")
    print(source)
    
    # 获取元素, 如果报错则显示无 指定元素
    try:
        logo = browser.find_element_by_class_name("logo")
        # 这个属性的标签是 父属性的 标签, 这里是为了测试 在子 frame 中 无法获取父 frame 的属性
    except NoSuchElementException:
        # 如果找不到则 进出 except
        print("NO  LOGO")
    
    # 切换回父 frame 中
    browser.switch_to.parent_frame()
    
    # 查找 logo 的标签
    flogo = browser.find_element_by_class_name('logo')
    
    print(flogo)
    print(flogo.text)
    
    browser.quit()
    

    11. 等待

    11.1. 等待的原因

    ​ 因为有些元素需要页面加载完成之后加载,为了防止在没有加载出所需要的标签时直接执行代码,所以在有些时候需要写入当待

    11.2 隐式等待

    ​ 当使用了隐式等待执行测试时候,如果 WebDriver 没有在DOM 中找到元素, 将继续等待, 超出等待时间后则抛出找不到元素的异常,换句话说, 当查找元素或元素并没有立即出现的时候,隐式等待将等待一段时间在查找 DOM,默认为 0

    from selenium import webdriver
    browser = webdriver.Chrome()
    
    # 设置隐式等待的时间
    browser.get("https://www.zhihu.com/explore")
    
    input_res = borwser.find_element_by_class_name('zu-top-add-question')
    print(input_res)
    
    # 退出
    browser.quit()
    

    11.3. 显示等待

    指定一个等待条件,在指定一个最长等待时间,他会最长等待时间内判断条件是否成立,成立则返回, 不成立则等待,如果达到最长等待时间,还是没有满足条件,则抛出异常

    显示等待 的模块是:

    from selenium.webdriver.support import expected_conditions as EC

    而且显示等待很灵活,可定义很多的等待条件, 如下

    • EC.title_is() :标题是某内容
    • EC.title_contains() :标题包含某内容
    • EC.presence_of_element_located() : 元素加载出,传入定位为元素, 如,(By.ID, "p")
    • EC.visibility_of_element_located() : 元素可见,传入定位元祖
    • EC.presence_of_all_elements_located() : 所有元祖加载出
    • EC.text_to_be_present_in_element() : 某个元素文本包括某文字
    • EC.text_to_be_present_in_element_value() : 某个元祖值包含某个文字
    • EC.frame_to_be_available_and_switch_to_it() : frame 加载并切换
    • EC.invisibility_of_element_located() : 元素不可见
    • EC.element_to_be_clickable() : 元素是否可点击
    • EC.staleness_of() : 判断一个元素仍然在DOM,可判断页面是否已经刷新
    • EC.element_to_be_selected() : 元素可选择,传元素对象
    • EC.element_located_to_be_selected() :元素可选择, 传入定位元祖
    • EC.element_selection_state_to_be() : 传入元素对象以及状态, 相等返回 True,否则返回 False
    • EC.element_located_selection_state_to_be() : 传入定位元组以及状态, 相等返回 True,否则返回 False
    • EC.alert_is_present() : 是否出现了 Alert

    详细内容:点击这里

    代码

    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
    
    
    # 1. 声明一个浏览器对象
    browser = webdriver.Chrome()
    
    # 2. 创建请求链接
    url = "http://www.taobao.com"
    browser.get(url)
    
    # 3. 声明一个显式等待的对象
    #   参数 1 就是 将浏览器对象
    #   参数 2 就是 最长等待时间
    walt = WebDriverWait(browser, 10)
    
    # 4. 利用 until 的方法 传入等待条件
    #   参数是一个元祖,第一个是 筛选条件,第二个就是 筛选的值
    driver = walt.until(EC.presence_of_element_located((By.ID, "q")))
    
    # 5. 可以在追加一个条件,(也可以不加)
    button = walt.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search')))
    
    
    print(driver, button)  # 打印的是标签的对象,可以根据对象进行操作
    
    print(dir(button))
    
    

    12. 网页的前进后退

    12.1. 使用了的两个方法:

    ​ browser.back() 在浏览器历史中向后退一步

    ​ browser.forward() 在浏览器历史上前进一步

    12.2. 代码

    from selenium import webdriver
    import time
    
    browser = webdriver.Chrome()
    
    browser.get('https://www.baidu.com/')
    time.sleep(1.3)
    browser.get('https://www.taobao.com/')
    time.sleep(2.3)
    browser.get('https://www.python.org/')
    time.sleep(2.1)
    
    # 在浏览器历史中向后退一步
    browser.back()
    time.sleep(1)
    
    # 在浏览器历史上前进一步
    browser.forward()
    
    browser.quit()
    

    cookie 的操作

    from selenium import webdriver
    
    browser = webdriver.Chrome()
    
    # url = 'https://www.zhihu.com/explore'
    url = 'https://www.baidu.com/'
    browser.get(url)
    
    # 1. 打印 cookie
    cookie_1 = browser.get_cookies()
    print(cookie_1)
    
    # 2. 添加 cookie
    #   2.1. 指定添加的字典
    new_cookie = {'name': 'name', 'domain': 'www.zhihu.com', 'value': 'germey'}
    #   2.2. 添加新的值
    browser.add_cookie(new_cookie)
    #   2.3. 查看添加后的属性
    cookie_2 = browser.get_cookies()
    print(cookie_2)
    
    # 3. 清除 cookie
    #   3.1. 清空 cookie
    browser.delete_all_cookies()
    #   3.2. 清空指定值
    # browser.delete_cookie("my_cookie")
    #   3.3. 打印cookie
    cookie_3 = browser.get_cookies()
    print(cookie_3)
    

    14. 浏览器选项卡管理

    14.1. 方法解释

    • 浏览器头部的选项卡(地址栏上面的选项卡)管理
    • 一般有操作时时对一个选项卡进行操作,接下来就操作多个
    • 有两种方法:
      • 方法 1 :使用快捷键,但是每个浏览器的快捷键都不一样,所以无法使用
      • 方法 2 :使用 JavaScrapy 的格式进行操作

    14.2. 代码解释

    使用 JS 的形式,打开新选项卡

    from selenium import webdriver
    from time import sleep
    
    browser = webdriver.Chrome()
    browser.get('https://www.baidu.com')
    
    # 1. 使用 JS 打开一个新选项卡
    browser.execute_script('window.open()')
    
    # 2. 生成 选项卡列表
    tab_list = browser.window_handles
    #   打印选项卡
    print(tab_list)
    
    
    sleep(2)
    # 3. 切换到选项卡 1, 第二个选项卡
    #   参数:只需要传选项卡代号即可
    browser.switch_to.window(tab_list[1])
    
    sleep(2)
    # 4. 操作选项卡 1, 第二个选项卡
    #   4.1. 在第二个选项卡上 访问数据
    browser.get('https://www.taobao.com')
    
    #   4.2. 切换到选项卡 0 ,第一个选项卡
    #       参数:只需要传选项卡代号即可
    browser.switch_to.window(tab_list[0])
    sleep(2)
    
    #   4.3. 重新访问其他页面
    browser.get('https://www.python.org')
    

    15. 异常处理

    15.1. 示例

    首先我们看一下报错信息

    from selenium import webdriver
    
    browser = webdriver.Chrome()
    browser.get("https://www.baidu.com")
    
    # 查找 一个 ID 不存在的 元素
    browser.find_element_by_id("hello")
    

    结果的报错信息

    Traceback (most recent call last):
    	.......
    selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"id","selector":"hello"}
    	.......
    

    报错信息中 有个报错 selenium.common.exceptions.NoSuchElementException 报错

    那么我们捕获一下

    from selenium import webdriver
    from selenium.common.exceptions import TimeoutException, NoSuchElementException
    # TimeoutException 超时报错
    # NoSuchElementException  当元素找不到时抛出
    
    browser = webdriver.Chrome()
    
    try:
        browser.get("https://www.baidu.com")
    except TimeoutException:
        print("超时,链接超时")
    
    try:
        # 查找 一个 ID 不存在的 元素
        browser.find_element_by_id("hello")
    except NoSuchElementException:
        print("元素不存在")
    
    finally:  # 不管是否报错都执行代码
        browser.quit()
    

    结果

    元素不存在
    

    15.2. 其他报错

    异常报错种类很多,请查看文档

    异常处理的文档

    异常处理的官方文档

  • 相关阅读:
    垂死挣扎-3
    垂死挣扎-2
    垂死挣扎-1
    【互联网考试系列-1】进程与线程
    【iOS基础学习随笔-2】SQLite的使用
    【iOS面试系列-2】多线程中同步、异步和串行、并行之间的逻辑关系(必考,必须掌握)
    docker
    给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。
    621. 任务调度器
    204. 计数质数
  • 原文地址:https://www.cnblogs.com/dream4567/p/9201743.html
Copyright © 2011-2022 走看看