用python写个博客迁移工具

前言

最近不少写博客的朋友跟我反馈博客园的一些文章下架了,这让我联想到去年简书一样,我之前写的博客都被下架不可见了。

我最开始接触的博客网址是 csdn、思否、简书还有博客园等,但是后期发现,单论博客的生态感觉做的越来越不行,干货虽然很多,但是垃圾、标题党很严重,我自己也有一些博文被莫名的搬走直接标为原创。

虽然搜问题在上面还是能搜到很多解决方案,但写作的欲望降低了很多。

综上我从去年入驻掘金,并以掘金作为博客的主平台。个人感觉掘金团队对个人原创的保护是非常好的,同时也在不断的听取用户的建议而去改进。有问题与建议能随时与掘金的同学讨论、沟通,非常方便。

掘金的成长

最开始的时候,掘金也是面试、标题党满天飞,但是掘金的运营大佬逐步整顿起来之后,文章的质量有了显著的提高,并且也不断推出有利于新手作者、高质量博文的各种活动,鼓励新人创作、老人分享。

同样在我入驻掘金之后,作为一个长期用户,新人作者,也是见证了这段时间以来掘金为了社区活跃,博客质量而做的种种努力。

而最开始使用掘金的 markdown,能吐槽的地方还是很多,但掘金的研发也非常给力,吸纳了用户的建议后,最新升级的 markdown 编辑器也是广受好评,使用过你就知道真相定律是什么了。

掘金在使用的时候,一直有种特殊的感觉,是一种很纯粹的 coding 情怀。并不仅仅只是一个单纯的博客平台,而是一直致力于社区共建、开源项目、掘金翻译计划等等的建设,为技术社区打造一片纯粹干净的后花园。

搬家命令行工具

那么作为程序员,手动搬文章显然是略 low 的

所以写了一个简单的 python 脚本,有兴趣的同学可以使用它将 cnblogs 上面已有或者创作中的草稿转移到掘金来。

如果有兴趣可以试试改造的更完美点,但不建议泄露自己的隐私信息

环境配置

脚本跑起来需要 python3 环境,所以先安装一下 python 环境

请在 cookie.json 中补充博客园与掘金的 cookie

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

作为程序员应该都了解 cookie 是啥,也知道从哪里捞出来吧

使用方法

还是上个获取 cookie 的图吧,哈哈

请先在 cookie.json 中替换 cookie_cnblogs 与 cookie_juejin 为自己在对应站点上的 cookie

请自行替换user_name与blog_id
// 下载单篇文章到默认目录'./cnblogs' 并输出日志到'./log'
python3 main.py -m download -a https://www.cnblogs.com/{{user_name}}/p/{{blog_id}}.html --enable_log 

// 下载用户所有文章到目录'/Users/cnblogs_t'
python3 main.py -m download -u https://www.cnblogs.com/{{username}} -p /Users/cnblogs_t

// 上传单篇文章到掘金草稿箱
python3 main.py -m upload -f ./cnblogs/{{blog_id}}.html

// 上传'./test_blogs'下所有的html文件到掘金草稿箱
python3 main.py -m upload -d ./test_blogs

main.py

新建 main.py 文件,将下述 python 代码复制进去

# coding=utf-8
import requests
import os
import argparse
import sys
import json
from lxml import etree
from urllib.parse import urlparse
import logging
reload(sys)
sys.setdefaultencoding('utf-8')

parser = argparse.ArgumentParser()
args_dict = {}
list_url_tpl = 'https://www.cnblogs.com/%s/default.html?page=%d'
draft_url = 'https://api.juejin.cn/content_api/v1/article_draft/create_offline'
jj_draft_url_tpl = 'https://juejin.cn/editor/drafts/%s'
cnblog_headers = {}
log_path = './log'

def myget(d, k, v):
 if d.get(k) is None:
  return v
 return d.get(k)

