zoukankan      html  css  js  c++  java
  • 可见即可爬:Selenium

    Selenium是通过拖放控件的方式设计UI,设计是什么样,运行就是什么样。

    一.安装Selenium和WebDriver

    1.安装Selenium

    pip安装

    pip install selenium
    

    离线安装
    在该网址中找到https://www.lfd.uci.edu/~gohlke/pythonlibs/#lxmlselenium的包
    然后解压到该目录下,cmd命令cd到该目录下,执行如下命令

    pip install selenium‑3.141.0‑py3‑none‑any.whl
    

    2.安装WebDriver

    2.1Chrome版本的WebDriver称为ChromeDriver

    ChromeDriver的官网https://chromedriver.chromium.org/

    2.1.1使用ChromeDriver:

    下载下来的ChromeDriver.exe是一个可执行文件,要将ChromeDriver.exe文件添加到PATH环境变量中,这样在任何路径下都可以执行ChromeDriver。或者将下载下来的ChromeDriver放到指定目录下,在使用ChromeDriver时指定其路径即可

    2.1.2

    在python中使用ChromeDriver

    from selenium import webdriver
    browser = webdriver.Chrome()
    

    执行上述代码会立刻启动一个Chrome浏览器的实例,也可以通过Chrome类的构造方法指定ChromeDriver的路径

    from selenium import webdriver
    browser = webdriver.Chrome('./webdriver/ChromeDriver')
    

    2.2装Edge WebDriver

    下载地址https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/

    2.2.1在python中使用Edge WebDriver

    from selenium import webdriver
    browser = webdriver.Edge()
    

    同样也可以指定Web WebDriver路径;可类比Chrome

    三.Selenium的基本使用方法

    3.1打开浏览器

    from selenium import webdriver
    browser = webdriver.Chrome('./webdriver/chromedriver')
    browser.get('https://www.jd.com')
    

    3.2控制浏览器页面的控件

    模拟按键,首先需要找到接收按键动作的节点
    Selenium支持多种方式查找节点,如通过id属性,通过class属性。然后可以通过send_keys方法模拟按键的动作

    from selenium import webdriver
    browser = webdriver.Chrome('./webdriver/chromedriver.exe')
    browser.get('https://www.jd.com')
    input = browser.find_element_by_id('key')
    input.send_keys('Python从菜鸟到高手')
    input.send_keys(Keys.ENTER)
    

    完整代码

    from selenium import webdriver
    from selenium.webdriver.common.keys import Keys
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as ec
    browser = webdriver.Chrome('./webdriver/chromedriver.exe)
    try:
        browser.get('https://www.jd.com')
        # 根据id的属性值来查找搜索框
        input = browser.find_element_by_id('key')
        # 使用send_keys方法向搜索框中输入文本
        input.send_keys('Python从菜鸟到高手')
        # 使用send_keys方法按下ENTER键
        input.send_keys(Keys.ENTER)
        # 设置WebDriverWait对象,设置等待时间(4秒)
        wait = WebDriverWait(browser,4)
        # 等待搜索页面显示(通过查找id值为J_goodsList的节点判断搜索页面是否显示)
        wait.until(ec.presence_of_all_elements_located((By.ID,'J_goodsList')))
        # 显示搜索页面的标题
        print(browser.title)
        # 显示搜索页面的URL
        print(browser.current_url)
        # 显示搜索页面的代码
        print(browser.page_source)
        # 关闭浏览器
        browser.close()
    
    except Exception as e:
        print(e)
        browser.close()
    

    在上面代码使用了WebDriverWait类,该类是为了在执行的过程中等待一段时间,这里设置为4秒。这是由于按下ENTER键后,并不一定马上显示搜索结果,需要一定的延长,但python程序不会等待搜索结果出来再往下继续执行下去,就会造成python程序已经运行到处理搜索结果页面的位置时,搜索结果页面还没显示出来。所以使用WebDriverWait类的until方法判断搜索结果页面是否显示完成。

    wait = WebDriverWait(browser,4)
        # 等待搜索页面显示(通过查找id值为J_goodsList的节点判断搜索页面是否显示)
    wait.until(ec.presence_of_all_elements_located((By.ID,'J_goodsList')))
    

    四.查找节点

    4.1查找单个节点

    find_element开头的方法都是用于查找单个节点的API.
    如下图所示

    上述API列表可以看到,Selenium支持通过多种方式查找节点,如XPath、CSS选择器、class属性、id属性、标签名等。这些方法使用都一样,只是需要传入不同的参数值
    本例通过使用Selenium通过id属性、name属性、和class属性获取表单中特定的input节点,并自动输入表单的内容
    这里查找的网页是用服务器挂载的静态页面

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    # 不支持本地网页
    browser = webdriver.Chrome('./webdriver/chromedriver')
    try:
        browser.get('http://localhost/demo.html')
        input = browser.find_element_by_id('name')
        input.send_keys('王军')
        input = browser.find_element_by_id('age')
        input.send_keys('30')
    
        input = browser.find_element_by_name('country')
        input.send_keys('中国')
    
        input = browser.find_element_by_class_name('myclass')
        input.send_keys('4000')
    
        # 或下面的代码
        input = browser.find_element(By.CLASS_NAME,'myclass')
        input.clear()  # 不清空  追加
        input.send_keys('8000')
    
    
    
    except Exception as e:
        print(e)
        browser.close()
    

    4.2查找多个节点

    查找多个节点返回的是一个列表,而查找单个节点返回的是一个节点
    若没有符合条件的节点,就会返回空列表
    这些API都是以find_elements开头的方法
    uploading-image-874268.png

    本例使用Selenium通过节点名查找所有符合条件的节点,并输入节点本身、符合条件的节点总数以及第一个符合条件的节点的文本

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    # 不支持本地网页
    browser = webdriver.Chrome('./webdriver/chromedriver')
    try:
        browser.get('https://www.jd.com')
        input = browser.find_elements_by_tag_name('li')
    
        print(input)
        print(len(input))
        print(input[0].text)
        input = browser.find_elements(By.TAG_NAME,'ul')
        print(input)
        print(input[0].text)
        
        browser.close()
    
    except Exception as e:
        print(e)
        browser.close()
    

    4.5节点交互

    例如click方法可以模拟单击节点的动作
    本例使用Selenium通过模拟浏览器单击动作循环单击页面上的6个按钮,单击每个按钮后,按钮下方的div就会按照按钮的背景色设置div的背景色

    from selenium import webdriver
    import time
    
    browser = webdriver.Chrome('./webdriver/chromedriver')
    try:
        browser.get('http://localhost/demo1.html')
        buttons = browser.find_elements_by_class_name('mybutton')
        i = 0
        while True:
            buttons[i].click()
            time.sleep(1)
            i += 1
            if i == len(buttons):
                i = 0
    
    except Exception as e:
        print(e)
        browser.close()
    
    

    4.6动作链

    在前面的交互动作中,交互动作都是针对某个节点执行的,例如,对于某个input节点输入一个字符串、模拟单击某一个按钮等。但还有另外一类交互动作,他们没有特定的执行对象,比如鼠标拖拽、键盘按键等,其实这些动作相当于全局事件,需要另外一种方式执行,这就是动作链。
    动作链需要创建ActionChains对象,并通过ActionChains类的若干方法向浏览器发送一个或多个动作。
    本例会使用Selenium动作链的move_to_element方法模拟鼠标移动的动作,自动显示京东商城首页左侧的每个二级导航菜单。

    from selenium import webdriver
    from selenium.webdriver import ActionChains
    import time
    browser = webdriver.Chrome()
    try:
        browser.get('https://www.jd.com')
        # 创建一个ActionChains对象
        actions = ActionChains(browser)
        # 通过CSS选择器查找所有class属性值为cate_menu_item的li节点,每一个li节点
        # 是一个二级导航栏
    
        li_list = browser.find_elements_by_css_selector(".cate_menu_item")
        # 通过迭代,显示每一个二级菜单,调用动作链中方法发送动作后,必须调用preform方法才能生效
        for li in li_list:
            actions.move_to_element(li).perform()
            time.sleep(1)
    except Exception as e:
        print(e)
        browser.close()
    

    本例演示地址是https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable,目的使用drag_and_drop方法将页面右侧的小方块拖到大方块上。

    from selenium import webdriver
    from selenium.webdriver import ActionChains
    
    browser = webdriver.Chrome('./webdriver/chromedriver')
    try:
        browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
        browser.switch_to.frame('iframeResult')
        source = browser.find_element_by_css_selector('#draggable')
        target = browser.find_element_by_css_selector('#droppable')
        actions = ActionChains(browser)
        # 调用drag_and_drop方法拖动节点
        actions.drag_and_drop(source, target)
        # 调用perform方法让拖动生效
        actions.perform()
    except Exception as e:
        print(e)
        browser.close()
    

    注意,如果页面存在iframe节点,而且要操作iframe中的节点,需要首先使用frame方法切换到iframe节点,才能操作里面的子节点。

    4.7执行JavaScript代码

    对于某些操作,Selenium并没有提供相应的API,例如,下拉页面,不过可以使用Selenium的execute_script方法直接运行JavaScript代码,以便扩展Selenium的功能。
    本例会使用Selenium的execute_script方法让京东商城首页滚动到最低端,然后弹出一个对话框。

    from selenium import webdriver
    browser = webdriver.Chrome('./webdriver/chromedriver')
    browser.get('https://www.jd.com')
    # 将京东商城滚动到最低端
    browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
    # 弹出对话框
    browser.execute_async_script('alert("已经到达页面底端")')
    

    4.8获取节点信息

    使用Selenium的API还可以获得详细的节点信息,如节点的位置,节点名称,节点尺寸和几点属性等。
    本例会使用Selenium的API获取京东商城首页HTML代码中id为navitems-groupl的ul节点的相关信息以及ul节点中li节点的相关信息

    from selenium import webdriver
    from selenium.webdriver import ActionChains
    options = webdriver.ChromeOptions()
    # 添加参数,不让Chrome浏览器显示,只在后台运行
    options.add_argument('headless')
    
    browser = webdriver.Chrome('./webdriver/chromedriver',chrome_options=options)
    #browser = webdriver.PhantomJS('./webdriver/phantomjs')
    browser.get('https://www.jd.com')
    # 查找页面中id属性值为navitems-group1的第一个节点
    ul = browser.find_element_by_id("navitems-group1")
    print(ul.text)
    print('id','=',ul.id)  # 内部id,不是节点id属性值
    print('location','=',ul.location)
    
    print('tag_name','=',ul.tag_name)
    print('size','=',ul.size)
    li_list = ul.find_elements_by_tag_name("li")
    for li in li_list:
        print(type(li))
        # 属性没找到,返回None
        print('<',li.text,'>', 'class=',li.get_attribute('class'))
        a = li.find_element_by_tag_name('a')
        print('href','=',a.get_attribute('href'))
    browser.close()
    

    五.管理Cookie

    使用Selenium,可以方便的管理Cookie,例如获取Cookie、添加和删除Cookie等
    本例使用Selenium API获取Cookie列表,并添加新的Cookie,以及删除所有的Cookie。

    from selenium import webdriver
    browser = webdriver.Chrome('./webdriver/chromedriver')
    browser.get('https://www.jd.com')
    # 为获取Cookie列表
    print(browser.get_cookies())
    # 添加新的Cookie
    browser .add_cookie({'name': 'name',
     'value':'jd','domain':'www.jd.com'})
    print(browser.get_cookies())
    # 删除所有的Cookie
    browser.delete_all_cookies()
    print(browser.get_cookies())  # 大部分删除了,可能还剩下一些
    

    六.管理节点的属性值

    Selenium本身并没有提供修改节点属性的API,不过可以通过执行JavaScript代码的方式设置节点属性,而且通过Selenium获取的节点可以直接作为DOM使用,这就意味着可以直接在JavaScript代码中使用查找到的节点。
    execute_script方法的第一个参数用于指定Javascript代码,后面的可变参数,可以为Javascript代码传递参数。通过arguments变量获取每一个参数值,例如arguments[0]表示第1个参数值,arguments[1]表示第2个参数值,以此类推。

    6.1本例会通过JavaScript代码改变百度搜索按钮的位置,让这个按钮在多个位置之间移动,时间间隔是2秒。

    from selenium import webdriver
    import time
    driver = webdriver.Chrome('./webdriver/chromedriver')
    driver.get("http://www.baidu.com")
    search_button = driver.find_element_by_id("su")  # 百度搜索按钮
    # arguments[0]对应的是第一个参数,可以理解为python里的%s传参,与之类似
    # 定义搜索坐标可以移动到x的坐标位置
    x_positions = [50,90,130,170]
    y_positions = [100,120,160,90]
    for i in range(len(x_positions)):
        # 用于移动的JavaScript代码,arguments[0]就是搜索按钮对应的DOM
        js = '''
         arguments[0].style.position = "absolute";
         arguments[0].style.left="{}px";
         arguments[0].style.top="{}px";
        '''.format(x_positions[i],y_positions[i])
        # 执行JS代码,并开始移动搜索按钮
        driver.execute_script(js, search_button)
        time.sleep(2)
    

    6.2本例使用JS代码修改京东商城首页顶端的前两个导航菜单的文本和链接,分别改成....。导航链接也会改变

    from selenium import webdriver
    import time
    driver = webdriver.Chrome('./webdriver/chromedriver')
    driver.get("https://www.jd.com")
    ul = driver.find_element_by_id('navitems-group1')
    li_list = ul.find_elements_by_tag_name('li')
    a1 = li_list[0].find_element_by_tag_name('a')
    a2 = li_list[1].find_element_by_tag_name('a')
    js = '''
     arguments[0].text = 'Python从菜鸟到高手'
     arguments[0].href = 'https://item.jd.com/12417265.html'
     arguments[1].text = '极客起源'
     arguments[1].href = 'https://geekori.com'
     '''
    driver.execute_script(js, a1,a2)
    

    12/13新增Webdriver常用方法

    通过partial_link_text(部分链接)文本来定位文本链接
    find_element_by_partial_link_text('字符串')
    通过完整链接文本link_text定位文本链接
    find_element_by_link_text('字符串')

    1.浏览器操作

    get() 访问URL driver.get('url链接')
    back 后退上一步 driver.back()
    forward 前进下一步 driver.forward()
    quit 退出驱动,关闭所有窗口 driver.quit()
    close 关闭当前打开的窗口 driver.close()
    maximize_window 浏览器最大化 driver.maximize_window()
    refresh 刷新浏览器 driver.refresh()
    

    2.元素操作

    send_keys() 向文本框类型输入数据 driver.find_element_by_tag('input').send_keys('selenium')
    clear() 清空输入的数据 driver.find_element_by_tag('input').clear()
    click() 单击事件 driver.find_element_by_tag('button').click()
    enter() 触发键盘enter操作 driver.find_element_by_tag('input').enter()
    text() 获取元素的文本内容 driver.find_element_by_partial_link_text('Outlook').text() 获取Outlook.com文本
    page_source 获取页面HTML内容 driver.page_source() ## 这句话非常有用,可以对抗任何反爬的措施,缘由是获取到了被浏览器渲染过后的网页源代码
    

    3.Cookie操作

    get_cookies() 获取当前页的所有Cookies driver.get_cookies()
    get_cookie(name) 获取当前页Cookies中的指定name值的cookie driver.get_cookies('time')
    add_cookie 添加Cookie driver.add_cookie({'time':'20211213121231'})
    delete_cookie(name) 删除一条Cookie driver.delete_cookie('time')
    delete_all_cookies 删除所有Cookie driver.delete_all_cookies()

    努力拼搏吧,不要害怕,不要去规划,不要迷茫。但你一定要在路上一直的走下去,尽管可能停滞不前,但也要走。
  • 相关阅读:
    清北学堂 清北-Day1-R1-Count
    清北学堂 清北-Day1-R2-监听monitor
    LuoGu P2420 让我们异或吧
    Milk(sort+结构体)
    开门人和关门人(结构体+sort)
    python-神奇的下划线
    python-pathlib
    python-文本字符串
    python-闭包
    进制-Iterative-进制转换
  • 原文地址:https://www.cnblogs.com/wkhzwmr/p/15236754.html
Copyright © 2011-2022 走看看