zoukankan      html  css  js  c++  java
  • 动态网页处理

    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 来驱动浏览器工作,而浏览器是一个个独立的浏览器进程。

       

  • 相关阅读:
    结构体中的冒号_转
    随机数产生random
    gdb调试段错误及使用
    gcc选项-g与-rdynamic的异同_转
    linux设备模型_转
    boost 1.57.0安装
    技术的正宗与野路子_转
    (转)Java里的堆(heap)栈(stack)和方法区(method)(精华帖,多读读)
    (转)面试大总结之一:Java搞定面试中的链表题目
    (转)类加载器与双亲委派模型
  • 原文地址:https://www.cnblogs.com/JerryZao/p/10103456.html
Copyright © 2011-2022 走看看