def init_parser():
 parser.description = 'blog move for cnblogs'
 parser.add_argument('-m', '--method', type=str, dest='method', help='使用方式: download下载 upload上传到草稿箱', choices=['upload', 'download'])
 parser.add_argument('-p', '--path', type=str, dest='path', help='博客html下载的路径')
 parser.add_argument('-d', '--dir', type=str, dest='rec_dir', help='制定要上传的博客所在文件夹')
 parser.add_argument('-f', '--file', type=str, dest='file', help='指定上传的博客html')
 parser.add_argument('-u', '--url', type=str, dest='url', help='个人主页地址')
 parser.add_argument('-a', '--article', type=str, dest='article_url', help='单篇文章地址')
 parser.add_argument('--enable_log', dest='enable_log', help='是否输出日志到./log', action='store_true')
 parser.set_defaults(enable_log=False)

def init_log():
 root_logger = logging.getLogger()
 log_formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(pathname)s:%(lineno)s %(message)s')
 console_handler = logging.StreamHandler(sys.stdout)
 console_handler.setFormatter(log_formatter)
 root_logger.addHandler(console_handler)
 if myget(args_dict, 'enable_log', False):
  if not os.path.exists(log_path):
   os.mkdir(log_path)
  file_handler = logging.FileHandler('./log/debug.log')
  file_handler.setFormatter(log_formatter)
  root_logger.addHandler(file_handler)
 root_logger.setLevel(logging.INFO)

def download():
 cookies = json.load(open('cookie.json'))
 headers = {'cookie': cookies.get('cookie_cnblogs', '')}

 dir_path = myget(args_dict, 'path', './cnblogs')
 if dir_path[len(dir_path)-1] == '/':
  dir_path = dir_path[:len(dir_path)-1]
 if not os.path.exists(dir_path):
  os.mkdir(dir_path)

 article_url = myget(args_dict, 'article_url', '-1')
 if article_url != '-1':
  logging.info('article_url=%s', article_url)
  try:
   resp = requests.get(article_url, headers=headers)
   if resp.status_code != 200:
    logging.error('fail to get blog \'%s\', resp=%s', article_url, resp)
    return
   tmp_list = article_url.split('/')
   blog_id_str = tmp_list[len(tmp_list)-1]
   with open(dir_path+'/'+blog_id_str, 'w') as f:
    f.write(resp.text)
   logging.info('get blog \'%s\' success.', article_url)
  except Exception as e:
   logging.error('exception raised, fail to get blog \'%s\', exception=%s.', list_url, e)
  finally:
   return

 raw_url = args_dict.get('url')
 rurl = urlparse(raw_url)
 username = (rurl.path.split("/", 1))[1]
 page_no = 1
 while True:
  list_url = list_url_tpl%(username, page_no)
  logging.info('list_url = %s', list_url)
  try:
   resp = requests.get(list_url, headers=headers)
   if resp.status_code != 200:
    break
  except Exception as e:
   logging.error('exception raised, fail to get list \'%s\', exception=%s.', list_url, e)
   return
  html = etree.HTML(resp.text)
  blog_list = html.xpath('//div[@class=\'postTitle\']/a/@href')
  if len(blog_list) == 0:
   break
  for blog_url in blog_list:
   tmp_list = blog_url.split('/')
   blog_id_str = tmp_list[len(tmp_list)-1]
   blog_resp = requests.get(blog_url, headers=headers)
   if resp.status_code != 200:
    logging.error('fail to get blog \'%s\', resp=%s, skip.', blog_url, resp)
    continue
   with open(dir_path+'/'+blog_id_str, 'w') as f:
    f.write(blog_resp.text)
   logging.info('get blog \'%s\' success.', blog_url)
  page_no += 1

def upload_request(headers, content, filename):
 body = {
  "edit_type": 0,
  "origin_type": 2,
  "content": content
 }
 data = json.dumps(body)
 try:
  resp = requests.post(draft_url, data=data, headers=headers)
  if resp.status_code != 200:
   logging.error('fail to upload blog, filename=%s, resp=%s', filename, resp)
   return
  ret = resp.json()
  draft_id = ret.get('data', {}).get('draft_id', '-1')
  logging.info('upload success, filename=%s, jj_draft_id=%s, jj_draft_url=%s', filename, draft_id, jj_draft_url_tpl%draft_id)
 except Exception as e:
  logging.error('exception raised, fail to upload blog, filename=%s, exception=%s', filename, e)
  return

