目录
selenium-TouchActions接口 行为控制、手势控制
定位元素方法
selenium 安装方法:https://blog.csdn.net/qq_44695727/article/details/106083938
# 查找单个元素:find_element_by_id find_element_by_name find_element_by_xpath find_element_by_link_text find_element_by_partial_link_text find_element_by_tag_name find_element_by_class_name find_element_by_css_selector # 查找多个元素 find_elements_by_name find_elements_by_xpath find_elements_by_link_text find_elements_by_partial_link_text find_elements_by_tag_name find_elements_by_class_name find_elements_by_css_selector # 两个私有方法 find_element find_elements
find_element和find_elements用法:
from selenium.webdriver.common.by import By driver.find_element(By.XPATH, '//button[text()="Some text"]') driver.find_elements(By.XPATH, '//button') XPATH = "xpath" LINK_TEXT = "link text" PARTIAL_LINK_TEXT = "partial link text" NAME = "name" TAG_NAME = "tag name" CLASS_NAME = "class name" CSS_SELECTOR = "css selector"
find_element_by_xpath用法:
绝对路径:login_form = driver.find_element_by_xpath("/html/body/form[1]") HTML中的第一个表单元素: login_form = driver.find_element_by_xpath("//form[1]") 属性id=loginForm的元素:login_form = driver.find_element_by_xpath("//form[@id='loginForm']") //div/* div下面的所有的元素 //div//p 查找div中的p节点,等于 css_selector里的('div p') //div/p 查找div的子节点p; 等价于 css_selector里的('div > p') //*[@style] 查找所有包含style的所有元素,所有的属性要加@,等于('*[style]'): //p[@spec='len'] 必须要加引号;等价于 css_selector里的("p[spec='len']") //p[@id='kw'] xpath中对于id,class与其他元素一视同仁,没有其他的方法 //div/p[2] 选择div下的第二个p节点 ;等价于css_selector里的div>p:nth-of-type(2) 符合p类型的第二个节点 //div/*[2] 选择div下第二个元素 //div/p[position()=2] position()=2 指定第二个位置; 等价于上面的 //div/p[2] position()>=2 位置大于等于2 position()<2 位置小于2 position()!=2 位置不等于2 //div/p[last()] 选择div下的倒数第一个p节点; last()倒数第一个 //div/p[last()-1] 选择div下的倒数第二个p节点; //div/p[position()=last()] 倒数第一个 //div/p[position()=last()-1] 倒数第二个 //div/p[position()>=last()-2]倒数第一个,第二个,第三个 //p | //button 选择所有的p和button,等价于css_selector里的 p, button //input[@id='kw' and @class='su'] 选择id=kw 并且 class=su的input元素 //p[@spec='len']/.. 选择p节点的上层节点 此方法在css_selector中没有 //p[@spec='len']/../.. 上层节点的上层节点
爬取网站案例:
from selenium import webdriver url = 'http://xxxxxxx' driver = webdriver.Chrome() # 隐式等待页面加载完 driver.implicitly_wait(20) # 设置窗口大小 # driver.set_window_size(10, 10) # 全屏操作 # driver.maximize_window() driver.get(url) aList = driver.find_elements_by_xpath('//*[@id="list"]//a') driver.close()
常用方法和一些常用操作
获取网页/文本
- driver.page_source 获取整个网页源代码
- get_attribute("outerHTML") 输出当前标签的本身和标签内的文本内容,如果有子标签,那么子标签本身和标签内的文本内容也将一起输出
- get_attribute('innerHTML') 获取当前标签的文本内容,如果标签内有子标签,会连子标签本身和子标签内的文本内容一起输出
- get_attribute('textContent') == .text
get_attribute:这个标签的某个属性的值。 screentshot:获取当前页面的截图。这个方法只能在driver上使用。 获取所有的cookie: for cookie in driver.get_cookies(): print(cookie)
操作节点/获取/文本框
# 获取标签内的属性值 aList[i].get_attribute('src') # 获取标签下的文本 aList[i].text # 关闭页面 driver.close() # 操作输入框:分为两步。第一步:找到这个元素。 # 第二步:使用send_keys(value),将数据填充进去 inputTag = driver.find_element_by_id('kw') inputTag.send_keys('python') # 清除输入框中的内容 inputTag.clear() # 操作checkbox # 要选中checkbox标签,在网页中是通过鼠标点击的。因此想要选中checkbox标签,那么先选中这个 # 标签,然后执行click事件 rememberTag = driver.find_element_by_name("rememberMe") rememberTag.click() # 选择select,select元素不能直接点击。因为点击后还需要选中元素。这时候selenium就专门 # 为select标签提供了一个类,示例: from selenium.webdriver.support.ui import Select # 选中这个标签,然后使用Select创建对象 selectTag = Select(driver.find_element_by_name("jumpMenu")) # 根据索引选择 selectTag.select_by_index(1) # 根据值选择 selectTag.select_by_value("http://www.95yueba.com") # 根据可视的文本选择 selectTag.select_by_visible_text("95秀客户端") # 取消选中所有选项 selectTag.deselect_all() # 按钮点击 inputTag = driver.find_element_by_id('su') inputTag.click() # 行为链: # 有时候在页面中的操作可能要有很多步,那么这时候可以使用鼠标行为链类ActionChains来完成。 # 比如现在要将鼠标移动到某个元素上并执行点击事件。那么示例代码如下: inputTag = driver.find_element_by_id('kw') submitTag = driver.find_element_by_id('su')
ActionChains(driver)鼠标事件
actions = ActionChains(driver) # 实例化一个action对象 # 移动操作 actions.move_to_element(inputTag) # 把鼠标移动到inputTag元素上,鼠标悬停 actions.move_by_offset(10, 20) # 从当前鼠标的位置向水平方向移动10个像素,向竖直方向移动20个像素 actions.send_keys_to_element(inputTag,'python') actions.send_keys("追光者") # 输入“追光者” # 全选,复制,粘贴(跨浏览器) actions.key_down(Keys.CONTROL).send_keys(‘a‘).key_up(Keys.CONTROL) #ctrl+a actions.key_down(Keys.CONTROL).send_keys(‘c‘).key_up(Keys.CONTROL) #ctrl+c actions.key_down(Keys.CONTROL,search_key).send_keys(‘v‘).key_up(Keys.CONTROL) #ctrl+v search_key=driver.find_element_by_id("search-key") search_key.send_keys(Keys.CONTROL,'v') key_down,发送,只是按下按键,并不会自动松开,而send_keys发送的键,会实现按下-松开的全过程 # 拖拽操作 actions.drag_and_drop(elem1, elem2).perform() # 把elem1元素拖拽到elem2上 actions.click_and_hold(elem1).release(elem2).perform() # 在elem1元素上按下鼠标左键不松,在elem2元素上释放,实现拖拽操作 # 点击操作 actions.click(submitTag) # 单击 actions.click_and_hold(element) # 鼠标左键按下不放 actions.context_click(element) # 右键点击。 actions.double_click(element) # 鼠标双击。 # 按下鼠标左键在一个元素上,release()释放 ActionChains(driver).click_and_hold(element).perform() ActionChains(driver).release(element).perform() actions.perform() # 执行所有ActionChains 中存储的行为
更多方法请:http://selenium-python.readthedocs.io/api.html
滑动解锁
time.sleep(3) button = driver.find_element_by_xpath('//*[@id="login-slider"]/div[1]/div[2]/div') action = ActionChains(driver) # 实例化一个action对象 action.click_and_hold(button).perform() # 鼠标左键按下不放 action.move_by_offset(400, 0).perform() # 平行移动鼠标 action.reset_actions()
登录输入
inputTag = driver.find_element_by_xpath('//*[@id="loginPage"]/ul/li[1]/div/input') inputTag.send_keys('13547584541') inputTag2 = driver.find_element_by_xpath('//*[@id="loginPage"]/ul/li[2]/div/input') inputTag2.send_keys('734888') driver.find_element_by_xpath('//*[@id="loginPage"]/div/button').click()
Python控制鼠标点击
import pyautogui # 用0.5 秒的时间把光标移动到x,y(437, 151) 位置,y竖向向下增加 pyautogui.moveTo(437, 151, duration=0.5) pyautogui.click() pyautogui.click(350, 190, button ='left')# 左击 pyautogui.click(350, 190, button ='right')# 右击
pyHook监听鼠标并打印位置
import pythoncom import PyHook3 as pyHook # 监听到鼠标事件调用 def onMouseEvent(event): if (event.MessageName == "mouse left down") and (event.MessageName != "mouse move"): # 因为鼠标一动就会有很多mouse move,所以把这个过滤下 x,y = pag.position() #返回鼠标的坐标 print(x,y) return True # 为True才会正常调用,如果为False的话,此次事件被拦截 # 创建管理器 hm = pyHook.HookManager() # 监听鼠标 hm.MouseAll = onMouseEvent hm.HookMouse() # 循环监听 pythoncom.PumpMessages()
判断节点是否存在
def isElementPresent(driver, path): #从selenium.common.exceptions 模块导入 NoSuchElementException类 from selenium.common.exceptions import NoSuchElementException try: element = driver.find_element_by_xpath(path) #原文是except NoSuchElementException, e: except NoSuchElementException as e: #打印异常信息 # print(e) #发生了NoSuchElementException异常,说明页面中未找到该元素,返回False return False else: #没有发生异常,表示在页面中找到了该元素,返回True return True res = isElementPresent(driver, "/html/div") if res is True: # -----
设置代理ip
有时候频繁爬取一些网页。服务器发现你是爬虫后会封掉你的ip地址。这时候我们可以更改代理ip。更改代理ip,不同的浏览器有不同的实现方式。这里以Chrome浏览器为例:
from selenium import webdriver options = webdriver.ChromeOptions() options.add_argument("--proxy-server=http://110.73.2.248:8123") driver_path = r"D:\ProgramApp\chromedriver\chromedriver.exe" driver = webdriver.Chrome(executable_path=driver_path,chrome_options=options) driver.get('http://xxxxx')
tab页面切换
有时候窗口中有很多子tab页面。这时候肯定是需要进行切换的。selenium提供了一个叫做switch_to_window来进行切换,具体切换到哪个页面,可以从driver.window_handles中找到。示例代码如下
# 打开一个新的页面 driver.execute_script("window.open('https://xxxxxxxx')") print(driver.window_handles) # 切换到这个新的页面中 driver.switch_to_window(self.driver.window_handles[1]) print(driver.current_url) #注意 #虽然在浏览器窗口中切换到了新的页面,但是driver中还没有切换 #如果想要在代码中切换到新的界面,那么应该使用driver.switch_to_window来切换到指定的窗口 #从driver.window_handles中取出具体第几个窗口 #driver.window_handles是一个列表,里面装的都是窗口句柄,它会按照打开的页面顺序来存储窗口的句柄。
更多python其他方法参考另一篇:
窗口切换
# 当前打开的所有窗口 windows = driver.window_handles # 转换到最新打开的窗口 driver.switch_to.window(windows[-1]) for handle in windows : # 切换窗口 if handle != driver.current_window_handle: print('switch to second window', handle) driver.close() # 关闭第一个窗口 driver.switch_to.window(handle) # 切换到第二个窗口
html转字符串:
driver.find_element_by_xpath('/html/body').get_attribute("outerHTML").__str__().replace('"', "'")
对象转json:
![]()
import json json.loads() 将json转换为dict json.dumps() 将dict转换为json json.load() 将json文件转换为dict json.dump() 将dict转换为json文件 person.json # 类对象转换为json person_json = json.dumps(person.__dict__) # 或者 # 第二个参数传递转换函数,或者使用default=lambda o: o.__dict__ person_json = json.dumps(person, default=convert2json) # 将person转换为dict def convert2json(person): return { 'name': person.name, 'age': person.age, 'email': person.email } # dict/对象转换为json文件 with open('person.json', 'w') as f: json.dump(person, f) # 将json文件转换为dict/对象 import json with open('person.json', 'r') as f: print(json.load(f))
python json.dumps() 中文乱码问题
json.dumps 序列化时默认使用的ascii编码,想输出真正的中文需要指定ensure_ascii=False:更深入分析,是应为
dJSON
object 不是单纯的unicode实现,而是包含了混合的unicode编码以及已经用utf-8编码之后的字符串。写法:
Python2 :json.dumps(odata, ensure_ascii=False).decode('utf8') json.dumps(odata,ensure_ascii=False).decode('utf8').encode('gb2312') Python3 :json.dumps(odata, ensure_ascii=False)
python-selenium切换手机模式
# 手机模式 option = webdriver.ChromeOptions() option.add_argument('disable-infobars') mobile_emulation = {"deviceName": "iPhone 6"} option.add_experimental_option('mobileEmulation', mobile_emulation) driver = webdriver.Chrome(chrome_options=option)
selenium-TouchActions接口 行为控制、手势控制
# 行为控制 perform --- 执行所有准备好的Actio # 手势控制 tap --- 在指定元素上敲击 double_tap --- 在指定元素上双敲击 tap_and_hold --- 在指定元素上点击但不释放 move --- 手势移动指定偏移(未释放) release --- 释放手势 scroll --- 手势点击并滚动 scroll_from_element --- 从某个元素位置开始手势点击并滚动 long_press --- 长按元素 flick --- 手势滑动 flick_element --- 从某个元素位置开始手势滑动 例: from selenium.webdriver.common.touch_actions import TouchActions Action = TouchActions(driver) Action.double_tap(driver.find_element_by_xpath('//*[@id="bw"]/div[1]/a[2]')) flick_element(on_element, xoffset, yoffset, speed); on_element #操作元素定位 xoffset #x轴偏移量 yoffset #y轴偏移量 speed #速度 注意:向上滑动为负数,向下滑动为正数 Action = TouchActions(driver) """从button元素像下滑动200元素,以50的速度向下滑动""" Action.flick_element(button, 0, 200, 50).perform()
selenium-开启开发者工具(F12)
option = webdriver.ChromeOptions() # 开启开发者工具(F12) option.add_argument("--auto-open-devtools-for-tabs") driver = webdriver.Chrome(chrome_options=option)
获取浏览器Network请求和响应
Selenium-获取请求的接口数据信息
Browsermob-Proxy是一个开源的Java编写的基于LittleProxy的代理服务。Browsermob-Proxy的具体流程有点类似与Flidder或Charles。即开启一个端口并作为一个标准代理存在,当HTTP客户端(浏览器等)设置了这个代理,则可以抓取所有的请求细节并获取返回内容。
- 安装:
直接到项目的github上下载打好的压缩包即可:https://github.com/lightbody/browsermob-proxy/releases ,支持Linux和Windows。
安装对应的python包:
pip install browsermob-proxy
- 完整代码:
import json from browsermobproxy import Server from selenium.webdriver.chrome.options import Options from selenium import webdriver if __name__ == '__main__': # 开启Proxy server = Server(r'D:\usr\data\browser\browsermob-proxy-2.1.4\bin\browsermob-proxy.bat') server.start() proxy = server.create_proxy() # 配置Proxy启动WebDriver chrome_options = Options() chrome_options.add_argument('--proxy-server={0}'.format(proxy.proxy)) # 解决 您的连接不是私密连接问题 chrome_options.add_argument('--ignore-certificate-errors') chrome_options.add_argument('--ignore-urlfetcher-cert-requests') driver = webdriver.Chrome(chrome_options=chrome_options) driver.implicitly_wait(20) proxy.new_har("douyin", options={'captureHeaders': True, 'captureContent': True}) driver.get(url) result = proxy.har for entry in result['log']['entries']: _url = entry['request']['url'] # 根据URL找到数据接口 if "/hotel/list" in _url: _response = entry['response'] _content = _response['content']['text'] # 获取接口返回内容 print(_content) # 读取信息 person_json = json.loads(_content) hotels = (person_json["data"])["hotels"] server.stop()