在進行Python截取網絡報表並發送釘釘群過程中,碰到一些問題,也用到一些工具,在這里做一下簡單總結。整個過程歸納如圖:
1 版本配置
windows 10
Google Chrome 74.0.3729.131(正式版本) (64 位)
python 3.7.1
selenium:3.141.0
2 打開瀏覽器
2.1 打開瀏覽器
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument('log-level=3') # suppress selenium logging to stdout
options.add_argument('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36')
driver = 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 模塊,並設置參數
from webdriver_manager.chrome import ChromeDriverManager
driver = webdriver.Chrome(ChromeDriverManager().install(), options=options)
3.瀏覽器有時打不開,可能是由於 Google Chrome 版本自動更新之后,chromedriver.exe 版本不再對其支持,因此需要及時更新版本,或者停止 Google Chrome 自動更新。
2.2 瀏覽器無界面模式最大化(headless)
options.add_argument('--headless')
driver = webdriver.Chrome(ChromeDriverManager().install(), options = options)
在瀏覽器使用 headless 模式時,如果調整窗口大小,需要使用如下方法:
driver.set_window_position(0, 0)
driver.set_window_size(1366, 768) # 分辨率為 1366 X 768
如果瀏覽器不使用 headless 模式, 則也可以用如下兩種方法,下面兩種方法在 headless 模式下不會執行(原因不確定):
options.add_argument('--start-maximized')
# 或者
driver.maximize_window()
3 查找節點
Selenium 提供了一系列查找節點的方法,還可以查找單個節點和多個節點。具體語法為 find_element_by_...(),如果有多個節點,用這種方法查找,只能得到第一個節點,這時候可以使用 find_elements_by_...() 方法。
from selenium import webdriver
driver = webdriver.Chrome() # 假設可以正常打開瀏覽器
driver.get('https://www.taobao.com')
# 根據 id 查找
driver.find_element_by_id('q')
# 根據 CSS 選擇器查找
driver.find_element_by_css_selector('#q')
# 根據 XPath 查找
driver.find_element_by_xpath('//*[@id="q"]')
# 兩個類 ng-star-inserted 和 caption
driver.find_elements_by_css_selector("div.ng-star-inserted.caption")
# 通過兩級類名查找
driver.find_elements_by_xpath("//div[contains(@class, 'chart-title-wrap')]/ancestor::div[contains(@class,'smartchart-box')]")
# 通過兩個類查找
driver.find_elements_by_xpath("//input[@name='login' and @type='submit']")
# 其它方法
find_element_by_name()
find_element_by_link_text()
find_element_by_partial_link_text()
find_element_by_tag_name()
find_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 的方式來完成整個過程:
創建存儲空間
import oss2
# 阿里雲主賬號AccessKey擁有所有API的訪問權限,風險很高。強烈建議您創建並使用RAM賬號進行API訪問或日常運維
auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
# Endpoint以杭州為例,其它Region請按實際情況填寫。
bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
# 設置存儲空間為私有讀寫權限。
bucket.create_bucket(oss2.models.BUCKET_ACL_PRIVATE)
上傳文件
# <yourObjectName>為文件上傳到bucket后的名稱
# <yourLocalFile>由本地文件路徑加文件名包括后綴組成,例如/users/local/myfile.txt
bucket.put_object_from_file('<yourObjectName>', '<yourLocalFile>')
下載文件
# <yourLocalFile>由本地文件路徑加文件名包括后綴組成,例如/users/local/myfile.txt
bucket.get_object_to_file('<yourObjectName>', '<yourLocalFile>')
列舉文件
from itertools import islice
# oss2.ObjectIteratorr用於遍歷文件,制定存儲空間下的10個文件
for b in islice(oss2.ObjectIterator(bucket), 10):
print(b.key)
刪除文件
# <yourObjectNmae> 為存儲空間上的制定文件
bucket.delete_object('<yourObjectName>')
上傳本地圖像至存儲空間,並獲得其外鏈
fig_url = bucket.sign_url('GET', os.path.basename(p), 180) # 生成圖片外鏈,180s后取消
5 釘釘群發送報表
首先在釘釘 “群設置“ 中點擊 “群機器人”,然后點擊 “添加機器人”,點擊 “自定義”,出現如下頁面,其中 webhook 就是后面要用到推送報表至釘釘的鏈接。
下面以推送 markdown 類型消息為例,列出解決方法。
5.1 使用 Python 模塊 requests 發送
headers = {"Content-Type": "application/json"}
# 消息類型和數據格式參照釘釘開發文檔
data = {
"msgtype": "markdown",
"markdown": {
"title": "首屏會話透出的展示內容",
"text": "# 這是支持markdown的文本 \n## 標題2 \n* 列表1 \n "
}
}
r = requests.post(webhook, data=json.dumps(data), headers=headers)
5.2 使用 Python 模塊 DingtalkChatbot 發送
import dingtalkchatbot.chatbot as cb
robot = cb.DingtalkChatbot(webhook)
robot.send_markdown(title='首屏會話透出的展示內容',
text="# 這是支持markdown的文本 \n## 標題2 \n* 列表1 \n ")
6 定時發送消息
windows 10 找到 任務計划程序,然后選擇創建基本任務或者創建任務。
設置自己的選項,主要是紅色方框里面的內容一定要填寫,這里啟動的是 .bat 文件。
下面是 .bat 文件的內容,由於 timeReport.py 文件路徑和 .bat 文件路徑一致,因此不需要再加上 timeReport.py 文件路徑。
在運行上面的定時任務時,會自動跳出命令行窗口,這樣有可能會影響我們的工作,也有可能我們不小心影響到定時任務的運行。因此,如果能隱藏命令行窗口的話,那絕對是很妙的。設置如下:
后面我們在 任務計划程序 中運行 timeReport.vbs 文件就可以了,當然也要注意路徑的設置。