寫在開始
這是本系列的第三篇文章,主要介紹如何用Python
+Selenium
自動發佈CSDN博客,一些必要的條件在之前的文章裏面已經提到過,這裏也不再重複。
使用說明
同樣的,還是需要先分析下CSDN寫博客的界面(記得設置默認編輯器爲Markdown)。
write-blog-csdn
post-blog-csdn
從上面兩張圖可以看到,在CSDN平臺寫一篇博客,依次需要填入標題和內容信息。如果是發佈博客操作,還需要選擇文章類型、博客分類、個人分類(可選)以及填寫文章標籤(可選)等信息。
我們結合auto.md
的內容進行分析,標題定義在title
處;正文內容通過匹配-->\n
獲取;剩下文章類型、博客分類、文章標籤和個人分類,按規則已經提前定義在註釋中,分別對應csdn_article_category
、csdn_blog_category
、self_tags
和self_category
。
代碼說明
main.py:程序入口類,主要負責正則匹配解析Markdown
和調用post
發佈文章
import re import csdn import linecache class Main(object): # init def __init__(self, file): self.title = '' self.content = '' self.category = '' self.tags = '' # OsChina的系統分類, 設個默認值 self.osChina_sys_category = '編程語言' # CSDN的文章分類, 設個默認值 self.csdn_article_category = '原創' # CSDN的博客分類, 設個默認值 self.csdn_blog_category = '後端' self.read_file(file) # 讀取MD中的title, content, self_category, self_tags, osChina_sys_category, csdn_article_category, csdn_blog_category def read_file(self, markdown_file): self.title = linecache.getline(markdown_file, 2).split('title: ')[1].strip('\n') with open(markdown_file, 'r', encoding='UTF-8') as f: self.content = f.read().split('-->\n')[1] # 重置文件指針偏移量 f.seek(0) for line in f.readlines(): if re.search('self_category: ', line) is not None: self.category = line.split('self_category: ')[1].strip('\n') elif re.search('self_tags: ', line) is not None: self.tags = line.split('self_tags: ')[1].strip('\n') elif re.search('osChina_sys_category: ', line) is not None: self.osChina_sys_category = line.split('osChina_sys_category: ')[1].strip('\n') elif re.search('csdn_article_category: ', line) is not None: self.csdn_article_category = line.split('csdn_article_category: ')[1].strip('\n') elif re.search('csdn_blog_category: ', line) is not None: self.csdn_blog_category = line.split('csdn_blog_category: ')[1].strip('\n') if __name__ == '__main__': md_file = 'auto.md' print("Markdown File is ", md_file) timeout = 10 main = Main(md_file) # CSDN csdn = csdn.CSDN() csdn.post(main, timeout)
authorize.py:目前僅實現了用qq進行授權登錄的方法
from selenium.webdriver.support.wait import WebDriverWait # QQ授權登錄, 使用前提是QQ客戶端在線 def qq(driver, timeout): # 切換到最新打開的窗口 window_handles = driver.window_handles driver.switch_to.window(window_handles[-1]) print('qq authorize title is ', driver.title) # 切換iframe iframe = WebDriverWait(driver, timeout).until(lambda d: d.find_element_by_id('ptlogin_iframe')) driver.switch_to.frame(iframe) # 點擊頭像進行授權登錄 login = WebDriverWait(driver, timeout).until(lambda d: d.find_element_by_xpath('//*[@id="qlogin_list"]/a[1]')) login.click()
csdn.py:這個是CSDN自動寫(發)博客的核心類
import time import authorize from selenium import webdriver from selenium.webdriver.support.ui import Select from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.common.action_chains import ActionChains # CSDN class CSDN(object): @staticmethod def post(main, timeout, self_timeout=5): # 1.賬號密碼 account = 'xxx' password = 'xxx' # 2.跳轉登陸 login = 'https://passport.csdn.net/account/login' driver = webdriver.Chrome() driver.get(login) # 3.窗口最大化 driver.maximize_window() # 4.使用賬號密碼登陸 # login_by_account = WebDriverWait(driver, timeout).until( # lambda d: d.find_element_by_xpath('/html/body/div[3]/div/div/div[2]/div/h3/a')) # login_by_account.click() # time.sleep(self_timeout) # driver.find_element_by_id('username').send_keys(account) # driver.find_element_by_id('password').send_keys(password) # driver.find_element_by_xpath('//*[@id="fm1"]/input[8]').click() # 4.使用QQ授權登錄 driver.find_element_by_id('qqAuthorizationUrl').click() driver.close() authorize.qq(driver, timeout) # 5.點擊"寫博客" write_blog = WebDriverWait(driver, timeout).until( lambda d: d.find_element_by_xpath('/html/body/div[1]/div/div/ul/li[3]/a')) write_blog.click() driver.close() window_handles = driver.window_handles driver.switch_to.window(window_handles[-1]) # 6.點擊"開始寫作" start = WebDriverWait(driver, timeout).until( lambda d: d.find_element_by_xpath('//*[@id="btnStart"]')) start.click() # 7.填寫標題, 內容 time.sleep(self_timeout) title = driver.find_element_by_xpath('//*[@id="txtTitle"]') title.clear() title.send_keys(main.title) # PS:下面這行代碼很重要,卡了好久才解決┭┮﹏┭┮,不信可以試試註釋掉這句 ActionChains(driver).click(title).perform() content = driver.find_element_by_xpath('//*[@id="wmd-input"]/div[1]') content.clear() content.send_keys(main.content) # 8.保存草稿 # driver.find_element_by_xpath('//*[@id="editorBox"]/div[2]/div/button[2]').click() # 8.發佈文章 driver.find_element_by_xpath('//*[@id="editorBox"]/div[2]/div/button[1]').click() # 9.若第8步選擇"發佈文章", 往下需依次填寫標籤,個人分類,文章類型,博客分類 tags = main.tags.split(',') add_tag = WebDriverWait(driver, timeout).until(lambda d: d.find_element_by_id('addTag')) for i, tag in enumerate(tags): add_tag.click() tag_input = WebDriverWait(driver, timeout).until( lambda d: d.find_element_by_xpath('//*[@id="tagBox"]/div[' + str(i + 1) + ']/span')) tag_input.send_keys(tag) classify = driver.find_elements_by_class_name('form-check-label') for c in classify: html = c.get_attribute('innerHTML') if main.category in html: c.click() select = Select(driver.find_element_by_id('selType')) select.select_by_visible_text(main.csdn_article_category) select = Select(driver.find_element_by_id('radChl')) select.select_by_visible_text(main.csdn_blog_category) # 10.保存草稿 driver.find_element_by_xpath('//*[@id="meditor_box"]/div[3]/div/div[6]/input[2]').click() # 10.發佈文章 # driver.find_element_by_xpath('//*[@id="meditor_box"]/div[3]/div/div[6]/input[3]').click() time.sleep(self_timeout)
CSDN支持賬號密碼登錄,也可以用qq授權的方式,後期只需要擴展authorize.py
的功能,就可以支持更多的第三方平臺進行授權登錄。
運行效果
還是來看看運行效果圖吧,這裏僅測試保存草稿。
auto-post-csdn
寫在最後
在CSDN平臺自動寫文章的流程大概也就這樣,同樣這不是唯一的辦法,也不敢保證程序可以一直正常運行下去。總而言之,這個花的時間是最多,因爲一直卡在了某一點上,不過還好最後還是解決了。本系列還有最後一篇,將介紹如何結合bat腳本在多個平臺同時發佈文章,以及對系列做一個簡單的總結,敬請期待。