一、思路
获取的思路很简单:点击所有元素,发生跳转事件就获取。
二、逻辑
1.获取所有元素;
使用XPath表达式:“//*”匹配所有元素;
获取所有元素的数量;
遍历元素:“(//*)[n]”,其中n为序号,从1开始;
2.全部模拟鼠标点击;
使用Selenium自带的鼠标点击方法,可能会出现页面遮挡的问题,最好使用js的方法点击;
3.判断跳转;
(1).在当前页面跳转:
提前获取原始页面的内容,点击元素之后再获取一遍,如果内容不一致说明发生了跳转;
也可以通过链接的变化来判断是否跳转,但有些页面是单页面应用,链接可能不会发生变化;
(2).打开新标签页跳转:
直接获取新标签页的链接;
三、代码
该代码会报一些无法点击的异常
import time
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
# 设置Chrome浏览器驱动路径
driver_path = "chromedriver.exe"
# 初始化Chrome浏览器
driver = webdriver.Chrome(executable_path=driver_path)
driver.maximize_window()
# 打开网页
driver.get("https://www.baidu.com")
wait = WebDriverWait(driver, 10)
# 获取原有内容
xPath = '//body'
elements = driver.find_elements(By.XPATH, xPath)
content = elements[0].get_attribute('innerText')
# 获取页面上所有的元素
xPath = '//*'
elements = driver.find_elements(By.XPATH, xPath)
# 点击每个元素并获取跳转后的URL
for index, element in enumerate(elements):
try:
try:
element.click()
time.sleep(1)
except:
continue
# try:
# # 使用js点击
# xPath = '({})[{}]'.format(xPath, index + 1)
# js = 'document.evaluate("{}",document).iterateNext().click()'.format(xPath)
# driver.execute_script(js)
# time.sleep(1)
# except:
# continue
pages = driver.window_handles
page_num = len(pages)
if page_num > 1:
driver.switch_to.window(pages[1])
WebDriverWait(driver, 10)
current_url = driver.current_url
driver.close()
driver.switch_to.window(pages[0])
else:
# 获取新内容
xPath = '//body'
elements = driver.find_elements(By.XPATH, xPath)
new_content = elements[0].get_attribute('innerText')
if new_content != content:
current_url = driver.current_url
# 返回原页面
driver.get("https://www.baidu.com")
else:
continue
print("Clicked element:", element.tag_name)
print("Current URL:", current_url)
except Exception as e:
print('错误:', e)
continue
# 关闭浏览器
driver.quit()
四、注意
- 页面含有多个网页嵌套iframe,iframe里面也有iframe,iframe套娃,Selenium获取iframe里面的内容需要先切换到iframe里面才能获取,而且获取完之后还要切换回原页面,非常麻烦;
- 页面含有隐藏的元素,只有点击才会出现,使用上述方法点击之后会因为新元素的出现导致前后内容不一致,误以为在当前页签跳转,实际并没有;
- 因为每个元素都会点击一遍,类似“”这种嵌套元素,XPath会匹配每一层嵌套,并依次点击div > a > span,这样的话,在HTML中明明表示是同一种链接,但使用XPath“(//*)[n]”匹配就会匹配出3个元素,并被点击三次,获取三个同样的链接,套娃式的标签嵌套也是无法获取全部链接的最大难题;
- XPath“(//*)[n]”会匹配所有页面上的元素,包括:head、meta、link、script、style、title等隐藏元素,虽然执行点击操作也不会发生什么,但会浪费大量时间,使整个获取过程变得非常缓慢。
六、总结
综上所述,Selenium可以获取页面的所有链接,但是一个网页的元素标签非常多,通过XPath表达式:“//*”匹配所有元素并遍历点击,这个过程非常缓慢。
如果想快速获取页面的所有链接,还是需要人工点击一遍网页的所有内容,确认该元素点击之后可发生跳转,然后通过Xpath表达式指定元素获取。
也就是说使用Selenium一键式获取页面上的所有链接,是非常不现实的,需要人工辅助。
版权归原作者 vdoi 所有, 如有侵权,请联系我们删除。