博客
关于我
动态网页 —— selenium+案例
阅读量:695 次
发布时间:2019-03-17

本文共 4110 字,大约阅读时间需要 13 分钟。

使用Selenium库进行动态网页爬取 Frame(iframe)切换操作详解

在开发自动化测试或动态网页爬取任务时,Selenium库提供了强大的页面操作和元素定位功能。然而,当项目涉及包含多个Frame(内嵌页面)的动态网页时,操作过程中经常会遇到元素定位失败的问题。这种情况下,我们需要理解并掌握Frame切换的相关知识,以确保能够正确识别和操作目标元素。

本文将详细介绍如何在Selenium库中处理Frame切换,具体包括Frame定位方法和实际案例——QQ邮箱信息爬取的实现。


现状与问题

当我们使用Selenium库对动态网页内容进行爬取时,通常会遇到以下错误情形:

吴腾富发在博客中提到frame窗口切换的问题,但并未详细讲解。今天就用Selenium库详细讲解frame的使用。

如果反复检查网页源码发现目标元素在页面中存在,并且使用Firebug等工具也能找到该元素,但Selenium定位却失败,该怎么办?答案是:我们需要先确认微调窗口是否切换了。

要理解这一点,需要了解Selenium如何处理页面布局。WebDriver只能在同一页面的元素进行识别和定位,对于内嵌的Frame表单内的元素,直接定位将失败。


Frame切换方法

在Selenium库中,Frame切换可通过 switch_to.frame() 方法实现,支持以下几种定位方式:

1. 使用Frame ID或名称定位

大多数情况下,Frame会有一些独特的属性,比如id或name。可以使用以下方式切换:

driver.switch_to.frame("login_frame")  # 根据Frame的id切换

此外,也可以传入Frame的name属性进行切换。

2. 根据Frame的索引定位

如果Frame没有id或name属性,Selenium可以根据Frame在页面中的顺序索引进行切换。索引从0开始计算:

driver.switch_to.frame(0)

3. 通过 WebElement 对象定位

如果你已经定位到了某个元素,并需要将该元素所属的Frame切换进来,可以直接使用该元素对象进行切换:

element = driver.find_element_by_tag_name('iframe')driver.switch_to.frame(element)

进一步切换——切换回主页面

在爬取过程中,我们经常需要切换回主页面进行操作。可以使用 switch_to.default_content() 方法完成这一操作:

driver.switch_to.default_content()

此方法会自动定位并切换回主页面的内容,从而使我们能够操作主页面中的元素。


窗口切换——switch_to.window()

在某些场景中,网页会打开新的窗口(如点击链接或下载文件等),这时可以通过以下方式切换到新窗口:

for handle in driver.window_handles:    driver.switch_to.window(handle)

注意:Window_Handle通常是一个唯一的标识符,用于区分不同的窗口。


案例——QQ邮箱信息爬取

在如今的动态网页中,表单结构越来越复杂,常包含多个Frame和页面跳转。以下是使用Selenium库爬取QQ邮箱信息的实现步骤。


