一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - 用python寫個博客遷移工具

用python寫個博客遷移工具

2021-09-27 00:19Cookieboty Python

這篇文章主要介紹了如何用python寫個博客遷移工具,幫助大家更好的理解和學習使用python,感興趣的朋友可以了解下

前言

最近不少寫博客的朋友跟我反饋博客園的一些文章下架了,這讓我聯想到去年簡書一樣,我之前寫的博客都被下架不可見了。

我最開始接觸的博客網址是 csdn、思否、簡書還有博客園等,但是后期發現,單論博客的生態感覺做的越來越不行,干貨雖然很多,但是垃圾、標題黨很嚴重,我自己也有一些博文被莫名的搬走直接標為原創。

雖然搜問題在上面還是能搜到很多解決方案,但寫作的欲望降低了很多。

綜上我從去年入駐掘金,并以掘金作為博客的主平臺。個人感覺掘金團隊對個人原創的保護是非常好的,同時也在不斷的聽取用戶的建議而去改進。有問題與建議能隨時與掘金的同學討論、溝通,非常方便。

掘金的成長

最開始的時候,掘金也是面試、標題黨滿天飛,但是掘金的運營大佬逐步整頓起來之后,文章的質量有了顯著的提高,并且也不斷推出有利于新手作者、高質量博文的各種活動,鼓勵新人創作、老人分享。

同樣在我入駐掘金之后,作為一個長期用戶,新人作者,也是見證了這段時間以來掘金為了社區活躍,博客質量而做的種種努力。

而最開始使用掘金的 markdown,能吐槽的地方還是很多,但掘金的研發也非常給力,吸納了用戶的建議后,最新升級的 markdown 編輯器也是廣受好評,使用過你就知道真相定律是什么了。

掘金在使用的時候,一直有種特殊的感覺,是一種很純粹的 coding 情懷。并不僅僅只是一個單純的博客平臺,而是一直致力于社區共建、開源項目、掘金翻譯計劃等等的建設,為技術社區打造一片純粹干凈的后花園。

搬家命令行工具

那么作為程序員,手動搬文章顯然是略 low 的

所以寫了一個簡單的 python 腳本,有興趣的同學可以使用它將 cnblogs 上面已有或者創作中的草稿轉移到掘金來。

如果有興趣可以試試改造的更完美點,但不建議泄露自己的隱私信息

環境配置

腳本跑起來需要 python3 環境,所以先安裝一下 python 環境

請在 cookie.json 中補充博客園與掘金的 cookie

使用 python3 main.py -h 查看使用說明

作為程序員應該都了解 cookie 是啥,也知道從哪里撈出來吧

使用方法

用python寫個博客遷移工具

還是上個獲取 cookie 的圖吧,哈哈

請先在 cookie.json 中替換 cookie_cnblogs 與 cookie_juejin 為自己在對應站點上的 cookie

  1. 請自行替換user_nameblog_id
  2. // 下載單篇文章到默認目錄'./cnblogs' 并輸出日志到'./log'
  3. python3 main.py -m download -a https://www.cnblogs.com/{{user_name}}/p/{{blog_id}}.html --enable_log
  4.  
  5. // 下載用戶所有文章到目錄'/Users/cnblogs_t'
  6. python3 main.py -m download -u https://www.cnblogs.com/{{username}} -p /Users/cnblogs_t
  7.  
  8. // 上傳單篇文章到掘金草稿箱
  9. python3 main.py -m upload -f ./cnblogs/{{blog_id}}.html
  10.  
  11. // 上傳'./test_blogs'下所有的html文件到掘金草稿箱
  12. python3 main.py -m upload -d ./test_blogs

main.py

