本文是博客搭建系列文章第七篇,其他文章链接:
- 从零开始免费搭建自己的博客(一)——本地搭建 Hexo 框架
- 从零开始免费搭建自己的博客(二)——基于 GitHub pages 建站
- 从零开始免费搭建自己的博客(三)——基于 Gitee pages 建站
- 从零开始免费搭建自己的博客(四)——编写Markdown文章利器 Typora
- 从零开始免费搭建自己的博客(五)——Typora + PicGo + GitHub/Gitee图床
- 从零开始免费搭建自己的博客(六)——三个站点一键发布博客
- 从零开始免费搭建自己的博客(七)——迁移 CSDN 博客到个人博客站点
- 从零开始免费搭建自己的博客(八)——博客网站个性化设置及优化
CSDN 没有提供文章导出功能,只有导入功能,我们想把自己以前写的文章迁移到其他平台或者自己的博客网站,还得自己想办法爬取下来。可是那是我写的文章啊,竟然不能想拿就拿回来。。。
我看到需多人的实现思路,是使用文章界面点击编辑按钮的接口,获取自己之前的文章 Markdown 源码。这样还得先登录自己的账号,而且前提是之前文章是用 Markdown 编辑器写的。其实不管是富文本编辑器还是 Markdown 编辑器写的,最终呈现的都是一个 html 网页,不需要登录就可以看到。之前介绍 Typora 时说过, Markdown 语法和 html 语法本来就类似,所以本文思路是直接下载 html 然后转化为 Markdown 格式。
在 CSDN 页面结构不发生改变的情况下,我们可以用这种方法下载 CSDN 上任意文章并保存成 Markdown 格式。只有写过博客的人才知道原创一篇文章要花费多少精力,所以希望大家如果下载别人的文章一定要标明原地址,这是基本节操。
语言:Python3
。
第三方库:requests
、parsel
、tomd
。
当然可以使用上一篇用到的 pyppeteer,不多对于这个需求来说速度太慢。CSDN 目前没有设置很多反爬虫机制,所以用轻量的 requests 就够了。
parsel
是 Scrapy 框架内置的 html 解析库,后来独立出来。选择 parsel 也是因为够用,且比 BeautifulSoup 更轻。
html 转 Markdown 的库找到两个:tomd 和 html2text ,试了一下都挺好用的,美中不足的是两个库转换完的代码块都没有标识语言类别,导致代码无法高亮。我看了 html 源码是有是语言类别信息的,所以需要对库稍作改动才能达到完美的效果。tomd
的原理比较简单粗暴,直接是正则表达式查找替换,源码就一个文件,比较好改,改动点和源码在下面。
.md
文件,先添加标题、标签、分类、发布时间,再写入 md 正文。在使用tomd
的过程中遇到两个问题,好在源码只有一个文件,原理也很简单,稍微看一下代码逻辑就可以解决。
无序列表转化后没有换行,导致无序列表只有一行。需要修改tomd.py
文件第103
行。
elif self.tag == 'ul' and tag == 'li':
self.content = re.sub(pattern, '\n- \g<1>', self.content)
代码块没有标识语言类别,无法代码高亮。需要修改tomd.py
文件第19
行和第50
行。各加三行,根据实际用到的语言。
# 'block_code': ('\n```\n', '\n```\n'),
'block_code_go': ('\n```go\n', '\n```\n'),
'block_code_py': ('\n```python\n', '\n```\n'),
'block_code_java': ('\n```java\n', '\n```\n'),
'block_code_cpp': ('\n```c\n', '\n```\n'),
# 'block_code': '(.*?)
',
'block_code_go': 'csdn_to_md.py
import os
import re
import parsel
import requests
import tomd
def get_article_info(url):
html = requests.get(url, headers=headers).text
selector = parsel.Selector(html)
urls = selector.css('#articleMeList-blog > div.article-list > div > h4 > a').xpath('.//@href').getall()
print('共找到%d篇文章...' % len(urls))
return urls
def get_html_from_csdn(url):
html = requests.get(url, headers=headers).text
selector = parsel.Selector(html)
title = selector.css('div.article-title-box > h1::text').get()
article = selector.css('div.article_content').get()
category = selector.css('div.blog-tags-box > div > a::text').getall()[0]
tags = selector.css('div.blog-tags-box > div > a[data-report-click*="mod"]::text').getall()
time_stamp = selector.css('div > span.time::text').get()
author = selector.css('#uid > span.name::text').get()
origin = url
return title, article, category, tags, time_stamp, author, origin
def html_to_md(title, article, category, tags, time_stamp, author, origin):
md = tomd.convert(article)
# 图片url标准化
url_pattern = re.compile(r'' )
for src_url in url_pattern.finditer(md):
img_name = src_url.group(1).split('/')[-1]
md = md.replace(src_url.group(0), '![%s](%s)' % (img_name, src_url.group(1)))
print('正在下载 %s' % title)
text = "---\ntitle: %s\ndate: %s\ntags: [%s]\ncategories: %s\n---\n\n> 作者: %s\n> 原文链接: %s\n%s" % (
title, time_stamp, ', '.join(tags), category, author, origin, md)
# Windows下文件名字不能包含特殊符号
file_name = re.sub(r'[\\/:*?"<>|]', ' ', title)
with open('articles/%s.md' % file_name.strip(), 'w', encoding='utf-8') as f:
f.write(text)
def main(url):
if not os.path.exists('articles'):
os.mkdir('articles')
article_urls = get_article_info(url)
for article_url in article_urls:
title, article, category, tags, time_stamp, author, origin = get_html_from_csdn(article_url)
html_to_md(title, article, category, tags, time_stamp, author, origin)
print('完成%d篇文章的下载' % len(article_urls))
if __name__ == '__main__':
headers = {
'Host': 'blog.csdn.net',
'Referer': 'https://blog.csdn.net',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3542.0 Safari/537.36'
}
start_url = "https://blog.csdn.net/用户名"
main(start_url)
本文解决了将 CSDN 上使用富文本编辑器写的文章下载到本地转化成 Markdown 格式的问题,然后再配合上一篇中实现的一键发布脚本,就可以实现三个博客站点的同步了。到这里,已经实现了我自认为很完美的效果,以后就可以开开心心安安静静的写博客了。
我们看别人的独立博客,包括一些博主自己定制的博客园页面时,经常会看到一些有意思的特效,比如切换页签时原标题会变成调皮搞笑的文字,页面点击出现文字或爱心,页面出现跟随鼠标的随机线条,页面动态下雨或雪花,还有可以点击互动的小老鼠、二次元妹子等等,这些效果有的 Hexo 主题就内置了只需要把开关打开,有的需要自己手动加代码实现,因为它们本质上就是一段 js 代码(突然想起在以前公司有一次被安排到前端帮忙,曾经“沉迷”于在系统登录页面添加这些特效,hh)。还有一些针对 Hexo 的优化内容,比如提升页面加载速度,seo 优化,全文搜索插件等。这两项内容准备在最后一篇文章介绍。
写本系列文章第一篇之前,我并没有接触过 Hexo 这些东西,不知道 GitHub Pages 还能这样用,更不知道原来搭建博客里面有这么大的名堂,甚至一直没用 Markdown 写博客。决定自己搭建博客后,我先大概查了一下资料,然后把 8 篇文章的标题确定下来,形成一个大纲。其实在写前面几篇文章的时候,我还没把自己的博客搭起来,是后面一边学习一边操作一边记录,从小白的角度去弄懂每个步骤的原理,将过程记录下来,希望可以帮助更多的小伙伴。还有个意外收获,那就是发现了这是一个学习新东西的好方法。