在进行Python截取网络报表并发送钉钉群过程中,碰到一些问题,也用到一些工具,在这里做一下简单总结。整个过程归纳如图:

1 版本配置
windows 10
Google Chrome 74.0.3729.131(正式版本) (64 位)
python 3.7.1 selenium:3.141.0
2 打开浏览器
2.1 打开浏览器
1from selenium import webdriver 2from selenium.webdriver.chrome.options import Options 3 4options = Options() 5options.add_argument('log-level=3') # suppress selenium logging to stdout 6options.add_argument('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36') 7 8driver = webdriver.Chrome(options=options)
执行上面的代码,会出现以下错误:
WebDriverException: Message: 'chromedriver' executable needs to be in PATH. Please see https://sites.google.com/a/chromium.org/chromedriver/home
这是因为没有找到 chromedriver.exe 可执行文件,两种解决方案如下:
1.找到 chromedriver.exe 的路径,并将其作为参数添加(注意,不是 chrome.exe 的路径)
driver = webdriver.Chrome(executable_path='/path/to/chromedriver.exe', options=options)
2.安装 webdriver_manager 模块,并设置参数
1from webdriver_manager.chrome import ChromeDriverManager 2 3driver = webdriver.Chrome(ChromeDriverManager().install(), options=options)
3.浏览器有时打不开,可能是由于 Google Chrome 版本自动更新之后,chromedriver.exe 版本不再对其支持,因此需要及时更新版本,或者停止 Google Chrome 自动更新。
2.2 浏览器无界面模式最大化(headless)
1options.add_argument('--headless') 2 3driver = webdriver.Chrome(ChromeDriverManager().install(), options = options)
在浏览器使用 headless 模式时,如果调整窗口大小,需要使用如下方法:
1driver.set_window_position(0, 0) 2driver.set_window_size(1366, 768) # 分辨率为 1366 X 768
如果浏览器不使用 headless 模式, 则也可以用如下两种方法,下面两种方法在 headless 模式下不会执行(原因不确定):
1options.add_argument('--start-maximized') 2 3# 或者 4driver.maximize_window()
3 查找节点
Selenium 提供了一系列查找节点的方法,还可以查找单个节点和多个节点。具体语法为 find_element_by_...(),如果有多个节点,用这种方法查找,只能得到第一个节点,这时候可以使用 find_elements_by_...() 方法。

1from selenium import webdriver 2 3driver = webdriver.Chrome() # 假设可以正常打开浏览器 4driver.get('https://www.taobao.com') 5 6# 根据 id 查找 7driver.find_element_by_id('q') 8 9# 根据 CSS 选择器查找 10driver.find_element_by_css_selector('#q') 11 12# 根据 XPath 查找 13driver.find_element_by_xpath('//*[@id="q"]') 14 15# 两个类 ng-star-inserted 和 caption 16driver.find_elements_by_css_selector("div.ng-star-inserted.caption") 17 18# 通过两级类名查找 19driver.find_elements_by_xpath("//div[contains(@class, 'chart-title-wrap')]/ancestor::div[contains(@class,'smartchart-box')]") 20 21# 通过两个类查找 22driver.find_elements_by_xpath("//input[@name='login' and @type='submit']") 23 24# 其它方法 25find_element_by_name() 26find_element_by_link_text() 27find_element_by_partial_link_text() 28find_element_by_tag_name() 29find_element_by_class_name()
4 阿里云对象存储(Object Storage Service,简称 OSS)
我在报表制作过程中,主要是进行网页截图和本地代码作图,并将它们保存到本地,然后将这些图像上传到阿里云对象存储空间获取图像外链,最后将外链嵌入到要发送钉钉的 Markdown 消息中。
注:直接将本地图片链接嵌入到 Markdown 消息中未取得成功,不知道有没有解决方法。
使用 OSS 管理控制台来完成 OSS 基本操作步骤如下:

还可以通过使用图形化管理工具 ossbrowser、命令行管理工具 ossutil,和 API/SDK 的方式来完成基本操作。
几个概念
-
存储空间(Bucket):存储空间是您用于存储对象(Object)的容器,所有的对象都必须隶属于某个存储空间
-
对象/文件(Object):对象是 OSS 存储数据的基本单元,也被称为 OSS 的文件。对象由元信息(Object Meta)、用户数据(Data)和文件名(Key)组成。对象由存储空间内部唯一的 Key 来标识。
-
访问密钥(AccessKey):AccessKey,简称 AK,指的是访问身份验证中用到的 AccessKeyId 和 AccessKeySecret。
下面以 Python SDK 的方式来完成整个过程:
创建存储空间
1import oss2 2 3# 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维 4auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>') 5 6# Endpoint以杭州为例,其它Region请按实际情况填写。 7bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>') 8 9# 设置存储空间为私有读写权限。 10bucket.create_bucket(oss2.models.BUCKET_ACL_PRIVATE)
上传文件
1# <yourObjectName>为文件上传到bucket后的名称 2# <yourLocalFile>由本地文件路径加文件名包括后缀组成,例如/users/local/myfile.txt 3bucket.put_object_from_file('<yourObjectName>', '<yourLocalFile>')
下载文件
1# <yourLocalFile>由本地文件路径加文件名包括后缀组成,例如/users/local/myfile.txt 2bucket.get_object_to_file('<yourObjectName>', '<yourLocalFile>')
列举文件
1from itertools import islice 2 3# oss2.ObjectIteratorr用于遍历文件,制定存储空间下的10个文件 4for b in islice(oss2.ObjectIterator(bucket), 10): 5 print(b.key)
删除文件
1# <yourObjectNmae> 为存储空间上的制定文件 2bucket.delete_object('<yourObjectName>')
上传本地图像至存储空间,并获得其外链
fig_url = bucket.sign_url('GET', os.path.basename(p), 180) # 生成图片外链,180s后取消
5 钉钉群发送报表
首先在钉钉 “群设置“ 中点击 “群机器人”,然后点击 “添加机器人”,点击 “自定义”,出现如下页面,其中 webhook 就是后面要用到推送报表至钉钉的链接。

下面以推送 markdown 类型消息为例,列出解决方法。
5.1 使用 Python 模块 requests 发送
1headers = {"Content-Type": "application/json"} 2 3# 消息类型和数据格式参照钉钉开发文档 4data = { 5 "msgtype": "markdown", 6 "markdown": { 7 "title": "首屏会话透出的展示内容", 8 "text": "# 这是支持markdown的文本 \n## 标题2 \n* 列表1 \n " 9 } 10} 11 12r = requests.post(webhook, data=json.dumps(data), headers=headers)
5.2 使用 Python 模块 DingtalkChatbot 发送
1import dingtalkchatbot.chatbot as cb 2 3robot = cb.DingtalkChatbot(webhook) 4robot.send_markdown(title='首屏会话透出的展示内容', 5text="# 这是支持markdown的文本 \n## 标题2 \n* 列表1 \n ")
6 定时发送消息
windows 10 找到 任务计划程序,然后选择创建基本任务或者创建任务。

设置自己的选项,主要是红色方框里面的内容一定要填写,这里启动的是 .bat 文件。

下面是 .bat 文件的内容,由于 timeReport.py 文件路径和 .bat 文件路径一致,因此不需要再加上 timeReport.py 文件路径。

在运行上面的定时任务时,会自动跳出命令行窗口,这样有可能会影响我们的工作,也有可能我们不小心影响到定时任务的运行。因此,如果能隐藏命令行窗口的话,那绝对是很妙的。设置如下:

后面我们在 任务计划程序 中运行 timeReport.vbs 文件就可以了,当然也要注意路径的设置。