Closed vieyahn2017 closed 3 months ago
初始化 options = webdriver.ChromeOptions() options.add_argument('ignore-certificate-errors') browser = webdriver.Chrome(chrome_options=options)
登录 browser.find_element_by_name('username').send_keys(username) browser.find_element_by_name('password').send_keys(password) browser.find_element_by_name('Submit').click()
获取元素 browser.find_element_by_name browser.find_element_by_xpath
内嵌在iframe的数据 browser.switch_to.frame('x-URS-iframe') browser.switch_to.parent_frame() browser.switch_to.default_content()
https://blog.csdn.net/q1694222672/article/details/82836315
这个讲的比较全。 里面的 【交互动作,动作链 执行JavaScript Cookies 】 应该也是某些场合会用到的
https://www.cnblogs.com/zi-yao/p/6178519.html
摘录部分:
2.输入框输入字后需要点击一下屏幕其他地方触发数据校验 怎么实现? 比如我在一个输入框书写一个名字后 需要点击屏幕空白地区 来确认我输入的没问题 需要这样操作的话,可以不一定非得要点击空白区域,因为空白区域对应selenium来说没法操作。可以点击一个没有连接的静态图片或者文字,也是一样的效果
在通过selenium使用xpath选择节点的时候,可能会遇到这么一种情况:在指定的当前节点下搜索满足要求的节点
node = driver.find_element_by_xpath("//div[@class='WB_cardwrap S_bg2 clearfix']")
BZNC = node.find_element_by_xpath("//div[@class='feed_content wbcon']/a[@class='W_texta W_fb']").text
BZZY = node.find_element_by_xpath("//div[@class='feed_content wbcon']/a[@class='W_texta W_fb']").get_attribute("href")
以上代码有什么错误吗?貌似没有,一切都很完美。 先拿到node节点,然后在node节点的子节点中搜索满足条件的节点并取出text及属性。 but!运行的结果却是把整个html中所有满足条件的节点都找出来了,而并非是node节点下的!!!仔细想一想,"//div"貌似就是搜索整个html下的div,即使是node下的find_element_by_xpath方法! 所以,只需要在”//”前面加上表示当前路径的"."既可,也就是node.find_element_by_xpath(“.//div”)
https://blog.csdn.net/u012941152/article/details/83011110
js定位
search_js = "document.getElementsByName('wd')[0].value='selenium';"
search_js2 = "document.querySelectorAll('.s_ipt')[0].value='selenium';"
button_js = "document.getElementById('su').click();"
button_js2 = "document.getElementsByClassName('s_btn')[0].click()"
driver.execute_script(search_js2)
driver.execute_script(button_js2)
jQuery定位
search_jq = "$('#kw').val('selenium')"
button_jq = "$('.s_btn').click()"
driver.execute_script(search_jq)
driver.execute_script(button_jq)
正好把定位,和执行js结合起来了。
https://vonsdite.github.io/posts/cb216d2c.html
使用selector定位元素 querySelector和querySelectorAll方法是W3C Selectors API规范中定义的。 document.querySelector('*[name="username"]')
根据xpath定位元素
function find_element_by_xpath(STR_XPATH) {
var xresult = document.evaluate(STR_XPATH, document, null, XPathResult.ANY_TYPE, null);
var xnodes = [];
var xres;
while (xres = xresult.iterateNext()) {
xnodes.push(xres);
}
return xnodes;
}
find_element_by_xpath("/html/body/div/div[2]/div/div/ul/li[10]/div/span[2]/span/span")
idp.py
# -*- coding: utf-8 -*-
import os
import sys
import time
import traceback
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
from selenium.common.exceptions import NoSuchElementException
USERNAME = "-----"
PASSWORD = "-------------"
CHAPTER_INDEX = 10
# 这边爬取第10小节【录像管理接口】的api
reload(sys)
sys.setdefaultencoding( "utf-8" )
options = webdriver.ChromeOptions()
options.add_argument('ignore-certificate-errors')
browser = webdriver.Chrome(chrome_options=options)
RESTFUL_API_URL = "https://..."
API_IFRAME_ID = "iframe-ZH-CN_BOOKMAP_0237887941"
def log_w3(username, password):
base_url = "https://..."
# 隐式等待
browser.implicitly_wait(5)
##跳过安全认证
options = webdriver.ChromeOptions()
options.add_argument('ignore-certificate-errors')
##登录
browser.get(base_url)
# js: document.querySelector('*[name="uid"]')
browser.find_element_by_name('uid').send_keys(username)
browser.find_element_by_name('password').send_keys(password)
browser.find_element_by_name('Submit').click()
time.sleep(30)
# log_w3(USERNAME, PASSWORD)
log_w3("xxx", "ppp")
def getLeftFrame(initing=True):
if initing:
browser.get(RESTFUL_API_URL)
time.sleep(60)
else:
browser.switch_to.default_content()
time.sleep(10)
browser.switch_to.frame(API_IFRAME_ID)
time.sleep(10)
browser.switch_to.frame('appFrame')
time.sleep(10)
browser.switch_to.frame('manualtree')
time.sleep(10)
def getRightFrame():
browser.get(RESTFUL_API_URL)
time.sleep(60)
# browser.switch_to.default_content()
time.sleep(10)
browser.switch_to.frame('iframe-ZH-CN_BOOKMAP_0237887941')
time.sleep(10)
browser.switch_to.frame('appFrame')
time.sleep(10)
def parse_log(method, url, title):
# DELETE_RM_ORG_DEL("DELETE_/RM/Org/Del", 990402, "orgCode", "删除设备组")
# PUT_VIDEO_GRUISE_PLAN_V10("PUT_/video/gruisePlan/v1.0", 990513, "cameraCode", "设置巡航计划")
if "?" in url:
url = url.split("?")[0]
url_filter = url.replace("/", "_").replace(".", "").replace("{", "").replace("}", "").upper()
# ? url的{}再怎么处理,暂时直接去除占位符,保留其中的字母
title = title.split(" ")[-1] if " " in title else title
return "{}{}(\"{}_{}\", 999999, \"xxxCode\", \"{}\"".format(method.upper(), url_filter, method.upper(), url, title)
# 最初的思路,getLeftFrame(),拿到所有topic的id,然后再getRightFrame(),在右边遍历。但是右边的数据默认并未加载出来,这个方法不可行
# 还是得左右配合:左边点击目录树才能加载右边
def get_part_i(index):
### 获取某个章节的内容
# 观察,第9个,第10个,分别是
# /html/body/div[1]/div[2]/div/div/ul/li[9]/div/span[2]/span/span
# /html/body/div[1]/div[2]/div/div/ul/li[10]/div/span[2]/span/span
# api的二级目录(左)路径为:
# /html/body/div[1]/div[2]/div/div/ul/li[10]/ul/li[44]/div/span/span/span
"""
# api的xpath
/html/body/table/tbody/tr[3]/td[2]/div/div[1]/div[1]/div/div[1]/div[162]/article/div/p[1] # 接口描述标题
/html/body/table/tbody/tr[3]/td[2]/div/div[1]/div[1]/div/div[1]/div[162]/article/div/p[2] # 接口描述
/html/body/table/tbody/tr[3]/td[2]/div/div[1]/div[1]/div/div[1]/div[162]/article/div/p[4] # 使用说明标题
# 使用说明
/html/body/table/tbody/tr[3]/td[2]/div/div[1]/div[1]/div/div[1]/div[162]/article/div/table[1]/tbody/tr[1]/td[2]/p
/html/body/table/tbody/tr[3]/td[2]/div/div[1]/div[1]/div/div[1]/div[162]/article/div/table[1]/tbody/tr[2]/td[2]/p
/html/body/table/tbody/tr[3]/td[2]/div/div[1]/div[1]/div/div[1]/div[162]/article/div/table[1]/tbody/tr[3]/td[2]/p
/html/body/table/tbody/tr[3]/td[2]/div/div[1]/div[1]/div/div[1]/div[162]/article/div/p[7] # 示例 DELETE /record/recordplan/v1.0 HTTP/1.1
# 参数描述 标题占第一行
/html/body/table/tbody/tr[3]/td[2]/div/div[1]/div[1]/div/div[1]/div[162]/article/div/table[2]/tbody/tr[1]/td[2]/p
/html/body/table/tbody/tr[3]/td[2]/div/div[1]/div[1]/div/div[1]/div[162]/article/div/table[2]/tbody/tr[2]/td[2]/p
/html/body/table/tbody/tr[3]/td[2]/div/div[1]/div[1]/div/div[1]/div[162]/article/div/table[2]/tbody/tr[4]/td[2]/p
"""
getLeftFrame()
# XPath中的索引从1开始而不是0
part_i_xpath = "/html/body/div/div[2]/div/div/ul/li[{}]/div/span[2]/span/span".format(index)
part_i_xpath1 = "/html/body/div[1]/div[2]/div/div/ul/li[{}]/div/span[2]/span/span".format(index)
# 这两是一样的
# print(part_i_xpath)
# print(part_i_xpath1)
for i in range(3):
try:
browser.find_element_by_xpath(part_i_xpath)
break
except:
time.sleep(30)
else:
print("cannot load, exit.")
return
browser.find_element_by_xpath(part_i_xpath).click()
# 定位到父章节,并获得其中所有子元素,这边是li。判断个数
parent_li = browser.find_element_by_xpath("/html/body/div[1]/div[2]/div/div/ul/li[{}]/ul".format(index))
rows = parent_li.find_elements_by_tag_name('li')
api_numbers = len(rows)
print(api_numbers)
child_li_id = "000"
endl = "\n" # api部分每个p子元素的span带有一个好像换行符的东西,影响p元素的text取值。 见循环中i==1的部分
is_except_occur = False
for i in range(1, 1 + api_numbers):
if i == 1:
# 第一个有时候找不到,大概是还未加载
time.sleep(30)
if is_except_occur:
# 不确定出异常是在左侧还是右侧,iframe层级不同,因此,只好每次出异常,回最顶端。网上介绍的方法find_elements_by_tag_name("iframe") 不可行,大概只有在最顶端才可以执行这个查询iframe子元素。我们希望的是查询当前的父元素iframe
getLeftFrame(False)
is_except_occur = False
# 网上介绍的方法find_elements_by_tag_name("iframe") 不可行,大概只有在最顶端才可以执行这个查询iframe子元素。我们希望的是查询当前的父元素iframe
# iframe = browser.find_elements_by_tag_name("iframe")
# print(iframe.get_attribute("id"))
child_li_xpath = "/html/body/div[1]/div[2]/div/div/ul/li[{}]/ul/li[{}]/div/span/span/span".format(index, i)
try:
child_li = browser.find_element_by_xpath(child_li_xpath)
child_li_id_raw = child_li.get_attribute("id") # such as 896619110#topic#ZH-CN_TOPIC_0237887792
child_li_id = child_li_id_raw.strip().split("#")[-1].strip()
# print(child_li_id)
article_title = child_li.text.strip()
child_li.click()
time.sleep(10)
# 以上代码,左边目录加载并获取topic的id,点击后,加载右侧数据
# 右侧,获取api数据
browser.switch_to.parent_frame()
time.sleep(5)
article = browser.find_element_by_xpath("//article[@data-hd-id='{}']".format(child_li_id))
# print(article.text)
if i == 1:
endl = article.find_element_by_xpath(".//div/p[2]/span").text
article_info = article.find_element_by_xpath(".//div/p[2]").text.strip().replace(endl, "")
article_method = article.find_element_by_xpath(".//div/table[1]/tbody/tr[1]/td[2]/p").text.strip().replace(endl, "")
article_url = article.find_element_by_xpath(".//div/table[1]/tbody/tr[2]/td[2]/p").text.strip().replace(endl, "")
article_example = article.find_element_by_xpath(".//div/p[7]").text.strip().replace(endl, "")
# print(article_title)
# print(article_info)
# print(article_method)
# print(article_url)
# print(article_example)
print(parse_log(article_method, article_url, article_title))
# 下一次循环回左侧,需要多进入一层ifrmae
browser.switch_to.frame('manualtree')
time.sleep(5)
except Exception as e:
print(child_li_id)
print(e)
is_except_occur = True
continue
# get_part_i(CHAPTER_INDEX)
get_part_i(7)
print("done.")
# browser.quit()
下载chromedriver,放在比如C:\Python27\Scripts 安装pip install selenium