对于一些程序化的WEB操作,Python 的requests和selenium都能够很方便实现。前者适用于程序逻辑和参数清晰明确的快速自动化。参数构造复杂和需要图形化时,selenium或许就是更好的选择。这篇适用于有了想要实现的自动化目标,结合内容快速编写相应代码。
浏览器驱动
geckodriver适用于Firefox,chromedrvier适用于chrome,下载对应的驱动即可。
绕过反爬的风控机制
网上已有的分析就不重复搬运了,这篇selenium 成功绕过淘宝登录反爬机制就对淘宝的反爬做了分析。
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
option = webdriver.ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
option.add_argument("--disable-blink-features=AutomationControlled")
browser = webdriver.Chrome(executable_path="E:/Python/chromedriver.exe", options=option)
browser.get('https://www.baidu.com')
定位和操作元素
浏览器的对于WEB网页的操作无非鼠标移动,点击,键盘的键值发送这类操作。但这些操作也有些小坑在里面。操作的第一步就是定位需要被操作的对象,最常用的是通过浏览器的开发者模式直接复制XPATH或者CSS选择器来定位元素。F12打开开发者窗口-----》选取元素----》鼠标右键----》copy selector或者copy Xpath。
当然也是支持通过class name, link text, partial link text, tag name等来定位,具体参见selelium开发手册。
这里主要讲讲怎么灵活运用和结合这些元素定位操作,来精准完成程序的控制流。
有得元素需要加载出来才显示和可操作,可以用WebDriverWait来查找,避免直接查找元素出现找不到元素的error
css_selecot = '#kw'
ele = WebDriverWait(browser, timeout=30).until(
EC.presence_of_element_located(
(By.CSS_SELECTOR, css_selector)))
ele.click()
打开的窗口大小有差异,有时需要被点击的元素不在顶层,导致点击该元素会点到其他顶层的元素时可以通过JS来精准点击
css_selecot = '#kw'
ele = WebDriverWait(browser, timeout=30).until(
EC.presence_of_element_located(
(By.CSS_SELECTOR, css_selector)))
browser.execute_script("arguments[0].click();", ele)
隐藏的页面需要onmouseover事件发生才显示的元素,可以通过ActionChains实现移动鼠标到目标元素,显示隐藏元素并点击隐藏元素。
target_ele = browser.find_element_by_xpath('')
hidden_ele = browser.find_element_by_xpath('')
ActionChains(browser).move_to_element(target_ele).click(hidden_ele).perform()
对于加载完成属性等有变化的元素,可以监控属性值保证在正确的时机完成操作
def able_click(css_selector, ):
ele = WebDriverWait(browser, timeout=30).until(
EC.presence_of_element_located(
(By.CSS_SELECTOR, css_selector)))
while ele.value_of_css_property('background').find('9,') < 0:
sleep(2)
ActionChains(browser).move_to_element(ele).perform()
ele = browser.find_element_by_css_selector(css_selector)
print('.', end='')
browser.execute_script("arguments[0].click();", ele)
return 0
有的元素不在视图中无法触发onmouserover之类的属性,可以先滚动页面直到显示
js = "arguments[0].scrollIntoView();"
mobiledescription = browser.find_element_by_id('struct-mobiledescription')
browser.execute_script(js, mobiledescription)
js = "var q=document.documentElement.scrollTop=400"
browser.execute_script(js)
有的元素怎么定位都定位不到,那可能是内嵌的iframe中的元素,需要切换到对应的iframe才能定位和操作元素
detail_editor_iframe = browser.find_elements(By.TAG_NAME, 'iframe')[2]
browser.switch_to.frame(detail_editor_iframe)
browser.switch_to.parent_frame()
拖动一个或者多个本地文件到上传文件框实现文件上传
file_location = "/tmp/file1 \n /tmp/file2"
up_box = 'body > input[type=file]'
browser.find_element_by_css_selector(up_box).send_keys(file_location)
删除原来input框填充值并写入新的值
product_title = WebDriverWait(browser, timeout=30).until(EC.presence_of_element_located((By.XPATH, '//*[@id="title"]')))
product_title.send_keys(Keys.COMMAND + 'a')
product_title.send_keys(Keys.DELETE)
product_title.send_keys('new title')
自动化的WEB可能任意一步没有按照预期执行后面的执行流就乱了,需要不停的调试和写try catch处理异常。一个成熟的程序一定是千锤百炼和耐心的一遍一遍调试出来的。
参考文档
selenium中文开发手册
|