新建 main.py 文件,將下述 python 代碼復制進去

  1. # coding=utf-8
  2. import requests
  3. import os
  4. import argparse
  5. import sys
  6. import json
  7. from lxml import etree
  8. from urllib.parse import urlparse
  9. import logging
  10. reload(sys)
  11. sys.setdefaultencoding('utf-8')
  12.  
  13. parser = argparse.ArgumentParser()
  14. args_dict = {}
  15. list_url_tpl = 'https://www.cnblogs.com/%s/default.html?page=%d'
  16. draft_url = 'https://api.juejin.cn/content_api/v1/article_draft/create_offline'
  17. jj_draft_url_tpl = 'https://juejin.cn/editor/drafts/%s'
  18. cnblog_headers = {}
  19. log_path = './log'
  20.  
  21. def myget(d, k, v):
  22. if d.get(k) is None:
  23. return v
  24. return d.get(k)
  25.  
  26. def init_parser():
  27. parser.description = 'blog move for cnblogs'
  28. parser.add_argument('-m', '--method', type=str, dest='method', help='使用方式: download下載 upload上傳到草稿箱', choices=['upload', 'download'])
  29. parser.add_argument('-p', '--path', type=str, dest='path', help='博客html下載的路徑')
  30. parser.add_argument('-d', '--dir', type=str, dest='rec_dir', help='制定要上傳的博客所在文件夾')
  31. parser.add_argument('-f', '--file', type=str, dest='file', help='指定上傳的博客html')
  32. parser.add_argument('-u', '--url', type=str, dest='url', help='個人主頁地址')
  33. parser.add_argument('-a', '--article', type=str, dest='article_url', help='單篇文章地址')
  34. parser.add_argument('--enable_log', dest='enable_log', help='是否輸出日志到./log', action='store_true')
  35. parser.set_defaults(enable_log=False)
  36.  
  37. def init_log():
  38. root_logger = logging.getLogger()
  39. log_formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(pathname)s:%(lineno)s %(message)s')
  40. console_handler = logging.StreamHandler(sys.stdout)
  41. console_handler.setFormatter(log_formatter)
  42. root_logger.addHandler(console_handler)
  43. if myget(args_dict, 'enable_log', False):
  44. if not os.path.exists(log_path):
  45. os.mkdir(log_path)
  46. file_handler = logging.FileHandler('./log/debug.log')
  47. file_handler.setFormatter(log_formatter)
  48. root_logger.addHandler(file_handler)
  49. root_logger.setLevel(logging.INFO)
  50.  
  51. def download():
  52. cookies = json.load(open('cookie.json'))
  53. headers = {'cookie': cookies.get('cookie_cnblogs', '')}
  54.  
  55. dir_path = myget(args_dict, 'path', './cnblogs')
  56. if dir_path[len(dir_path)-1] == '/':
  57. dir_path = dir_path[:len(dir_path)-1]
  58. if not os.path.exists(dir_path):
  59. os.mkdir(dir_path)
  60.  
  61. article_url = myget(args_dict, 'article_url', '-1')
  62. if article_url != '-1':
  63. logging.info('article_url=%s', article_url)
  64. try:
  65. resp = requests.get(article_url, headers=headers)
  66. if resp.status_code != 200:
  67. logging.error('fail to get blog \'%s\', resp=%s', article_url, resp)
  68. return
  69. tmp_list = article_url.split('/')
  70. blog_id_str = tmp_list[len(tmp_list)-1]
  71. with open(dir_path+'/'+blog_id_str, 'w') as f:
  72. f.write(resp.text)
  73. logging.info('get blog \'%s\' success.', article_url)
  74. except Exception as e:
  75. logging.error('exception raised, fail to get blog \'%s\', exception=%s.', list_url, e)
  76. finally:
  77. return
  78.  
  79. raw_url = args_dict.get('url')
  80. rurl = urlparse(raw_url)
  81. username = (rurl.path.split("/", 1))[1]
  82. page_no = 1
  83. while True:
  84. list_url = list_url_tpl%(username, page_no)
  85. logging.info('list_url = %s', list_url)
  86. try:
  87. resp = requests.get(list_url, headers=headers)
  88. if resp.status_code != 200:
  89. break
  90. except Exception as e:
  91. logging.error('exception raised, fail to get list \'%s\', exception=%s.', list_url, e)
  92. return
  93. html = etree.HTML(resp.text)
  94. blog_list = html.xpath('//div[@class=\'postTitle\']/a/@href')
  95. if len(blog_list) == 0:
  96. break
  97. for blog_url in blog_list:
  98. tmp_list = blog_url.split('/')
  99. blog_id_str = tmp_list[len(tmp_list)-1]
  100. blog_resp = requests.get(blog_url, headers=headers)
  101. if resp.status_code != 200:
  102. logging.error('fail to get blog \'%s\', resp=%s, skip.', blog_url, resp)
  103. continue
  104. with open(dir_path+'/'+blog_id_str, 'w') as f:
  105. f.write(blog_resp.text)
  106. logging.info('get blog \'%s\' success.', blog_url)
  107. page_no += 1
  108.  
  109. def upload_request(headers, content, filename):
  110. body = {
  111. "edit_type": 0,
  112. "origin_type": 2,
  113. "content": content
  114. }
  115. data = json.dumps(body)
  116. try:
  117. resp = requests.post(draft_url, data=data, headers=headers)
  118. if resp.status_code != 200:
  119. logging.error('fail to upload blog, filename=%s, resp=%s', filename, resp)
  120. return
  121. ret = resp.json()
  122. draft_id = ret.get('data', {}).get('draft_id', '-1')
  123. logging.info('upload success, filename=%s, jj_draft_id=%s, jj_draft_url=%s', filename, draft_id, jj_draft_url_tpl%draft_id)
  124. except Exception as e:
  125. logging.error('exception raised, fail to upload blog, filename=%s, exception=%s', filename, e)
  126. return
  127.  
  128. def upload():
  129. cookies = json.load(open('cookie.json'))
  130. headers = {
  131. 'cookie': cookies.get('cookie_juejin', ''),
  132. 'content-type': 'application/json'
  133. }
  134. filename = myget(args_dict, 'file', '-1')
  135. if filename != '-1':
  136. logging.info('upload_filename=%s', filename)
  137. try:
  138. with open(filename, 'r') as f:
  139. content = f.read()
  140. upload_request(headers, content, filename)
  141. return
  142. except Exception as e:
  143. logging.error('exception raised, exception=%s', e)
  144.  
  145. rec_dir = myget(args_dict, 'rec_dir', '-1')
  146. if rec_dir != '-1':
  147. logging.info('upload_dir=%s', filename)
  148. try:
  149. g = os.walk(rec_dir)
  150. for path, dir_list, file_list in g:
  151. for filename in file_list:
  152. if filename.endswith('.html'):
  153. filename = os.path.join(path, filename)
  154. with open(filename, 'r') as f:
  155. content = f.read()
  156. upload_request(headers, content, filename)
  157. except Exception as e:
  158. logging.error('exception raised, exception=%s', e)
  159. return
  160.  
  161. if __name__ == '__main__':
  162. init_parser()
  163. args = parser.parse_args()
  164. args_dict = args.__dict__
  165. init_log()
  166.  
  167. empty_flag = True
  168. for k, v in args_dict.items():
  169. if k != 'enable_log' and v is not None:
  170. empty_flag = False
  171. if empty_flag:
  172. parser.print_help()
  173. exit(0)
  174.  
  175. if args_dict.get('method') == 'upload':
  176. upload()
  177. else:
  178. download()
  179. pass