def upload():
 cookies = json.load(open('cookie.json'))
 headers = {
  'cookie': cookies.get('cookie_juejin', ''),
  'content-type': 'application/json'
 }
 filename = myget(args_dict, 'file', '-1')
 if filename != '-1':
  logging.info('upload_filename=%s', filename)
  try:
   with open(filename, 'r') as f:
    content = f.read()
    upload_request(headers, content, filename)
   return
  except Exception as e:
   logging.error('exception raised, exception=%s', e)

 rec_dir = myget(args_dict, 'rec_dir', '-1')
 if rec_dir != '-1':
  logging.info('upload_dir=%s', filename)
  try:
   g = os.walk(rec_dir)
   for path, dir_list, file_list in g:
    for filename in file_list:
     if filename.endswith('.html'):
      filename = os.path.join(path, filename)
      with open(filename, 'r') as f:
       content = f.read()
       upload_request(headers, content, filename)
  except Exception as e:
   logging.error('exception raised, exception=%s', e)
  return

if __name__ == '__main__':
 init_parser()
 args = parser.parse_args()
 args_dict = args.__dict__
 init_log()

 empty_flag = True
 for k, v in args_dict.items():
  if k != 'enable_log' and v is not None:
   empty_flag = False
 if empty_flag:
  parser.print_help()
  exit(0)

 if args_dict.get('method') == 'upload':
  upload()
 else:
  download()
 pass

cookie.json

本地新建 cookie.json 文件,与 main.py 同级

{
 "cookie_cnblogs": "请替换为博客园cookie",
 "cookie_juejin": "请替换为掘金cookie"
}

github 地址

最后附上 github 地址,里面除了 demo 的 源码之外也有录制好的一个视频,有兴趣的同学可以下载使用或者研究研究,脚本有问题或者写的不好改进的地方也可以互相探讨下。有意见也可以随时留言反馈

以上就是用python写个博客迁移工具的详细内容,更多关于python 博客迁移的资料请关注我们其它相关文章!

(0)

