selenium使用(二)

172 阅读4分钟

行为链ActionChains

行为链可以完成简单的交互行为,例如鼠标移动,鼠标点击事件,键盘输入,以及内容菜单交互。这对于模拟那些复杂的类似于鼠标悬停和拖拽行为很有用。

当你在ActionChains对象上调用行为方法时,这些行为会存储在ActionChains对象的一个队列里。调用perform()时,这些动作就以他们队列的顺序来触发。

click(on_element=None) ——单击鼠标左键
click_and_hold(on_element=None) ——点击鼠标左键,不松开
context_click(on_element=None) ——点击鼠标右键
double_click(on_element=None) ——双击鼠标左键
drag_and_drop(source, target) ——拖拽到某个元素然后松开
move_to_element(to_element) ——鼠标移动到某个元素
perform() ——执行链中的所有动作
release(on_element=None) ——在某个元素位置松开鼠标左键
send_keys(*keys_to_send) ——发送某个键到当前焦点的元素
send_keys_to_element(element, *keys_to_send) ——发送某个键到指定元素

案例:

import time
from selenium import webdriver
from selenium.webdriver import ActionChains #导入行为链模块
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get('https://sahitest.com/demo/dragDropMooTools.htm')
time.sleep(2)
# 实例化行为链对象
action=ActionChains(driver)
# 定位到允许拖拽的元素
div=driver.find_element(By.ID,'dragger')
# 定位到拖拽的目标元素
item4=driver.find_element(By.XPATH,'//div[@class="item"][4]')

# 方法一:实现拖拽(拖拽到某个元素然后松开)  需要两个指标
# action.drag_and_drop(div,item4).perform()
# time.sleep(2)
# 方法二:实现拖拽(点击左键不松开)(再松开)
# action.click_and_hold(div).release(item4).perform()
# time.sleep(2)
# 方法三  实现拖拽
action.click_and_hold(div).move_to_element(item4).perform()
time.sleep(2)

等待

现在的网页越来越多采用了 Ajax 技术,这样程序便不能确定何时某个元素完全加载出来了。如果实际页面等待时间过长导致某个dom元素还没出来,但是你的代码直接使用了这个WebElement,那么就会抛出NullPointer的异常。为了解决这个问题。所以 Selenium 提供了两种等待方式:一种是隐式等待、一种是显式等待。

隐式等待

Selenium 有一种内置的方法来自动等待元素,称为隐式等待。 隐式等待值可以使用浏览器选项中的超时功能或驱动程序方法。

driver.implicitly_wait(10)  #只要找到元素就会立即执行,如果找不到才会等待10秒;

优点

  1. 只需设置一次,全局都生效。
  2. 如果时间内网页完成了全部加载,则立即进行下面的操作。比sleep()智能很多。

缺点

  1. 隐式等待需要等到网页所有元素都加载完成才会执行下面的操作。
  2. 如果我需要操作的元素提前加载好了,但是其他无关紧要的元素还没有加载完成,那么还是需要浪费时间去等待其他元素加载完成。

强制等待

time.sleep(10)  #无论找到还是没找到都要等待10秒钟

显示等待

显式等待是添加到轮询应用程序的代码中的循环 对于特定条件,在退出循环之前将其评估为 true,并且 继续执行代码中的下一个命令。如果在指定的超时值之前未满足条件, 该代码将给出超时错误。由于有很多方法可以使应用程序不处于所需状态, 因此,显式等待是指定要等待的确切条件的绝佳选择 在每个地方都需要它。

# 导入显示等待的模块
from selenium.webdriver.support.wait import WebDriverWait
# 导入条件模块
from selenium.webdriver.support import expected_conditions as ec

import time #强制等待
from selenium import webdriver
from selenium.webdriver.common.by import By

# 创建Chrom浏览器驱动
driver=webdriver.Chrome()
driver.get('http://baidu.com')
time.sleep(3)

#driver是webdriver对象,10是最长等待时间,0.5是每0.5秒去查询对应的元素。
# until后面跟的等待具体条件,EC是判断条件,检查元素是否存在于页面的 DOM 上。
ele=WebDriverWait(driver,10,0.5).until(ec.presence_of_element_located((By.XPATH,'//*[@id="kw"]')))
ele.send_keys('编程')
time.sleep(3)
buttom=driver.find_element(By.XPATH,'//*[@id="su"]')
buttom.click()
time.sleep(3)

selenium被识别

selenium做爬虫能解决很多反爬问题,但是selenium也有很多特征可以被识别,比如用selenium驱动浏览器后window.navigator.webdriver值是true,而正常运行浏览器该值是false 通过访问bot.sannysoft.com/网站观察浏览器参数的变化。

正常访问:

image.png

通过selenium浏览器访问: image.png

解决办法:

import time
from selenium import webdriver
from selenium.webdriver import Keys

drive = webdriver.Chrome()

# 解决办法:
# stealth.min.js这个文件 用于抹去自动化程序特征的,可百度搜索下载
with open('stealth.min.js','r')as f:
    js = f.read()
# 让浏览器在新打开的文档中 执行抹去特征的js文件
drive.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",{"source":js})

drive.get('https://bot.sannysoft.com/')
time.sleep(100)

案例

import time
from selenium import webdriver
from selenium.webdriver.common.by import By

driver=webdriver.Chrome()
driver.maximize_window()
# data=driver.page_source#获取页面源代码
driver.get('https://jzsc.mohurd.gov.cn/data/company')
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
time.sleep(3)
# driver.implicitly_wait(10)#隐式等待

list_info=[]
def parse_data():
    for tr in driver.find_elements(By.CLASS_NAME,'el-table__row'):
        dict_info={}
        dict_info['code']=tr.find_element(By.XPATH,'./td[2]/div').text
        dict_info['title']=tr.find_element(By.XPATH,'./td[3]/div/span').text
        dict_info['address']=tr.find_element(By.XPATH,'./td[5]/div').text
        list_info.append(dict_info)

def page_data():
    for i in range(5):
        if i==0:
            continue
        else:
            btn=driver.find_element(By.XPATH,'//button[@class="btn-next"]')
            btn.click()
            parse_data()
            time.sleep(3)


#调用每一页的数据
page_data()
parse_data()

print(list_info)
print(len(list_info))