我们在工作中时长会用到一些在线表格实现多人协作,但是有事会遇到一些例如数据的录入等人工操作过于麻烦,或者需要周期性的操作,我们希望使用自动化的方式在指定的数据源获取数据然后按照指定的要求填入在线表格
【GIF】
有两种实现方式:
本地实现表格的操作就不多说,有多种方式来实现,无非是导入在线表格,这里我们也是需要提前登录才行,一般的上传导入重名也不会出现覆盖的情况所以我们相当于生成一个新的表格,
在操作之前我们可以下载旧的表格数据,再次基础上进行操作
然后再上传导入,导入之前记得删除原表格
实现在线文档的编辑三步走:
1、设置浏览器和代理调用UI自动化操作的时候直接操作已打开的浏览器
2、登录在线文档:在打开的浏览器打开并登录在线文档--此文直接进入需要操作的文档
3、通过键盘操作来实现文档内容的增删改查【登录用户要具备相应的权限】
本文只要讲解第二种方式。
在接到需求的时候首先想到的就是接口的方式,没办法谁让它最为习惯也最为稳定呢,但是在调研过程中发现两个比价难以突破的问题:
1、接口请求时需要使用cookie,存在多个cookie而且有时效性,无法实现保持可用cookie
2、在线表格内容发生变更接口保存数据后分析难度比较高
最终放弃此方式,因为本身对自动化有所研究就考虑使用UI自动化的方式来实现,有存在新的问题
1、登录:UI自动化打开新网页需要登录【已解决】
2、表格内容属于画布里面,只能定位到画布,画布内部无法精确定位到每个表格【已解决】
from selenium import webdriver #调用webdriver
from selenium.webdriver.chrome.options import Options #设置浏览器初始化内容
from selenium.webdriver.common.by import By #定位元素
from selenium.webdriver.common.keys import Keys #键盘操作
保持登录–取巧:发现在线文档只要登录之后不主动退出/长时间不操作则都可以一直保持登录,那我们就可以直接操作已经登录的在线文档不就好啦,但是用过selenium的都知道,调用webdriver默认会打开一个纯净的浏览器,后来想到一个就是我不打开新的浏览器,直接操作已经打开的浏览器是不是就能实现。
下面是实现过程:
(1)打开浏览器设置端口调试代理和数据存储:
# 进入浏览器的安装目录中【可以在任务管理器跳转过去】打开CMD窗口执行下面命令既可【注意端口号和用户数据存储位置是可以改的】
chrome.exe --remote-debugging-port=9222 --user-data-dir="G:\test"
#9222 是端口号,最好不要和本机其他端口号冲突,G:\test打开的浏览器用户数据存储,这里设置一个存在的目录既可
#回车之后会打开一个空白的浏览器,在这个浏览器上登录就行,
(2)webdriver的初始化中写入调试的数据就可以操作打开的浏览器,而不是重新打开新的
chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
此时再执行脚本就是操作我们上面打开的浏览器,不是冲洗打开空白浏览器啦
没啥可多说的,上一步打开的浏览器扫码之类的登录就行
本来想着修改哪一行数据直接定位哪一行双击修改既可,但是出现了一个小意外:表格是在一个画布上,想定位画布上的表格发现不能进行下一步的定位啦,这让我毫升的郁闷呢
最终查阅了一些资料找寻到了两种可行的办法
(1)坐标定位
我们可以定位到画布,画布是有坐标的,我们可以通过不断变更坐标的位置来实现表格定位,
但是有一个弊端,如果表格大小发生变更了,那之前的坐标都需要调整,而且还要手动去滑动表格
ele = 画布定位
ActionChains(driver).move_to_element_with_offset(ele,X,Y).send_keys('输入内容')
最终此种方法不好用被舍弃
(2)通过键盘的操作
发现我们可以通过剪片的HOME键、TAB键、ENTER键,以及上下键实现表格定位
在表格的最上方输入框是在画布之外的可以进行增删改查等操作
driver.find_element(By.XPATH, '//*[@id="alloy-simple-text-editor"]').send_keys(Keys.HOME)
driver.find_element(By.XPATH, '//*[@id="alloy-simple-text-editor"]').send_keys(Keys.CONTROL, Keys.UP)
driver.find_element(By.XPATH, '//*[@id="alloy-simple-text-editor"]').send_keys(Keys.ENTER)
driver.find_element(By.XPATH, '//*[@id="alloy-simple-text-editor"]').send_keys(Keys.TAB)
然后我们根据获取到的数据来进行判断、修改、删除等操作,也可以进行追加写入,一般是按行写入
# 这是每行需要写入的数据,当前就设置了一行,如果更多的话使用列表就行
list = [1,2,3,54]
# 获取第一列数据
driver.find_element(By.XPATH,'//*[@id="alloy-simple-text-editor"]').click()
txt = driver.find_element(By.XPATH,'//*[@id="alloy-simple-text-editor"]/p').text
# 判断为空输入数据,否则进入下一行,追加的方式添加数据
if txt =='':
for i in range(len(list)):
driver.find_element(By.XPATH, '//*[@id="alloy-simple-text-editor"]/p').send_keys(list[i])
driver.find_element(By.XPATH,'//*[@id="alloy-simple-text-editor"]').send_keys(Keys.TAB)#进入下一个单元格
driver.find_element(By.XPATH, '//*[@id="alloy-simple-text-editor"]').send_keys(Keys.ENTER) # 进入下一个行
我们都知道插入数据的时候在线表格一般只加载200行,需要更多就自己添加,这里我们就可以使用最下方的添加按钮添加行,当然我们要检测出现添加按钮–也就是到最后一行之后才点击添加
# 行数不够添加行数
try:
driver.find_element(By.XPATH, '//*[text()="添加"]').click()
except:
print('不需要扩展列表')
完整代码
# -*- coding: utf-8 -*-
'''
@Time : 2023/7/12 15:39
@File : 在线文档写入数据.py
'''
'''
实现在线文档的编辑三步走:
1、设置浏览器和代理调用UI自动化操作的时候直接操作已打开的浏览器
2、登录在线文档:在打开的浏览器打开并登录在线文档--此文直接进入需要操作的文档
3、通过键盘操作来实现文档内容的增删改查【登录用户要具备相应的权限】
'''
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
# 文件存储位置打开浏览器
# chrome.exe --remote-debugging-port=9222 --user-data-dir="G:\test"
chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
driver = webdriver.Chrome(options=chrome_options)
driver.get('https://docs.qq.com/sheet/DTEtLSW5NWldEcWJE?tab=gqke19')
print(driver.title)
j = 0 #使用变量来定位列表
# 移动焦点到第一行第一列
driver.find_element(By.XPATH, '//*[@id="alloy-simple-text-editor"]').send_keys(Keys.HOME)
driver.find_element(By.XPATH, '//*[@id="alloy-simple-text-editor"]').send_keys(Keys.CONTROL, Keys.UP)
driver.find_element(By.XPATH, '//*[@id="alloy-simple-text-editor"]').send_keys(Keys.ENTER)
driver.find_element(By.XPATH, '//*[@id="alloy-simple-text-editor"]').send_keys(Keys.TAB)
# 这是每行需要写入的数据,当前就设置了一行,如果更多的话使用列表就行
list = [1,2,3,54]
for i in range(300):#循环行,这里是操作最大行数
driver.find_element(By.XPATH, '//*[@id="alloy-simple-text-editor"]').send_keys(Keys.HOME) #先跳到当前行的第一列
driver.find_element(By.XPATH, '//*[@id="alloy-simple-text-editor"]').click()
s = driver.find_element(By.XPATH,'//*[@class="bar-label"]').text #获取此行的行数
a = int(s[1:])-1 #将A**去除A,留下数字,如果你的排序为行的相差则减去几即可
print(a)
# 获取第一列数据
driver.find_element(By.XPATH,'//*[@id="alloy-simple-text-editor"]').click()
txt = driver.find_element(By.XPATH,'//*[@id="alloy-simple-text-editor"]/p').text
# 判断为空输入数据,否则进入下一行,追加的方式添加数据
if txt =='':
for i in range(len(list)):
driver.find_element(By.XPATH, '//*[@id="alloy-simple-text-editor"]/p').send_keys(list[i])
driver.find_element(By.XPATH,'//*[@id="alloy-simple-text-editor"]').send_keys(Keys.TAB)#进入下一个单元格
driver.find_element(By.XPATH, '//*[@id="alloy-simple-text-editor"]').send_keys(Keys.ENTER) # 进入下一个行
# 行数不够添加行数
try:
driver.find_element(By.XPATH, '//*[text()="添加"]').click()
except:
print('不需要扩展列表')