cookie.json

本地新建 cookie.json 文件,與 main.py 同級

  1. {
  2. "cookie_cnblogs": "請替換為博客園cookie",
  3. "cookie_juejin": "請替換為掘金cookie"
  4. }

github 地址

最后附上 github 地址,里面除了 demo 的 源碼之外也有錄制好的一個視頻,有興趣的同學可以下載使用或者研究研究,腳本有問題或者寫的不好改進的地方也可以互相探討下。有意見也可以隨時留言反饋

以上就是用python寫個博客遷移工具的詳細內容,更多關于python 博客遷移的資料請關注服務器之家其它相關文章!

原文鏈接:https://juejin.cn/post/6942882189277298696

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 顶级欧美做受xxx000大乳 | 精品一久久香蕉国产二月 | 狠狠色综合久久婷婷色天使 | 四虎院影永久在线观看 | 精品视频免费在线观看 | gay18高中生白袜xnxx动漫 | 日韩欧免费一区二区三区 | 福利久草| 91精品国产色综合久久不卡蜜 | 色在线看| 禁忌第一季第3季 | 美女靠逼免费网站 | 男人最爱看的网站 | 91porny丨首页 | 99国产自偷色久 | 国产综合第一页 | 国产在线步兵一区二区三区 | 欧美另类xxx精品人妖 | 韩国禁片在线观看久 | 亚洲天堂免费 | 很黄的网站在线观看 | 久久永久影院免费 | 无码精品一区二区三区免费视频 | 日本中年japanesebear | www.最色| 国产精品久久久久aaaa | 日本bbwbbw| 日本护士xxxx视频免费 | 久久夜色噜噜噜亚洲AV0000 | 九九大香尹人视频免费 | 特级av毛片免费观看 | boobsmilking流奶水野战 | 日韩精品一区二区三区中文在线 | 亚洲国产天堂久久精品网 | 欧美三级做爰全过程 | 美女毛片老太婆bbb80岁 | 娇小异类videos| 激情偷拍网 | 国产香蕉一区二区在线观看 | 亚洲精品国精品久久99热 | 舔比小说 |