篇二:爬虫笔记-Selenium动态网页

  • 一、动态网页爬虫

    1、基本概念

    1. 动态网页:在网页不重新加载的情况下,通过ajax技术动态更新网站中的局部数据
    2. AJAX(asynchronous javascript and xml)异步JavaScript和xml,传统传输数据格式是xml语法,现在使用的数据格式基本都是JSON
    3. 使用Ajax加载的数据查看源代码是找不到的

    2、动态网页爬虫的解决方案

    1. 直接分析Ajax调用的接口,然后通过代码去请求这个接口
      • 优点:不需要做一些解析工作,代码量少,性能高
      • 缺点:分析接口比较复杂,特别是通过js混淆的接口,要有js功底,否则容易发现是爬虫
    2. 使用selenium+chromedriver模拟浏览器的行为
      • 优点:直接模拟浏览器行为,更稳定
      • 缺点:代码量多,性能低

    二、Selenium

    • Selenium相当于一个机器人,可以模拟人类在浏览器上的行为,比如点击,填充数据,删除cookie。
    • chromedriver是一个驱动Chrome浏览器的驱动程序,使用它才可以驱动浏览器。

    A、基本使用

    1. 打开网页地址

      driver = webdriver.Chrome(executable_path=‘’)

      driver.get(“网页地址”)

      from selenium import webdriver
      
      driver = webdriver.Chrome(executable_path=r"E:\develop\chromedriver\chromedriver_win32\chromedriver.exe")
      driver.get("https://www.baidu.com")
      
    2. 关闭网页

      driver.close()关闭当前网页

      driver.quit()退出浏览器,关闭所有网页

    3. 定位元素

      find_element:获取第一个满足条件的元素

      find_elements:获取所有满足条件的元素

      #根据ID查找,并填充文本框
      inputTag = driver.find_element_by_id("kw")
      inputTag.send_keys("加油啦")
      # 根据class查找
      input_tag = driver.find_element_by_class_name("s_ipt")
      input_tag.send_keys("努力女孩")
      
      input_tag = driver.find_element_by_name("wd")
      input_tag = driver.find_element_by_tag_name("input")
      input_tag = driver.find_element_by_xpath("//input[@id='kw']")
      input_tag = driver.find_element_by_css_selector("#form #kw")      
      

    B、表单元素

    1. 操作input

      • driver.find_element_xx()找到需要的元素
      • .sendKey(“”)填充值
    2. 操作checkbox

      • driver.find_element_xx()找到需要的元素
      • .click进行点击勾选
    3. 操作select

      select元素不能直接点击,因为点击后还要选择元素,所以selenium提供了一个类selenium.webdriver.support.ui.Select将所获得的元素当成参数传到这个类里,创建这个对象就可以对这个对象进行选择了

      • selectTag = Select(driver.find_element_xx())选择需要的标签,使用select创建对象
      • selectTag.select_by_index(n)根据索引选择
      • selectTag.select_by_value(“”)根据值选择
      • selectTag.select_by_visible_text(“”)根据可视的文本选择

    C、行为链

    • 行为链更能模拟人的行为,功能更加强大,更稳定,在自动化测试中非常有用

    • 步骤

      1. 获得驱动

        driver = webdriver.Chrome(驱动的绝对地址)

      2. 打开网址

        driver.get(url)

      3. 封装对象

        actions = ActionChains(driver)

      4. 获得需要操作的标签

        driver.find_element_by_xx

      5. 行为链模拟人类行为

        actions.move_to_element(xx)

      6. 运行,执行

        actions.perform()

        可以让它睡1一秒钟去执行下面的语句time.sleep(1)

      from selenium import webdriver
      from selenium.webdriver import ActionChains
      #获得驱动,打开网址
      driver = webdriver.Chrome(executable_path=r"E:\develop\chromedriver\chromedriver_win32\chromedriver.exe")
      driver.get("https://www.dlmu.edu.cn/")
      #封装对象
      actions = ActionChains(driver)
      #获得标签
      inputTag = driver.find_element_by_id("showkeycode180073")
      submitTag = driver.find_element_by_xpath("//form[@id='au1a']/input[@type='image']")
      #模拟人类行为
      actions.move_to_element(inputTag)
      actions.send_keys_to_element(inputTag, "指导员")
      actions.move_to_element(submitTag)
      actions.click(submitTag)
      #执行
      actions.perform()
      

    D、Cookie操作

    • 获得所有的cookie:get_cookies()
    • 获得key代表的cookie:get_cookie(key)
    • 删除所有的cookie:delete_all_cookies()
    • 删除某个cookie:delete_cookie(key)
    • 添加cookie:add_cookie({“key”:“value”, “key”:“value”,…})

    E、页面等待

    由于很多网站采取Ajax技术,所以这样程序有些标签可能加载不出来,提供两种等待方式:

    一、显示等待;指定等待的时间和条件,如果在等待的时间里等待的条件满足了,就不用等待了,WebDriverWait(driver, 等待时间).until(
    EC.text_to_be_present_in_element_value((By.ID, "ID名"),"标签里的值")
    )

    二、隐式等待;指定等待时间,不管条件满足与否也要等待那么久,driver.implicitly_wait(n)

    • 显示等待事例

      from selenium import webdriver
      from selenium.webdriver.common.by import By
      from selenium.webdriver.support.wait import WebDriverWait
      from selenium.webdriver.support import expected_conditions as EC
      
      driver = webdriver.Chrome(executable_path=r"E:\develop\chromedriver\chromedriver_win32\chromedriver.exe")
      driver.get("https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc")
      
      WebDriverWait(driver, 100).until(
          EC.text_to_be_present_in_element_value((By.ID, "fromStationText"),"长沙")
      )
      WebDriverWait(driver, 100).until(
          EC.text_to_be_present_in_element_value((By.ID, "toStationText"),"成都")
      )
      btn = driver.find_element_by_id("query_ticket")
      btn.click()
      

    F、页面切换

    • 打开新窗口:driver.execute_script("window.open('地址')")
    • 控制台显示网页的代码:driver.page_source
    • 切换页面:driver.switch_to.window(driver.window_handles[n])
    from selenium import webdriver
    
    driver = webdriver.Chrome(executable_path=r"E:\develop\chromedriver\chromedriver_win32\chromedriver.exe")
    driver.get("https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc")
    #隐式等待
    driver.implicitly_wait(2)
    driver.execute_script("window.open('https://www.baidu.com/')")
    #控制台显示12306的代码
    print(driver.page_source)
    # 切换页面
    driver.switch_to.window(driver.window_handles[1])
    #控制台显示百度代码
    print(driver.page_source)
    

    三、12306抢票(未完)

    import time
    
    from selenium import webdriver
    from selenium.webdriver import ActionChains
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    import csv
    
    driver = webdriver.Chrome(executable_path=r"E:\develop\chromedriver\chromedriver_win32\chromedriver.exe")
    actions = ActionChains(driver)
    login_before = "https://www.12306.cn/index/"
    login_on = "https://kyfw.12306.cn/otn/resources/login.html"
    login_after = "https://kyfw.12306.cn/otn/view/index.html"
    left_ticket = "https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc"
    
    class GetTicket:
        #初始化
        def __init__(self, fromstation, tostation, datestation, trains):
            """
            :param fromstation:
            :param tostation:
            :param datestation:
            :param trains:
            """
            self.fromstation =fromstation
            self.tostation = tostation
            self.datestation = datestation
            self.trains = trains
            self.station_code = {}
            self.init_station()
        #初始化站点所对应的代号
        def init_station(self):
            with open("stations.csv", "r", encoding="utf-8") as fp:
                reader = csv.DictReader(fp)
                for line in reader:
                    name = line["name"]
                    code = line["code"]
                    self. station_code[name] = code
        # 获得登录页面
        def get_scan(self):
            driver.get(login_before)
            loginTag = driver.find_element_by_xpath("//li[@id='J-header-login']/a")
            actions.move_to_element(loginTag)
            actions.click()
            actions.perform()
            WebDriverWait(driver, 100).until(
                EC.url_contains(login_on)
            )
            print("获得扫描")
        # 登录
        def login(self):
            WebDriverWait(driver, 100).until(
                EC.url_contains(login_after)
            )
            print("登陆成功")
        # 删除弹窗
        def del_ok(self):
            time.sleep(10)
            driver.find_element_by_class_name("btn-primary").click()
    
        def search_left(self):
            driver.find_element_by_xpath("//li[@id='J-chepiao']/a").click()
            driver.find_element_by_xpath("//*[@id='J-chepiao']/div/div[1]/ul/li[1]/a").click()
            from_station_input = driver.find_element_by_id("fromStation")
            from_station_code = self.station_code[self.fromstation]
            to_station_input = driver.find_element_by_id("toStation")
            to_station_code = self.station_code[self.tostation]
            date = driver.find_element_by_id("train_date")
            driver.execute_script("arguments[0].value='%s'"%from_station_code, from_station_input)
            driver.execute_script("arguments[0].value='%s'"%to_station_code, to_station_input)
            driver.execute_script("arguments[0].value='%s'"%self.datestation, date)
            search_click = driver.find_element_by_id("query_ticket")
            search_click.click()
    
    
        def run(self):
            # 获得登录页面
            self.get_scan()
            # 登录
            self.login()
            # 删除弹窗
            self.del_ok()
            # 余票查询
            self.search_left()
    def main():
        getTicket = GetTicket("北京北", "重庆", "2020-12-24","G306")
        getTicket.run()
    if __name__ == '__main__':
       main()
    

你可能感兴趣的:(数据分析笔记,爬虫,selenium,python)