最近在爬取Kaseya远程监控平台数据的时候遇到一些难题,这个老牌监控平台页面使用的是frameset框架构建的,需要定位的元素在子框架中的不同页面,所以需要定位元素需要在不同的ifream中来回切换,故有了以下研究。
一、frameset框架介绍
1、<frameset> 标签
frameset 元素可定义一个框架集。它被用来组织多个窗口(框架)。每个框架存有独立的文档。在其最简单的应用中,frameset 元素仅仅会规定在框架集中存在多少列或多少行。您必须使用 cols 或 rows 属性。
重要事项:您不能与 <frameset></frameset> 标签一起使用 <body></body> 标签。不过,如果您需要为不支持框架的浏览器添加一个 <noframes> 标签,请务必将此标签放置在 <body></body> 标签中
1.1 格式
<frameset cols="280,*" framespacing="0" border="0" bordercolor="#333333">
<frameset rows="390,*" framespacing="0" border="0">
<frame name="accessFrame" scrolling="no" src="logon.asp?0.19116143065271418" frameborder="no" marginwidth="0" marginheight="0"></frame>
<frame name="leftFrame" src="loginCtl.asp?0.5055629947442568" scrolling="auto" frameborder="no" marginwidth="0" marginheight="0" noresize=""></frame>
</frameset>
<frame name="headerFrame" src="defaultContent.htm" scrolling="no" frameborder="no" marginwidth="0" marginheight="0" noresize=""></frame>
</frameset>
1.2 子项说明
<frame src="logon.asp"></frame>
<frame> 标签定义 frameset 中的一个特定的窗口(框架)。
1.3 frameset 属性
src 规定在框架中显示的文档的 URL。
name 规定框架的名称。
2、iframe 标签
HTML内联框架元素(<iframe>
) 表示嵌套的browsing context。它能够将另一个HTML页面嵌入到当前页面中。
每个iframe元素都有自己的会话历史记录(session history)和DOM树。包含嵌入内容的浏览上下文称为<dfn style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-weight: inherit;">父级</dfn>浏览上下文。顶级浏览上下文(没有父级)通常是由Window
对象表示的浏览器窗口。
页面上每个<iframe>
都会需要包括内存占用在内的额外计算资源,这是因为每个<iframe>
会都构建出一颗完整的DOM树。虽然理论上来说你能够在代码中写出来无限多的<iframe>
,但是你最好还是先看看这么写会不会导致某些性能问题。
2.1 格式
<iframe id="x-history-frame"></iframe>
2.2 属性
name
能够用于定位内联框架(iframe)的名称。
src
规定在 iframe 中显示的文档的 URL。
二、Selenium爬取信息
导入相关的包
from selenium.webdriver import Chrome
# 导入Select 利用select模块处理下拉框选择option
from selenium.webdriver.support.select import Select
import time
开始爬取
# 实例化Chrome浏览器对象
web = Chrome()
# 设置超时时间
web.set_page_load_timeout(300)
# 打开登录页面
web.get("Kaseya地址/access/logon.asp")
# 最大化窗口
web.maximize_window()
# 查找登陆框,输入账号
web.find_element_by_name("adminName").send_keys("你的用户名")
# password
web.find_element_by_name("pass").send_keys("你的密码")
# 点击登陆按钮
web.find_element_by_xpath('//*[@id="ext-gen1018"]/form/table/tbody/tr[8]/td/input').click()
各个ifream之间来回之间切换需要使用switch_to功能
switch_to_iframe() # 切换到iframe上(已弃用)
switch_to.frame() # 切换到iframe上
switch_to.default_content() # 切换回原主页面
登录进去后,发现有多个分页,要想全部爬取得进行页面切换
# 查找翻页按钮所在的iframe
filters = web.find_element_by_xpath('//*[@id="panel-1052-body"]/iframe')
# 进入iframe
web.switch_to.frame(filters)
# 获取分页页数
option = web.find_elements_by_xpath('//*[@id="ext-gen3"]/form/table/tbody/tr[2]/td[1]/select[1]/option')
获取到页数后开始爬取
# 循环爬取
for d in range(len(option)-1):
# 选择页面
d = d*100
print(d)
Select(web.find_element_by_xpath('//*[@id="ext-gen3"]/form/table/tbody/tr[2]/td[1]/select[1]')).select_by_value("%s" %d)
time.sleep(5)
# 切换回原主页面
web.switch_to.default_content()
# 切换到iframe上
iframe = web.find_element_by_xpath('//*[@id="panel-1055-body"]/iframe')
web.switch_to.frame(iframe)
# find_elements_by_**** 查找多个element
tbody = web.find_elements_by_xpath('//*[@id="Table1"]/tbody/tr')
for i in range(len(tbody)+1):
if i > 0:
terminal_id = web.find_element_by_xpath('//*[@id="Table1"]/tbody/tr[%s]/td[1]' %i).text
name = web.find_element_by_xpath('//*[@id="Table1"]/tbody/tr[%s]/td[2]' %i).text
ip = web.find_element_by_xpath('//*[@id="Table1"]/tbody/tr[%s]/td[3]'%i).text
user = web.find_element_by_xpath('//*[@id="Table1"]/tbody/tr[%s]/td[4]'%i).text
reboot_time = web.find_element_by_xpath('//*[@id="Table1"]/tbody/tr[%s]/td[5]'%i).text
start_time = web.find_element_by_xpath('//*[@id="Table1"]/tbody/tr[%s]/td[6]'%i).text
groups = web.find_element_by_xpath('//*[@id="Table1"]/tbody/tr[%s]/td[7]'%i).text
# 存文件
with open("data.csv", mode="a") as f:
f.write(terminal_id+","+name+","+ip+","+user+","+reboot_time+","+start_time+","+groups+"\n")
# 切换回原主页面
web.switch_to.default_content()
filters = web.find_element_by_xpath('//*[@id="panel-1052-body"]/iframe')
web.switch_to.frame(filters)