• 动态网页处理


    1、概述:

      很多网站都采用AJAX 技术,SPA技术,部分都是异步动态加载的,可以提高用户体验,减少不必要的流浪,方便CDN 加速

      但是,对于爬虫程序爬到的HTML页面相当于页面的模板,动态内容不在其中

      解决办法之一:如果能构造一个包含js引擎的浏览器,让他加载网页并和网站交互,我们编程从这个浏览器获取内容包括动态内容,这个浏览器不需要和用户交互的界面,只要你能支持HTTP ,HTTPS 协议 和服务器交互,能解析HTML CSS JS 就行

    2、PhantomJS    

      它是一个headless无头浏览器,支持js, 可以运行在windows, Linux, MacOS

      所谓无头浏览器,就是包含JS引擎,浏览器排版引擎等核心组件,但是没有和用户交互的界面的浏览器

      官网:http://phantomjs.org/

      官方文档:http://phantomjs.org/documentation/

      下载:http://phantomjs.org/download.html

      下载对应操作系统的PhantomJS ,解压就可以使用

      测试:

        编写test.js ,执行: $ phantomjs/bin/phantomjs.exe  test.js

              

    3、Selenium

      它是一个WEB 自动化测试工具,它可以直接运行在浏览器中,支持主流的浏览器,包括PhantomJS(无界面浏览器)

      安装:

        $ pip install  selenium

      官网:https://www.seleniumhq.org/

        

    4、开发实战

      不同浏览器都会提供操作的接口,Selelnium 就是使用这些接口来操作浏览器的。

      Selenium 最核心的对象就是webdriver, 通过它 就可以操作浏览器,截图,HTTP 访问,解析HTML 等

      处理异步请求:

        bing的查询结果是通过异步请求返回结果,所以直接访问页面不能直接获取到搜索结果。

        测试:

     1 # 查询bing查询数据
     2 from selenium import webdriver # 核心对象
     3 import  datetime
     4 import random
     5 import time
     6 from urllib import  parse
     7 
     8 # 指定PhantomJS 的执行文件路径
     9 driver = webdriver.PhantomJS('f:/phantomjs-2.1.1-windows/phantomjs-2.1.1-windows/bin/phantomjs.exe')
    10 # 设置窗口大小
    11 driver.set_window_size(1280,1024) #
    12 
    13 # 打开浏览器GET 方法,模拟浏览器地址输入网址
    14 url = 'http://cn.bing.com/search?' +parse.urlencode({
    15     'q':'张三'
    16 })
    17 
    18 driver.get(url)
    19 
    20 # 保存图片
    21 def savepic():
    22     base_dir = 'f:/'
    23     filename = "{}{:%Y%m%d%H%M%S}{:03}.png".format(
    24         base_dir,
    25         datetime.datetime.now(),
    26         random.randint(1,100)
    27     )
    28     
    29     driver.save_screenshot(filename)
    30 
    31 savepic()
    32 
    33 MAXRETRIEX = 5 # 最大重试次数
    34 for i in range(MAXRETRIEX):
    35     time.sleep(1)
    36     try:
    37         ele = driver.find_element_by_id('b_results')#如果查询结果来了,就会有这个id的标签
    38         if not ele.is_displayed(): # 等待数据显示出来
    39             continue
    40         print('ok')
    41         savepic()
    42         break
    43     except:
    44         pass
    45 
    46 driver.quit()

        

        

        可能结果未必能看到,说明数据回来了,而且组织好了,但是没有显示出来,DOM 树没有渲染

        可以增加判断元素是否显示的代码,直到等待的数据显示在页面上

    5、下拉框处理

      Selenium 专门提供了select类来处理网页中的下拉框

      不过下拉框用的页面越来越少,本次使用:https://www.oschina.net/search?q=python&scope=project&fromerr=fYWMOvs4

      (这种页面很笨重,每选一下,重新发起请求,但是很多东西  css等可以缓存,所以,还有使用)

      

      这个下拉框影响下一个 下拉框:所有子类, 下面就模拟来操作下拉框,需要使用:

        selenium.webdriver.suport.select.Select    

      

       测试代码:

     1 # 查询bing查询数据
     2 from selenium import webdriver # 核心对象
     3 import  datetime
     4 import random
     5 import time
     6 from urllib import  parse
     7 from selenium.webdriver.support.ui import Select
     8 
     9 # 指定PhantomJS 的执行文件路径
    10 driver = webdriver.PhantomJS('f:/phantomjs-2.1.1-windows/phantomjs-2.1.1-windows/bin/phantomjs.exe')
    11 # 设置窗口大小
    12 driver.set_window_size(1280,1024) #
    13 
    14 # 保存图片
    15 def savepic():
    16     base_dir = 'f:/'
    17     filename = "{}{:%Y%m%d%H%M%S}{:03}.png".format(
    18         base_dir,
    19         datetime.datetime.now(),
    20         random.randint(1,100)
    21     )
    22 
    23     driver.save_screenshot(filename)
    24 
    25 # 打开浏览器GET 方法,模拟浏览器地址输入网址
    26 url = "https://www.oschina.net/search?q=python&scope=project"
    27 driver.get(url)
    28 
    29 ele = driver.find_element_by_name('tag1') # 获取元素
    30 print(ele.tag_name) # 标签名
    31 print(driver.current_url)# 当前的url
    32 savepic()
    33 
    34 s = Select(ele)
    35 s.select_by_index(1)
    36 # s.select_by_value('309')
    37 print(driver.current_url) #新页面
    38 
    39 driver.quit()

        结果:

    1 D:python3.7libsite-packagesseleniumwebdriverphantomjswebdriver.py:49: UserWarning: Selenium support for PhantomJS has been deprecated, please use headless versions of Chrome or Firefox instead
    2   warnings.warn('Selenium support for PhantomJS has been deprecated, please use headless '
    3 select
    4 https://www.oschina.net/search?q=python&scope=project&fromerr=4VrMLlrv
    5 https://www.oschina.net/search?q=python&scope=project&tag1=309&tag2=0&lang=0&os=0

        

        

                  ||

                  ||

        

    6、模拟键盘操作(模拟登录)  

      webdriver 提供了一系列的 find 方法,用户获取一个网页中的元素,元素对象可以使用send_keys 模拟键盘输入

      oschina的登录页,登录成功后,会跳转到首页,首页右上角会显示会员信息,如果未登录,无此信息。

      测试:

     1 # 查询bing查询数据
     2 from selenium import webdriver # 核心对象
     3 import  datetime
     4 import random
     5 import time
     6 from urllib import  parse
     7 from selenium.webdriver.support.ui import Select
     8 
     9 # 指定PhantomJS 的执行文件路径
    10 driver = webdriver.PhantomJS('f:/phantomjs-2.1.1-windows/phantomjs-2.1.1-windows/bin/phantomjs.exe')
    11 # 设置窗口大小
    12 driver.set_window_size(1280,1024) #
    13 
    14 # 保存图片
    15 def savepic():
    16     base_dir = 'f:/'
    17     filename = "{}{:%Y%m%d%H%M%S}{:03}.png".format(
    18         base_dir,
    19         datetime.datetime.now(),
    20         random.randint(1,100)
    21     )
    22 
    23     driver.save_screenshot(filename)
    24 
    25 # 打开浏览器GET 方法,模拟浏览器地址输入网址
    26 url = "https://www.oschina.net/home/login"
    27 driver.get(url)
    28 savepic()
    29 
    30 # 模拟输入用户名和密码
    31 username = driver.find_element_by_id('userMail') # 获取元素
    32 username.send_keys("wei.xu@magedu.com")
    33 password = driver.find_element_by_id('userPassword') #获取元素
    34 password.send_keys('magedu.com18')
    35 savepic()
    36 
    37 MAXRETRIEX = 5 # 最大重试次数
    38 for i in range(MAXRETRIEX):
    39     time.sleep(1)
    40     print(i, driver.current_url)
    41     try:
    42         # 登录后右上角的元素 class = "box user-info"
    43         userinfo = driver.find_element_by_class_name('user-info')
    44         savepic()
    45         break
    46     except:
    47         pass

        结果:

    1 0 https://www.oschina.net/home/login
    2 1 https://www.oschina.net/home/login
    3 2 https://www.oschina.net/home/login
    4 3 https://www.oschina.net/home/login
    5 4 https://www.oschina.net/home/login

        

          登录后:

        

          截图:

            

        

        获得cookies后,可以继续后面的爬虫操作:

        测试:

     1 # 查询bing查询数据
     2 from selenium import webdriver # 核心对象
     3 import  datetime
     4 import random
     5 import time
     6 from urllib import  parse
     7 from selenium.webdriver.support.ui import Select
     8 
     9 # 指定PhantomJS 的执行文件路径
    10 driver = webdriver.PhantomJS('f:/phantomjs-2.1.1-windows/phantomjs-2.1.1-windows/bin/phantomjs.exe')
    11 # 设置窗口大小
    12 driver.set_window_size(1280,1024) #
    13 
    14 # 保存图片
    15 def savepic():
    16     base_dir = 'f:/'
    17     filename = "{}{:%Y%m%d%H%M%S}{:03}.png".format(
    18         base_dir,
    19         datetime.datetime.now(),
    20         random.randint(1,100)
    21     )
    22 
    23     driver.save_screenshot(filename)
    24 
    25 # 打开浏览器GET 方法,模拟浏览器地址输入网址
    26 url = "https://www.oschina.net/home/login"
    27 driver.get(url)
    28 savepic()
    29 
    30 # 模拟输入用户名和密码
    31 username = driver.find_element_by_id('userMail') # 获取元素
    32 username.send_keys("wei.xu@magedu.com")
    33 password = driver.find_element_by_id('userPassword') #获取元素
    34 password.send_keys('magedu.com18')
    35 savepic()
    36 
    37 MAXRETRIEX = 5 # 最大重试次数
    38 for i in range(MAXRETRIEX):
    39     time.sleep(1)
    40     print(i, driver.current_url)
    41     try:
    42         userinfo = driver.find_element_by_class_name('user-info')
    43         savepic()
    44         break
    45     except:
    46         pass
    47 
    48 
    49 ###############   登录后获得cookie ###############
    50 cookies = driver.get_cookies()
    51 print(cookies)
    52 for c in cookies:
    53     print(c)
    54     print(type(c))
    55 
    56 import requests
    57 from requests.cookies import RequestsCookieJar
    58 
    59 jar = RequestsCookieJar()
    60 for c in cookies:
    61     jar.set(c.get('name'), c.get('value'))
    62 
    63 print(jar)
    64 headers = {
    65     "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3486.0 Safari/537.36"
    66 }
    67 
    68 print(' ============   不带cookie ============')
    69 response = requests.request('GET', url, headers= headers)
    70 with response:
    71     print('----', response.url)
    72 
    73 print('==================  带cookie =============')
    74 response = requests.request('GET', url, headers=headers, cookies=jar)
    75 with response:
    76     print('++++', response.url)
    77     print(type(response.text))
    78     with open("f:/t.html", 'w', encoding='utf-8') as f:
    79         f.write(response.text)

       

    7、页面等待

       越来越多的页面使用Ajax这样的异步加载技术,这就会导致代码中要访问的颜面元素,还没有被加载就被访问了。抛出异常。

      方法1,线程休眠:

      使用time.sleep() 来等待数据加载

      配合循环一直等到数据被加载完成,可以解决很多页面动态加载或加载慢的问题,当然可以设置一个最大重试次数,以免一直循环下去,

      方法2 ,Selenium 等待

      Selenium 的等待分为:显示等待 和隐式等待

      隐式等待: 等待指定的时间

      显示等待:指定一个条件,一直等到这个条件成立后继续执行,也可以设置超时时间,超时会抛异常

        参考:https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp#explicit-and-implicit-waits

      显示等待:

        

              

     1 # 定位搜索框,搜索电影
     2 from selenium import webdriver # 核心对象
     3 import  datetime
     4 import random
     5 
     6 from selenium.webdriver.common.by import  By
     7 # 键盘操作
     8 from selenium.webdriver.common.keys import Keys
     9 # WebDriverWait 负责循环的等待
    10 from selenium.webdriver.support.wait import WebDriverWait
    11 # expected_conditions 条件,负责条件触发
    12 from selenium.webdriver.support import expected_conditions as EC
    13 
    14 # 指定 PhantomJS的执行文件路径
    15 driver = webdriver.PhantomJS('f:/phantomjs-2.1.1-windows/phantomjs-2.1.1-windows/bin/phantomjs.exe')
    16 # 设置窗口大小
    17 driver.set_window_size(1280,1024) #
    18 
    19 # 保存图片
    20 def savepic():
    21     base_dir = 'f:/'
    22     filename = "{}{:%Y%m%d%H%M%S}{:03}.png".format(
    23         base_dir,
    24         datetime.datetime.now(),
    25         random.randint(1,100)
    26     )
    27 
    28     driver.save_screenshot(filename)
    29 
    30 # 打开网页GET方法,模拟浏览器地址输入网址
    31 url = 'https://movie.douban.com/'
    32 driver.get(url)
    33 
    34 try:
    35     # element = WebDriverWait(driver,10).until(
    36     #     EC.presence_of_element_located(
    37     #         # 元素是否已经加载到DOM 中
    38     #         (By.ID,'inp-qurey')
    39     #     )
    40     # ) # 使用哪个drivel  等到什么条件ok, EC 就是等待的条件
    41 
    42     element = WebDriverWait(driver, 10).until(
    43         EC.presence_of_element_located((By.XPATH, "//input[@id='inp-qurey']"))
    44     )
    45 
    46     element.send_keys('TRON')
    47     element.send_keys(Keys.ENTER)
    48 
    49     print(driver.current_url)
    50     savepic()
    51     print('============')
    52 
    53 except Exception  as e:
    54     print(e)
    55 finally:
    56     driver.quit()

         默认的查看频率是0.5 秒每天,当元素存在则立即返回这个元素

      隐式等待:

        如果出现No Such Element Exception  则智能的等待指定的时长,缺省值是0   

     1 # 定位搜索框,搜索电影
     2 from selenium import webdriver # 核心对象
     3 import  datetime
     4 import random
     5 
     6 from selenium.webdriver.common.by import  By
     7 # 键盘操作
     8 from selenium.webdriver.common.keys import Keys
     9 # WebDriverWait 负责循环的等待
    10 from selenium.webdriver.support.wait import WebDriverWait
    11 # expected_conditions 条件,负责条件触发
    12 from selenium.webdriver.support import expected_conditions as EC
    13 
    14 # 指定 PhantomJS的执行文件路径
    15 driver = webdriver.PhantomJS('f:/phantomjs-2.1.1-windows/phantomjs-2.1.1-windows/bin/phantomjs.exe')
    16 # 设置窗口大小
    17 driver.set_window_size(1280,1024) #
    18 
    19 # 保存图片
    20 def savepic():
    21     base_dir = 'f:/'
    22     filename = "{}{:%Y%m%d%H%M%S}{:03}.png".format(
    23         base_dir,
    24         datetime.datetime.now(),
    25         random.randint(1,100)
    26     )
    27 
    28     driver.save_screenshot(filename)
    29 
    30 # 打开网页GET方法,模拟浏览器地址输入网址
    31 url = 'https://movie.douban.com/'
    32 driver.get(url)
    33 
    34 try:
    35     element = driver.find_element_by_id('abcdfe')
    36 
    37 except Exception  as e:
    38     print(e)
    39     print(type(e))
    40 finally:
    41     driver.quit()

      

    总结:

       Selenium的webdriver是其核心, 从Selenium2开始就是最重要的核心编程对象, 在Selenium3中更加是如此

      和浏览器交互完全靠他, 他可以:

      • 打开URL,可以跟踪跳转,可以返回当前页面的实际URL
      • 获取页面的title
      • 处理cookie
      • 控制浏览器的操作, 例如 前进,后退,刷新,关闭,最大化等
      • 执行JS 脚本
      • 在DOM 中搜索页面 元素Web Element 指定的或一批,fing系方法
      • 操作网页元素
        • 模拟下拉框操作 Selelct(element)
        • 在元素上模拟鼠标操作  click(
        • 在元素上模拟键盘输入send_keys()
        • 获取元素的文字text
        • 获取元素的属性 get_attribute()
        •           

       Selenium 通过Web Driver 来驱动浏览器工作,而浏览器是一个个独立的浏览器进程。

       

  • 相关阅读:
    广域网(ppp协议、HDLC协议)
    0120. Triangle (M)
    0589. N-ary Tree Preorder Traversal (E)
    0377. Combination Sum IV (M)
    1074. Number of Submatrices That Sum to Target (H)
    1209. Remove All Adjacent Duplicates in String II (M)
    0509. Fibonacci Number (E)
    0086. Partition List (M)
    0667. Beautiful Arrangement II (M)
    1302. Deepest Leaves Sum (M)
  • 原文地址:https://www.cnblogs.com/JerryZao/p/10103456.html
Copyright © 2020-2023  润新知