因为工作内容每个月需要整理大量的数据,于是决定自己写个脚步来爬取数据,顺便学习练习一下selenium的使用
背景
因工作需要每个月都需要整理40个项目左右的慢SQL以及慢事务的数据,纯靠人工整理数据实在是费时费力,第一次整理数据时需要花差不多5天的时间,所以趁这个机会写个脚本,以后再整理数据就不用那么累了(可以摸鱼了),数据为内部数据。
-
搞定登录页面:因为没有开启验证码,所以搞定登录脚本只需要简简单单的定位用户名和密码输入框输入内容,再定位登录登录按钮-点击,就可以登录成功了。
(1)通过控制台查找到用户名输入框有个id属性,通过id属性我们就可以唯一的定位到用户输入框,然后通过.send_keys()方法输入用户名。(定位密码框,输入密码同理)
# 输入用户名
username=driver.find_element(By.ID,'username')
username.send_keys('nb')
(2)登录成功后进入应用一览页面,然后通过id定位时间设置按钮-点击,以此类推再定位点击按钮设置为指定时间,再通过.execute_script(‘arguments[0].value=“2022-05-01 00:00”’,time_type)方法设置我们需要的时间。
# 点击日历控件
__timePanel__=driver.find_element(By.ID,'__timePanel__')
__timePanel__.click()
sleep(0.8)
#点击自定义时间
time_type=driver.find_element(By.ID,'time_type')
time_type.click()
sleep(0.8)
# 输入开始时间
time_type=driver.find_element(By.ID,'timeForm_fromTime')
driver.execute_script('arguments[0].value="2022-05-01 00:00"',time_type)
# 输入结束时间
timeForm_endTime=driver.find_element(By.ID,'timeForm_endTime')
driver.execute_script('arguments[0].value="2022-06-01 00:00"',timeForm_endTime)
(3)接下来再通过定位下拉选择框选择我们需要查询的应用组,此处下拉选择框虽然用的是select框(网页代码中能看到select标签),但却不能通过select单选框的Select方法来选择内容。然后观察到页面使用的是ul列表来制作的下拉选项内容,于是我们可以通过XPATH值来定位我们想要的选项,且由于只能选择在页面显示出来的元素,于是还需要判断选项在下拉列表的位置是否需要滑动到下拉列表的底部。
# 函数,判断应用组是否存在内容
def content():
if '实例数量' in driver.page_source:
return 1
else:
return 0
#根据应用组定位的XPATH值定义列表,遍历选择应用组
# [15,16,6,8,7,4]
pitch_on_list=[15,16,6]
for m in pitch_on_list:
sleep(1)
groupid = driver.find_element(By.CLASS_NAME, 'selected') #获取下拉列表,点击下拉列表
groupid.click()
sleep(1)
if m > 8 : #根据元素XPATH值判断应用组在下拉列表的位置,如位置在下面则通过移动鼠标到下拉列表位置,输入空格滚动下拉列表
for i in range(3):
nav=driver.find_element(By.CLASS_NAME,'jg-scrollbar-y')
ActionChains(driver).move_to_element(nav).perform()
driver.find_element(By.TAG_NAME, 'body').send_keys(' ')
sleep(0.5)
target = driver.find_element(By.XPATH,f'//*[@id="mainPage"]/div/div/div/div[2]/div[2]/div[1]/div/div/ul/li[{m}]')
sleep(0.5)
target.click()
sleep(1)
# 判断所选应用组是否存在内容
if content()==0: continue
(4)选择好应用后通过id定位表格,然后读取表格里的内容,获取每个应用组下的所有应用列表,然后点击跳转进入应用页面。再点击定位数据库按钮,进入详情页面,方法和前面类似,这里就不再赘述。
(5)进入页面后滑动到页面底部定位表格获取数据,我们可以通过向页面发送空格键滑动到页面底部,当前慢SQL数据不会一次全部加载,并且通过观察发现页面按钮标签是一直存在的,通过改变按钮的display属性来决定按钮是否显示,所有我们可以所以通过获取元素的display属性值判断页面中加载更多这个按钮是否存在从而来判断是否需要继续加载数据
# 向页面输入空格跳到页面底部
# sleep(1)
# 等待页面加载完成再跳转到页面底部
try:
database_list = driver.find_element(By.CLASS_NAME, 'ground')
except Exception as e:
pass
else:
title = driver.find_element(By.CLASS_NAME, 'frame_page_second_title')
title.click()
for i in range(5):
driver.find_element(By.TAG_NAME, 'body').send_keys(' ')
sleep(0.5)
# 页面中加载更多这个按钮是一直存在的,通过display属性来显示或隐藏,所以通过获取元素的display属性值判断页面中
# 加载更多这个按钮是否存在从而来判断是否需要继续加载数据
button = driver.find_element(By.ID, 'loadData')
button_display = button.value_of_css_property("display")
# print(button_display)
while button_display == 'block':
sleep(0.8)
button.click()
button_display = button.value_of_css_property("display")
(6)接下来只需要定位table表格提取数据,然后写入csv文件就完成一个应用的整理,然后再完善其他亿点点细节就可以实现遍历整理所有的应用组里的所有应用了。
完整代码如下,代码里有详细的注释
import re
import csv
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome()
# 隐式等待 ,或者 全局等待 。
# 该方法接受一个参数, 用来指定 最大等待时长。
driver.implicitly_wait(10)
driver.get("#url")
# 输入用户名
username=driver.find_element(By.ID,'username')
username.send_keys('username')
# 输入密码-登录
password=driver.find_element(By.ID,'password')
password.send_keys('password\n')
sleep(1)
# 点击日历控件
__timePanel__=driver.find_element(By.ID,'__timePanel__')
__timePanel__.click()
sleep(0.8)
#点击自定义时间
time_type=driver.find_element(By.ID,'time_type')
time_type.click()
sleep(0.8)
# 输入开始时间
time_type=driver.find_element(By.ID,'timeForm_fromTime')
driver.execute_script('arguments[0].value="2022-05-01 00:00"',time_type)
# 输入结束时间
timeForm_endTime=driver.find_element(By.ID,'timeForm_endTime')
driver.execute_script('arguments[0].value="2022-06-01 00:00"',timeForm_endTime)
# 设置时间
time_ok=driver.find_element(By.ID,'time_ok')
time_ok.click()
sleep(1)
# 函数,判断应用组是否存在内容
def content():
if '实例数量' in driver.page_source:
return 1
else:
return 0
#根据应用组定位的XPATH值定义列表,遍历选择应用组
# [15,16,6,8,7,4]
pitch_on_list=[15,16,6,8,7,4]
for m in pitch_on_list:
sleep(1)
groupid = driver.find_element(By.CLASS_NAME, 'selected') #获取下拉列表,点击下拉列表
groupid.click()
sleep(1)
if m > 8 : #根据元素XPATH值判断应用组在下拉列表的位置,如位置在下面则通过移动鼠标到下拉列表位置,输入空格滚动下拉列表
for i in range(3):
nav=driver.find_element(By.CLASS_NAME,'jg-scrollbar-y')
ActionChains(driver).move_to_element(nav).perform()
driver.find_element(By.TAG_NAME, 'body').send_keys(' ')
sleep(0.5)
target = driver.find_element(By.XPATH,f'//*[@id="mainPage"]/div/div/div/div[2]/div[2]/div[1]/div/div/ul/li[{m}]')
sleep(0.5)
target.click()
sleep(1)
# 判断所选应用组是否存在内容
if content()==0: continue
# 获取选中的项目名称
pitch_on = driver.find_element(By.XPATH, '//*[@id="mainPage"]/div/div/div/div[2]/div[2]/div[1]/a/span')
#收起应用详情
sleep(1)
Pack_up_the_list = driver.find_element(By.ID, 'doMore0')
Pack_up_the_list.click()
sleep(1)
# 定位表单
project_tbody = driver.find_element(By.XPATH, '//*[@id="hasDataTbody"]')
project_list = project_tbody.text.split('\n')
#处理列表文本提取表单应用名
project_list_len=len(project_list)
project_option=[]
for i in range(project_list_len):
if i % 6 == 0:
project_option.append(project_list[i])
# project_option[2] 可以变量化,如project_option[i],然后可以把进入数据库读取数据的脚步封装成函数
#根据提取的应用名提取选择选项
project_option_quantity=len(project_option)
with open(r'C:\Users\Administrator\Desktop\test.csv', 'a+', encoding='utf-8', newline='') as f:
csv_writer = csv.writer(f)
csv_writer.writerow(["应用", "SQL操作", "追踪次数", "平均执行时间(ms)", f"{pitch_on.text}"])
#根据观察,下拉列表选项中css属性的title值跟选项一致,所有可以根据csstitle属性选择对应应用
for k in range(project_option_quantity):
project = driver.find_element(By.CSS_SELECTOR, f'[title="{project_option[k]}"]')
sleep(1)
project.click()
# 进入数据库页面 !!!!数据库没有数据的情况没有做判断
sleep(1.5)
databases = driver.find_element(By.CSS_SELECTOR, '[href="/server/application/{applicationId}/databases"]')
databases.click()
# 向页面输入空格跳到页面底部
# sleep(1)
# 等待页面加载完成再跳转到页面底部
try:
database_list = driver.find_element(By.CLASS_NAME, 'ground')
except Exception as e:
pass
else:
title = driver.find_element(By.CLASS_NAME, 'frame_page_second_title')
title.click()
for i in range(5):
driver.find_element(By.TAG_NAME, 'body').send_keys(' ')
sleep(0.5)
# 页面中加载更多这个按钮是一直存在的,通过display属性来显示或隐藏,所以通过获取元素的display属性值判断页面中
# 加载更多这个按钮是否存在从而来判断是否需要继续加载数据
button = driver.find_element(By.ID, 'loadData')
button_display = button.value_of_css_property("display")
# print(button_display)
while button_display == 'block':
sleep(0.8)
button.click()
button_display = button.value_of_css_property("display")
# 选择慢SQL表单
SQL_tbody = driver.find_element(By.XPATH, '//*[@id="sqlTrace"]/tbody')
# 文本切片处理
text = SQL_tbody.text
text = text.split('\n')
# 处理list列表,把对应数据写到csv文件
# with open(r'C:\Users\Administrator\Desktop\test.csv', 'a+', encoding='utf-8', newline='') as f:
# csv_writer = csv.writer(f)
# csv_writer.writerow(["应用", "SQL操作", "追踪次数", "平均执行时间(ms)",f"{pitch_on}"])
j = len(text)
for i in range(j):
if i % 2 == 1:
text_mach = text[i].split(' ')
with open(r'C:\Users\Administrator\Desktop\test.csv', 'a+', encoding='utf-8', newline='') as f:
csv_writer = csv.writer(f)
csv_writer.writerow([project_option[k], text[i - 1], text_mach[0], text_mach[1]])
# 读取完一个应用的数据后再回到概览页面读取下一个应用的慢SQL
overview = driver.find_element(By.XPATH, '//*[@id="server_overview"]/div')
overview.click()
sleep(1)