登录流程

  • 打开QQ邮箱登录页面:
  • driver.get('https://mail.qq.com/')time.sleep(3)
    1. 切换Frame进入登录界面:
    2. driver.switch_to.frame('login_frame')time.sleep(3)
      1. 模拟输入登录信息:
      2. login_element = driver.find_element_by_name('u')login_element.send_keys('QQ账号')  # 请输入QQ号password_element = driver.find_element_by_name('p')password_element.send_keys('QQ密码')  # 请输入QQ密码login_button = driver.find_element_by_id('login_button')login_button.click()time.sleep(3)
        1. 切换回主页面:
        2. driver.switch_to.default_content()time.sleep(3)

          收件箱信息爬取

        3. 点击收件箱:
        4. inbox_element = driver.find_element_by_id('folder_1')inbox_element.click()time.sleep(3)
          1. 切换到收件箱内部Frame:
          2. driver.switch_to.frame('mainFrame')time.sleep(3)
            1. 提取收件箱信息:
            2. # 使用BeautifulSoup或其他工具解析页面内容source = driver.page_source# 通过解析获取收件箱内容from lxml import etreehtml = etree.HTML(source)for row in html.xpath('//tr[@id="div_showbefore"]/tbody/tr/td'):    addressee = row.xpath('nobr/span/text()')[0].strip()    email = row.xpath('@e')[0]    title = row.xpath('div/u/text()')[0]    date = row.xpath('div/text()')[0]    # 将数据保存至数据库    result.append([addressee, email, title, date])

              数据库保存

              from selenium import webdriverimport timeimport pymysql# 数据库连接信息,注意替换为你的数据库信息dbinfo = {    'host': 'localhost',    'user': 'root',    'password': '你的密码',    'db': 'qq_email',    'charset': 'utf8'}def save_to_mysql(sql, val):    try:        conn = pymysql.connect(**dbinfo)        cursor = conn.cursor()        cursor.execute(sql, val)        conn.commit()    except Exception as e:        print(f'错误:{e}')        conn.rollback()    finally:        cursor.close()        conn.close()if __name__ == '__main__':    # 初始化浏览器    driver = webdriver.Chrome('路径到chromedriver.exe')    driver.get('https://mail.qq.com/')    time.sleep(3)        # 登录    driver.switch_to.frame('login_frame')    login_email = driver.find_element_by_name('u')    login_email.send_keys('QQ账号')    password = driver.find_element_by_name('p')    password.send_keys('QQ密码')    login_button = driver.find_element_by_id('login_button')    login_button.click()    time.sleep(3)    driver.switch_to.default_content()    time.sleep(3)        # 收件箱    inbox_button = driver.find_element_by_id('folder_1')    inbox_button.click()    time.sleep(3)    main_frame = driver.find_element_by_id('mainFrame')    driver.switch_to.frame(main_frame)    time.sleep(3)        # 爬取数据    source = driver.page_source    save_to_mysql(        "INSERT INTO qq_youxiang (addressee, email, title, date) VALUES (%s, %s, %s, %s)",        result    )        # 关闭浏览器    driver.quit()

              注意事项

            3. Frame选择:明确Frame的定位方式,避免因窗口切换而导致定位失败。
            4. 窗口切换:在处理多窗口切换时,确保正确使用 switch_to.window(handle) 方法。
            5. 数据库设置:请根据实际情况修改数据库信息。
            6. 浏览器驱动:在生产环境中,建议使用不同的浏览器驱动(如chrome_option)。
            7. 通过以上方法,可以轻松处理包含Frame的动态网页爬取任务,同时充分利用Selenium库的强大功能。希望本文能为您的开发工作提供帮助!

    转载地址:http://aiphz.baihongyu.com/

    你可能感兴趣的文章
    MySQL-Explain的详解
    查看>>
    mysql-group_concat
    查看>>
    MySQL-redo日志
    查看>>
    MySQL-【1】配置
    查看>>
    MySQL-【4】基本操作
    查看>>
    Mysql-丢失更新
    查看>>
    Mysql-事务阻塞
    查看>>
    Mysql-存储引擎
    查看>>
    mysql-开启慢查询&所有操作记录日志
    查看>>
    MySQL-数据目录
    查看>>
    MySQL-数据页的结构
    查看>>
    MySQL-架构篇
    查看>>
    MySQL-索引的分类(聚簇索引、二级索引、联合索引)
    查看>>
    Mysql-触发器及创建触发器失败原因
    查看>>
    MySQL-连接
    查看>>
    mysql-递归查询(二)
    查看>>
    MySQL5.1安装
    查看>>
    mysql5.5和5.6版本间的坑
    查看>>
    mysql5.5最简安装教程
    查看>>
    mysql5.6 TIME,DATETIME,TIMESTAMP
    查看>>