相关推荐

  • pycharm使用正则表达式批量添加print括号完美从python2迁移到python3

    网络下载的python代码,版本参差,从python2.x迁移python3.x的过程中,存在print语法问题,即python2.x中print无括号,python3.x中print有括号. 逐行添加括号未免效率过低,因此,可使用正则表达式的方法,提供解决方法. 1.在pycharm编译器中,Ctrl+R调出替换功能框,勾选"Regex",选择正则表达式替换方法 2. 从上到下,第一个搜索框输入 print (.*?);?$ 正则表达式 含义 . 匹配任意字符,除了换行符,当re.D

  • python django生成迁移文件的实例

    关于Django生成迁移文件,我是在虚拟机上完成的 1.创建虚拟环境: 在终端上输入创建python3的虚拟环境 mkvirtualenv -p python3 虚拟环境的名字 在虚拟环境中安装好django1.8.4和pymysql 2.创建项目 创建项目语句:django-admin startproject 项目名字 创建APP:python manage.py startapp 模块名字 这时,我们要在pycham中打开这个项目,并在项目名的同名文件夹下的settings.py的INST

  • 如何把外网python虚拟环境迁移到内网

    外网python2.7 虚拟环境中安装了 flask 模块,期望在内网使用,如何迁移外网的虚拟环境到内网呢? 1 进入外网python虚拟环境 [root@localhost 20200422]# source python27_virtual_env/bin/activate (python27_virtual_env) [root@localhost 20200422]# 2 导入虚拟环境中已安装包的信息到requirements.txt 文件中 (python27_virtual_env)

  • Python依赖包迁移到断网环境操作

    场景:由于自己的电脑A性能不足,需要转移到一台高性能的主机B上运行python程序,但是该主机不能连接互联网. 问题:在个人电脑A上建立了一个虚拟环境,安装了依赖包并且调试程序使其能运行.但是将虚拟环境所在文件夹复制粘贴到主机B上时,无法运行. 环境:Windows.Python3.6 解决办法: 1.主机A(虚拟环境激活)pip freeze >requirements.txt 将虚拟环境中安装的Python依赖包记录到文件requirements.txt中. 2.主机A(虚拟环境激活)pip

  • 如何将你的应用迁移到Python3的三个步骤

    Python 2.x 很快就要 失去官方支持 了,尽管如此,从 Python 2 迁移到 Python 3 却并没有想象中那么难.我在上周用了一个晚上的时间将一个 3D 渲染器的前端代码及其对应的 PySide 迁移到 Python 3,回想起来,尽管在迁移过程中无可避免地会遇到一些牵一发而动全身的修改,但整个过程相比起痛苦的重构来说简直是出奇地简单. 每个人都别无选择地有各种必须迁移的原因:或许是觉得已经拖延太久了,或许是依赖了某个在 Python 2 下不再维护的模块.但如果你仅仅是想通过做

  • 详解Python3迁移接口变化采坑记

    1.除法相关 在python3之前, print 13/4 #result=3 然而在这之后,却变了! print(13 / 4) #result=3.25 "/"符号运算后是正常的运算结果,那么,我们要想只取整数部分怎么办呢?原来在python3之后,"//"有这个功能: print(13 // 4) #result=3.25 是不是感到很奇怪呢?下面我们再来看一组结果: print(4 / 13) # result=0.3076923076923077 prin

  • python实现数据库跨服务器迁移

    基于Python2.7的版本环境,Python实现的数据库跨服务器(跨库)迁移, 每以5000条一查询一提交,代码中可以自行更改每次查询提交数目. # -*- coding: utf-8 -*- import MySQLdb import time import warnings warnings.filterwarnings("ignore") class ConnectMysql(object): def __init__(self): # 这里设置分页查询, 每页查询多少数据 s

  • python 动态迁移solr数据过程解析

    前言 上项目的时候,遇见一次需求,需要把在线的 其中一个 collection 里面的数据迁移到另外一个collection下,于是就百度了看到好多文章,其中大部分都是使用导入的方法,没有找到在线数据的迁移方法.于是写了python脚本,分享出来. 思路: collection数据量比较大,所以一次性操作所有数据太大,于是分段执行操作. 先分段 按1000条数据量进行查询,处理成json数据 把处理后的json数据 发送到目的collection上即可 实现: 一.使用http的接口先进行查询

  • Python依赖包整体迁移方法详解

    1.新建site-packages目录,进入到site-packages目录下: 2.在site-packages目录下执行pip freeze >requirements.txt: 3.查看requirements.txt,可以看到当前机器的python所有依赖包已生成列表 ​ 4.在当前目录下执行pip download -rrequirements.txt,可以看到pip开始下载依赖包列表中的所有依赖包 ​ 5.等待下载完成后,可以看到当前目录下已经有了依赖包文件 ​ 6.将site-pa

  • 使用python和Django完成博客数据库的迁移方法

    上一讲完成了基本博客的配置和项目工程的生成.这次开始将博客一些基本的操作主要是数据库方面学习. 1.设计博客数据库表结构 博客最主要的功能就是展示我们写的文章,它需要从某个地方获取博客文章数据才能把文章展示出来,通常来说这个地方就是数据库.我们把写好的文章永久地保存在数据库里,当用户访问我们的博客时,Django 就去数据库里把这些数据取出来展现给用户. 博客的文章应该含有标题.正文.作者.发表时间等数据.一个更加现代化的博客文章还希望它有分类.标签.评论等.为了更好地存储这些数据,我们需要合理

  • python虚拟环境迁移方法

    python虚拟环境迁移: 注意事项:直接将虚拟环境复制到另一台机器,直接执行是会有问题的. 那么可以采用以下办法: 思路:将机器1虚拟环境下的包信息打包,之后到机器2上进行安装: (有两种情况要考虑,机器2无网络和有网络情况(无网,证明无法在线安装包,那么就需要在机器1将包,整体打包成.whl,然后到机器2安装:有网情况,只需将导信息导出,然后到机器2上在线安装)) 机器1: 1.首先在cmd命令行下,激活虚拟环境 2.在项目目录下新建一个whls文件夹(用来存储我们依赖包)然后在虚拟环境cm

随机推荐