zoukankan      html  css  js  c++  java
  • 爬虫四 selenium模块

    一、介绍
    selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题
    selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如跳转、输入、点击、下拉等,来拿到网页渲染之后的结果,可支持多种浏览器
    from selenium import webdriver          #导入模块,然后产生一个浏览器对象
    browser=webdriver.Chrome()
    browser=webdriver.Firefox()
    browser=webdriver.PhantomJS()
    browser=webdriver.Safari()
    browser=webdriver.Edge()

    二、安装

      1、selenium+chromedriver

     pip3 install selenium
    下载chromdriver.exe放到python安装路径的scripts目录中即可,可以在notes.txt中查看每个版本适用与那个浏览器
    下载链接:http://npm.taobao.org/mirrors/chromedriver/
    
    #验证安装
    C:UsersAdministrator>python3
    Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from selenium import webdriver
    >>> driver=webdriver.Chrome() #弹出浏览器,产生一个浏览器对象,后续就是通过这个浏览器对象来操作浏览器
    >>> driver.get('https://www.baidu.com')   #控制浏览器访问url
    >>> driver.page_source         #打印访问url后返回的html信息
    
    #注意:
    selenium3默认支持的webdriver是Firfox,而Firefox需要安装geckodriver
    下载链接:https://github.com/mozilla/geckodriver/releases

       2、selenium+phantomjs

    #PhantomJS 是一个无界面的webkit内核浏览器,你可以把它当作一个没有界面的 Safari
    pip3 install selenium
    下载phantomjs,解压后把phantomjs.exe所在的bin目录放到环境变量中
    下载链接:http://phantomjs.org/download.html
    
    #验证安装
    C:UsersAdministrator>phantomjs
    phantomjs> console.log('egon gaga')
    egon gaga
    undefined
    phantomjs> ^C
    C:UsersAdministrator>python3
    Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from selenium import webdriver
    >>> driver=webdriver.PhantomJS() #无界面浏览器
    >>> driver.get('https://www.baidu.com')
    >>> driver.page_source

     三、基本使用

    from selenium import webdriver  #驱动浏览器
    from selenium.webdriver import ActionChains #作用链,主要用作滑动验证
    from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
    from selenium.webdriver.common.keys import Keys #键盘按键操作
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.wait import WebDriverWait #EC联用,等待页面中的某个元素被加载完成
    
    browser=webdriver.Chrome()
    try:
        browser.get('https://www.baidu.com')
        input_tag=browser.find_element_by_id('kw') #通过id的方式查找元素,与input_tag=browser.find_element(By.CSS_SELECTOR,'#kw')的结果一样
        input_tag.send_keys('美女') #python2中输入中文错误,字符串前加个u,在这个input标签内输入查找的字符
        input_tag.send_keys(Keys.ENTER) #输入回车或者是查找到提交按钮点击都可以# input_tag.click()
        wait=WebDriverWait(browser,10)         #产生一个等待的对象
        wait.until(EC.presence_of_element_located((By.ID,'content_left'))) #等到id为content_left的元素加载完毕,最多等10秒
        print(browser.page_source)   #获取返回的网页html
        print(browser.current_url)  #获取返回的网页url
        print(browser.get_cookies()) #获取返回的网页cookie
    finally:
        browser.close()     #无论怎样关闭浏览器
     

    四、三种选择器

      1、三种查找元素(标签)方式

    from selenium import webdriver
    from selenium.webdriver import ActionChains
    from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
    from selenium.webdriver.common.keys import Keys #键盘按键操作
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素
    browser=webdriver.Chrome()
    browser.get('https://www.baidu.com')
    
    #以下三种方式达到的都是同一种效果:查找id为kw的标签
    input_tag1=browser.find_element(By.ID,'kw') #等同于:input_tag1=browser.find_element_by_id('kw')
    input_tag2=browser.find_element(By.CSS_SELECTOR,'#kw') #等同于:input_tag2=browser.find_element_by_css_selector('#kw')
    input_tag3=browser.find_element(By.XPATH,'//*[@id="kw"]') #等同于:input_tag3=browser.find_element_by_xpath('//*[@id="kw"]')

    总结:
    # By.CSS_SELECTOR  通过css属性查看,属性可以是id,class等。
    # By.CLASS_NAME 通过class属性查找
    # By.XPATH      通过路径匹配查找
    # By.ID        通过id查找
    # By.TAG_NAME    通过tag标签查找
    #注意:browser.find_elements系列与browser.find_element的区别就是,前者是查找多个,后者是只找第一个 div1=browser.find_element(By.CSS_SELECTOR,'div') #找到第一个div标签 div2=browser.find_elements(By.CSS_SELECTOR,'div') #找到所有的div标签,放到列表里 browser.close()
    复制代码

       2、获取元素(标签)内容的方式

    复制代码
    from selenium import webdriver
    from selenium.webdriver import ActionChains
    from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
    from selenium.webdriver.common.keys import Keys #键盘按键操作
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素
    
    browser=webdriver.Chrome()
    browser.get('https://www.amazon.cn/')
    wait=WebDriverWait(browser,10)
    wait.until(EC.presence_of_element_located((By.ID,'cc-lm-tcgShowImgContainer')))
    tag=browser.find_element(By.CSS_SELECTOR,'#cc-lm-tcgShowImgContainer img')
    #获取标签属性,
    print(tag.get_attribute('src'))
    #获取标签ID,位置,名称,大小,内容(了解)
    print(tag.id)
    print(tag.location)
    print(tag.tag_name)
    print(tag.size)

    print(tag.text)
    browser.close()

    五、等待元素被加载

      1、简介

    #1、selenium只是模拟浏览器的行为,而浏览器解析页面是需要时间的(执行css,js),一些元素可能需要过一段时间才能加载出来,为了保证能查找到元素,必须等待 
    #2、等待的方式分两种: 隐式等待:在browser.get('xxx')前就设置,针对所有元素有效
                显式等待:在browser.get('xxx')之后设置,只针对某个元素有效

       2、隐式等待

    #当使用了隐式等待执行测试的时候,如果 WebDriver没有在 DOM中找到元素,将继续等待,超出设定时间后则抛出找不到元素的异常,
    换句话说,当查找元素或元素并没有立即出现的时候,隐式等待将等待一段时间再查找 DOM,默认的时间是0
    from selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR from selenium.webdriver.common.keys import Keys #键盘按键操作 from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素 browser=webdriver.Chrome() #隐式等待:在查找所有元素时,如果尚未被加载,则等10秒 browser.implicitly_wait(10)#等待十秒加载不出来就会抛出异常,10秒内加载出来正常返回数据 browser.get('https://www.baidu.com') input_tag=browser.find_element_by_id('kw') input_tag.send_keys('美女') input_tag.send_keys(Keys.ENTER) contents=browser.find_element_by_id('content_left') #没有等待环节而直接查找,找不到则会报错 print(contents) browser.close()

       3、显式等待

    from selenium import webdriver
    from selenium.webdriver import ActionChains
    from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
    from selenium.webdriver.common.keys import Keys #键盘按键操作
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素
    
    browser=webdriver.Chrome()
    browser.get('https://www.baidu.com')
    input_tag=browser.find_element_by_id('kw')
    input_tag.send_keys('美女')
    input_tag.send_keys(Keys.ENTER)
    #显式等待:显式地等待某个元素被加载
    wait=WebDriverWait(browser,10)#指定一个等待条件,和一个最长等待时间,程序会判断在等待时间内条件是否满足,如果满足则返回,如果不满足会继续等待,超过时间就会抛出异常
    wait.until(EC.presence_of_element_located((By.ID,'content_left')))
    contents=browser.find_element(By.CSS_SELECTOR,'#content_left')
    print(contents)
    browser.close()

     六、元素交互操作

      1、点击清空

    from selenium import webdriver
    from selenium.webdriver import ActionChains
    from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
    from selenium.webdriver.common.keys import Keys #键盘按键操作
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素
    
    browser=webdriver.Chrome()
    browser.get('https://www.amazon.cn/')
    wait=WebDriverWait(browser,10)
    input_tag=wait.until(EC.presence_of_element_located((By.ID,'twotabsearchtextbox')))
    input_tag.send_keys('iphone 8')
    button=browser.find_element_by_css_selector('#nav-search > form > div.nav-right > div > input')
    button.click()
    
    import time
    time.sleep(3)
    input_tag=browser.find_element_by_id('twotabsearchtextbox')
    input_tag.clear() #清空输入框
    input_tag.send_keys('iphone7plus')
    button=browser.find_element_by_css_selector('#nav-search > form > div.nav-right > div > input')
    button.click()
    # browser.close()

       2、action chains 行为链

    #http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.action_chains
    from selenium import webdriver
    from selenium.webdriver import ActionChains
    from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
    from selenium.webdriver.common.keys import Keys #键盘按键操作
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素

    browser=webdriver.Chrome() browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable') browser.switch_to.frame('iframeResult') #切换到iframeResult,只有frame中嵌套一个frame时才会使用 source=browser.find_element_by_id('draggable') target=browser.find_element_by_id('droppable') actions=ActionChains(browser) #拿到动作链对象 actions.drag_and_drop(source,target) #把动作放到动作链中,准备串行执行,意思就是把source元素移动到target元素 actions.perform() #执行

       3、在交互动作比较困难的情况下可以自己写js代码(万能方法)

    from selenium import webdriver
    from selenium.webdriver import ActionChains
    from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
    from selenium.webdriver.common.keys import Keys #键盘按键操作
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素
    
    try:
        browser=webdriver.Chrome()
        browser.get('https://www.baidu.com')
        browser.execute_script('alert("hello world")') #打印警告
    finally:
        browser.close()

    有些动作可能没有提供api,比如进度条下拉,这时,我们可以通过代码执行JavaScript
    from selenium import webdriver browser = webdriver.Chrome() browser.get('https://www.zhihu.com/explore') browser.execute_script('window.scrollTo(0, document.body.scrollHeight)') browser.execute_script('alert("To Bottom")')

       4、frame的切换(frame内嵌套frame)

    #frame相当于一个单独的网页,在父frame里是无法直接查看到子frame的元素的,必须switch_to_frame切到该frame下,才能进一步查找
    from selenium import webdriver
    from selenium.webdriver import ActionChains
    from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
    from selenium.webdriver.common.keys import Keys #键盘按键操作
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素
    
    try:
        browser=webdriver.Chrome()
        browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
        browser.switch_to.frame('iframeResult') #切换到id为iframeResult的frame
        tag1=browser.find_element_by_id('droppable')
        print(tag1)
        # tag2=browser.find_element_by_id('textareaCode') #报错,在子frame里无法查看到父frame的元素
        browser.switch_to.parent_frame() #切回父frame,就可以查找到了
        tag2=browser.find_element_by_id('textareaCode')
        print(tag2)
    finally:
        browser.close()

     七、其他

      1、模拟浏览器的前进后退功能

    import time
    from selenium import webdriver
    
    browser=webdriver.Chrome()
    browser.get('https://www.baidu.com')
    browser.get('https://www.taobao.com')
    browser.get('http://www.sina.com.cn/')
    
    browser.back()    #后退
    time.sleep(10)
    browser.forward()  #前进
    browser.close()

       2、#cookies

    #获取网页返回的cookie
    from selenium import webdriver
    
    browser=webdriver.Chrome()
    browser.get('https://www.zhihu.com/explore')
    print(browser.get_cookies())
    browser.add_cookie({'k1':'xxx','k2':'yyy'})
    print(browser.get_cookies())
    # browser.delete_all_cookies()

       3、选项卡管理(就是一个浏览器打开多个窗口)

    #选项卡管理:切换选项卡,有js的方式windows.open,有windows快捷键:ctrl+t等,最通用的就是js的方式
    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(10)
    browser.switch_to_window(browser.window_handles[0])
    browser.get('https://www.sina.com.cn')
    browser.close()

       4、异常处理

    from selenium import webdriver
    from selenium.common.exceptions import TimeoutException,NoSuchElementException,NoSuchFrameException
    
    try:
        browser=webdriver.Chrome()
        browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
        browser.switch_to.frame('iframssseResult')
    
    except TimeoutException as e:
        print(e)
    except NoSuchFrameException as e:
        print(e)
    finally:
        browser.close()

     八、自动登陆163邮箱

     1 #注意:网站都策略都是在不断变化的,精髓在于学习流程。下述代码生效与2017-11-7,不能保证永久有效
     2 from selenium import webdriver
     3 from selenium.webdriver import ActionChains
     4 from selenium.webdriver.common.by import By
     5 from selenium.webdriver.common.keys import Keys
     6 from selenium.webdriver.support import expected_conditions as EC
     7 from selenium.webdriver.support.wait import WebDriverWait
     8 
     9 browser=webdriver.Chrome()
    10 try:
    11     browser.get('http://mail.163.com/')
    12     wait=WebDriverWait(browser,5)
    13     frame=wait.until(EC.presence_of_element_located((By.ID,'x-URS-iframe')))
    14     browser.switch_to.frame(frame)
    15     wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'.m-container')))
    16 
    17     inp_user=browser.find_element_by_name('email')
    18     inp_pwd=browser.find_element_by_name('password')
    19     button=browser.find_element_by_id('dologin')
    20     inp_user.send_keys('18611453110')
    21     inp_pwd.send_keys('xxxx')
    22     button.click()
    23 
    24     #如果遇到验证码,可以把下面一小段打开注释
    25     # import time
    26     # time.sleep(10)
    27     # button = browser.find_element_by_id('dologin')
    28     # button.click()
    29 
    30     wait.until(EC.presence_of_element_located((By.ID,'dvNavTop')))
    31     write_msg=browser.find_elements_by_css_selector('#dvNavTop li')[1] #获取第二个li标签就是“写信”了
    32     write_msg.click()
    33 
    34 
    35     wait.until(EC.presence_of_element_located((By.CLASS_NAME,'tH0')))
    36     recv_man=browser.find_element_by_class_name('nui-editableAddr-ipt')
    37     title=browser.find_element_by_css_selector('.dG0 .nui-ipt-input')
    38     recv_man.send_keys('378533872@qq.com')
    39     title.send_keys('圣旨')
    40     print(title.tag_name)
    41 
    42 
    43     frame=wait.until(EC.presence_of_element_located((By.CLASS_NAME,'APP-editor-iframe')))
    44     browser.switch_to.frame(frame)
    45     body=browser.find_element(By.CSS_SELECTOR,'body')
    46     body.send_keys('你很帅,可以加工资了')
    47 
    48     browser.switch_to.parent_frame() #切回他爹
    49     send_button=browser.find_element_by_class_name('nui-toolbar-item')
    50     send_button.click()
    51 
    52     #可以睡时间久一点别让浏览器关掉,看看发送成功没有
    53     import time
    54     time.sleep(10000)
    55 
    56 except Exception as e:
    57     print(e)
    58 finally:
    59     browser.close()
    View Code

    九、破解极验滑动验证

    
    
    #安装PIL模块
    #pip3 install pillow
    
    from selenium import webdriver
    from selenium.webdriver import ActionChains
    from selenium.webdriver.common.by import By  # 按照什么方式查找,By.ID,By.CSS_SELECTOR
    from selenium.webdriver.common.keys import Keys  # 键盘按键操作
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.wait import WebDriverWait  # 等待页面加载某些元素
    import time
    
    def get_image():
        #拿到验证码图片在整个页面的元素
        img=wait.until(EC.presence_of_element_located((By.CLASS_NAME,'geetest_canvas_img')))
        time.sleep(2)  # 保证验证码图片已经被加载成功
        driver.save_screenshot('snap.png')
    
        #拿到图片的位置
        top=img.location['y']
        left=img.location['x']
        right=img.location['x']+img.size['width']
        bottom=img.location['y']+img.size['height']
    
        from PIL import Image
        full_snap=Image.open('snap.png') #裁剪图片
        crop_image=full_snap.crop((left,top,right,bottom))
    
        # crop_image.show() #显示剪裁后的图片
        # crop_image.size #宽weight和高height
    
        return crop_image
    
    def get_distance(image1,image2):
        p1=image1.load()
        p2=image2.load()
        x=60
        for i in range(x,image1.size[0]):
            for j in range(20,image1.size[1]-20):
                print(i,j)
                dot1=p1[i,j]
                dot2=p2[i,j]
                r=abs(dot1[0]-dot2[0])
                g=abs(dot1[1]-dot2[1])
                b=abs(dot1[2]-dot2[2])
                if not (r < 60 and g < 60 and b < 60):
                    return i-7
        # return i
    
    def get_tracks(distance):
        t = 0.2
        v = 0
        mid=distance*3/5
        tracks=[]
    
        current=0
        while current < distance:
            if current < mid:
                a=2
            else:
                a=-3
            v0 = v
            s = v0 * t + 0.5 * a * (t ** 2)
            current+=s
            v=v0+a*t
            # print(round(s))
    
            tracks.append(round(s))
        return tracks
    
    driver=webdriver.Chrome()
    wait=WebDriverWait(driver,10)
    
    try:
        #步骤一:访问登录页面,拿到点击按钮,点击出图(完整的图)
        driver.get('https://account.geetest.com/login')
    
        button=wait.until(EC.presence_of_element_located((By.CLASS_NAME,'geetest_radar_tip')))
        button.click()
    
        #步骤二:拿到验证码图片(没有缺口)
        image1=get_image()
    
        #步骤三:拿到滑动按钮,点击出图(有缺口的图)
        button=wait.until(EC.presence_of_element_located((By.CLASS_NAME,'geetest_slider_button')))
        button.click()
    
        #步骤四:拿到验证码图片(有缺口)
        image2=get_image()
    
        #步骤五:对比两种图的像素RGB,得到不一样的像素点,取位移
        distance=get_distance(image1,image2)
        print(image1.size)
        print(image2.size)
        print(distance)
    
        #步骤六:把distance分解成一段一段的小轨迹,模拟人的行为:先匀加速再匀减速
        '''
        v=v0+a*t
        s=v0*t+0.5*a*(t**2)
        a=5
        '''
        tracks=get_tracks(distance)
    
        #步骤七:按照轨迹列表先匀加速移动再匀减速运动
        button=wait.until(EC.presence_of_element_located((By.CLASS_NAME,'geetest_slider_button')))
        ActionChains(driver).click_and_hold(button).perform()
        for track in tracks:
            ActionChains(driver).move_by_offset(xoffset=track,yoffset=0).perform()
        else:
            ActionChains(driver).move_by_offset(xoffset=3,yoffset=0).perform()
            ActionChains(driver).move_by_offset(xoffset=-3,yoffset=0).perform()
    
    
        time.sleep(0.5)
        ActionChains(driver).release().perform()
    
        time.sleep(20)
    
    finally:
        driver.close()
    View Code
    
    

    十、滑动托块

    #破码之拖动滑块
    # encoding:utf-8
    import selenium
    import time
    from selenium import webdriver
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver import ActionChains
    
    driver = webdriver.Chrome()
    # 设定等待时间
    wait = WebDriverWait(driver, 30)
    # 打开网页
    driver.get("http://……")
    
    #等待搜索框加载完成传入搜索关键字
    input = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="searchText"]')))
    input.send_keys(u"安徽投资有限责任公司")
    time.sleep(5)
    #等待搜索按钮可点击,点击
    button = wait.until(EC.element_to_be_clickable((By.XPATH,'//*[@id="click"]')))
    button.click()
    time.sleep(5)
    actions = ActionChains(driver)
    # 进入搜索页后,找到滑块
    element = driver.find_element_by_xpath("//div[@class='gt_slider_knob gt_show']")
    
    #鼠标点击元素并按住不放
    actions.click_and_hold(on_element = element).perform()
    
    #拖动鼠标到指定的位置,注意这里位置是相对于元素左上角的相对值
    actions.move_to_element_with_offset(to_element = element, xoffset=200, yoffset = 50).perform()
    # actions.move_to_element(to_element = element).perform()
    
    #释放鼠标
    actions.release(on_element = element).perform()
    time.sleep(3)
    View Code
  • 相关阅读:
    101. Symmetric Tree(js)
    100. Same Tree(js)
    99. Recover Binary Search Tree(js)
    98. Validate Binary Search Tree(js)
    97. Interleaving String(js)
    96. Unique Binary Search Trees(js)
    95. Unique Binary Search Trees II(js)
    94. Binary Tree Inorder Traversal(js)
    93. Restore IP Addresses(js)
    92. Reverse Linked List II(js)
  • 原文地址:https://www.cnblogs.com/xuanan/p/7804652.html
Copyright © 2011-2022 走看看