微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

selenium网页自动登录、打卡三

文章目录


前言

前面做了一个自动打卡小程序,基本可以实现上班签到,下班签退的任务,并白嫖了CSDN的服务器作为数据收发的基础。在继续优化功能的同时,解决了selenium使用过程中的小坑点。

  1. 定位以及切换frame(iframe)
  2. webdriver爬虫#document问题

一、Python+Selenium

具体的环境配置可以参考之前的文章

二、webdriver中#document问题

如图,我们想获取#document下面body的内容

在这里插入图片描述

如果直接通过获取到的xpath定位的话

driver = webdriver.Firefox()
driver.get(url)
driver.find_element_by_xpath()
print(driver .page_source)

会发现#document下的内容为空。换言之,根本没有定位到相应的元素,而且#document下的内容也没有爬取到。观察发现,#docoment的上一级是iframe标签,相当于内嵌了一段HTML到原本的代码中,根据之前新打开标签页的经验:当driver重新打开一个标签页,需要通过如下代码切换到子标签页中。

current_windows = browser.window_handles
# browser.switch_to_window(current_windows[1])
self.__driver.switch_to.window(current_windows[0])
self.__driver.maximize_window()

因此对于iframe来说,也是同样的,需要切换到iframe中才能定位到相应的元素完成爬取。很多人在用selenium定位页面元素的时候,通过浏览器获取的Xpath元素就是定位不到,这种情况很有可能是frame在搞鬼。

2.1 切换frame的方法

  1. selenium提供了switch_to.frame()方法来切换frame

    switch_to.frame(reference)
    switch_to_frame(reference)
    

    提到switch_to_frame(),这个方法已经out了,之后很有可能会不支持,建议的写法是switch_to.frame(),反正到时候多尝试几次,总有一个是可以的。reference是传入的参数,用来定位frame,可以传入id、name、index以及selenium的WebElement对象。例如:

    from selenium import webdriver
    driver = webdriver.Firefox()
    driver.switch_to.frame(0)  # 1.用frame的index来定位,第一个是0
    driver.switch_to.frame("frame1")  # 2.用id来定位
    driver.switch_to.frame("myframe")  # 3.用name来定位
    driver.switch_to.frame(driver.find_element_by_tag_name("iframe"))  # 4.用WebElement对象来定位
    
  2. 从frame中切回主文档(switch_to.default_content())
    切到frame中之后,我们便不能继续操作主文档的元素,这时如果想操作主文档内容,则需切回主文档。

    driver.switch_to.default_content()
    
  3. 嵌套frame的操作(switch_to.parent_frame()),有时候我们会遇到嵌套的frame,如下:

    <html>
        <iframe id="frame1">
            <iframe id="frame2" / >
        </iframe>
    </html>
    

    从主文档切到frame2,一层层切进去:

    driver.switch_to.frame("frame1")
    driver.switch_to.frame("frame2")
    
  4. 所以只要善用以下三个方法,遇到frame分分钟搞定:

    driver.switch_to.frame(reference)
    driver.switch_to.parent_frame()
    driver.switch_to.default_content()
    

2.2 切换#docment的方法

有了刚刚的切换iframe的基础,就可以获取到iframe中的内容了,此时如果通过xpath的方法去定位document中的内容,结果却任然是失败的。网上找到了如下方法,实测有用:在get(url)之后使用

driver.switch_to_default_content() 
frame = driver.find_elements_by_tag_name('iframe')[0]  
driver.switch_to_frame(frame) 

跳转到iframe中,然后再driver.find_element_by_xpath即可,至于这种跳转方法为什么可以,俺也搞不清楚。

2.3 切换#docment的子#document方法

这次遇到的是#document中套着#document套着#document,无论多少级,切换的方法和iframe的嵌套类似,一层一层切换下去

# 切换到子#document
frame1 = browser3.find_elements_by_tag_name('iframe')[0]  
browser3.switch_to_frame(frame1) 

# 切换到孙子#document
frame2 = browser3.find_elements_by_tag_name('iframe')[0]
browser3.switch_to_frame(frame2)   
#print(browser1.page_source)

在这里插入图片描述

总体流程如下:因为#document是嵌入在iframe中的,多层嵌套代码如下:

# 切换到mainFrame这个iframe中的#document==0
browser3.switch_to_default_content() 
frame = browser3.find_elements_by_tag_name('iframe')[0]  
browser3.switch_to_frame(frame) 

# 切换到子#document
frame1 = browser3.find_elements_by_tag_name('iframe')[0]  
browser3.switch_to_frame(frame1) 

# 切换到孙子#document
frame2 = browser3.find_elements_by_tag_name('iframe')[0]
browser3.switch_to_frame(frame2)   

# 点击确定,确定按钮在上一级iframe
browser3.switch_to.parent_frame()

# 点击确定按钮,再回到第一级
browser3.switch_to.default_content()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