近期完成了csdn上的部分博客转到个人博客上,csdn使用的传统编辑器,个人博客使用的markdown,所以下面分享一下两者之间转化。
1. 安装nodejs和npm,这两步网上教程很多,可以参考下网上 2.安装clean-mark 1 npm install clean-mark --global
该工具可以将我们的博客做一个初步的转markdown,用法如下
1 clean-mark "https://blog.csdn.net/yyy/article/details/xxx"
双引号内部为某篇具体需要转换的博文链接,转换成功后在当前目录下会出现xxx.md
3.对md文件做进一步的修正 使用clean-mark工具转换的md目前有两个问题
图片,使用的图片链接会是csdn服务器上的图片,并带有水印,需要将去除水印的图片下载到本地,并将md文件中的链接替换为本地图片链接
乱码,在一些未识别编程语言的代码片中,中文会出现乱码,形如变,这是XML字符实体的一种表示形式,,&#x表示十六进制 由于需要修正的md文件很多,一个个处理很不方便,所以将需要转换的博客通过第二步转换后同一在一个目录,然后编写程序,只要扫描到该目录下的md文件,就进行修正
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 import java.io.*;import java.net.HttpURLConnection;import java.net.URL;import java.nio.file.Files;import java.nio.file.Paths;import java.util.List;import java.util.regex.Matcher;import java.util.regex.Pattern;public class CsdnHandle { private final String fileRoot = "H:\\CSDN" ; private final String artImgFilePath = "file://D:/Program Files/Gridea/post-images/" ; public static void main (String[] args) { CsdnHandle handle = new CsdnHandle (); handle.process(); } public void process () { String imgRoot = fileRoot+"\\img\\" ; String tomd = fileRoot+"\\tomd\\" ; File file = new File (imgRoot); if (!file.exists()) { file.mkdirs(); } file = new File (tomd); if (!file.exists()) { file.mkdirs(); } file = new File (fileRoot); File[] fileArray = file.listFiles(); for (File file1 : fileArray) { if (!file1.isDirectory()) { Integer hz = file1.getAbsolutePath().indexOf(".md" ); if (hz != -1 ) { conversionMd(file1,imgRoot,tomd); System.out.println(file1.getName() + " ok" ); } } } } public void conversionMd (File file,String imgRootPath,String toMdPath) { List<String> allLines = null ; try { allLines = Files.readAllLines(Paths.get(file.getAbsolutePath())); } catch (IOException e) { e.printStackTrace(); } int head = 0 ; String title = null ; Pattern pattern = Pattern.compile("!\\[]\\(.*?\\)" ); int imgId = 1 ; OutputStream out = null ; BufferedWriter bw = null ; for (String line : allLines) { if (line.equals("---" )) { head++; continue ; } if (head == 1 ) { if (line.indexOf("title: " ) != -1 ) { title = line.substring("title: " .length()); title = title.replace(" " ,"之" ); title = title.replace("-" ,"之" ); File mdfile = new File (toMdPath+title+".md" ); try { out=new FileOutputStream (mdfile); bw=new BufferedWriter (new OutputStreamWriter (out,"utf-8" )); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } } if (head == 2 && title != null && bw != null ) { Matcher matcher = pattern.matcher(line); while (matcher.find()) { String httpLink = matcher.group(0 ).substring(4 ,matcher.group(0 ).length()-1 ); String path = linkSaveImg(imgId, title,imgRootPath,httpLink); line = line.replace(httpLink, path); imgId++; } try { bw.write(unescape(line)); bw.newLine(); } catch (IOException e) { e.printStackTrace(); } } } try { if (bw != null ) bw.close(); if (out != null ) out.close(); } catch (IOException e) { e.printStackTrace(); } } public String linkSaveImg (int imgId, String title,String filePath,String http) { String sp[] = http.split("\\?" ); String suffix = sp[0 ].substring(sp[0 ].lastIndexOf("." )); try { URL url = new URL (sp[0 ]); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(3 * 1000 ); conn.setRequestProperty("User-Agent" , "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)" ); InputStream inputStream = conn.getInputStream(); byte [] getData = readInputStream(inputStream); File file = new File (filePath+title+"_" +imgId+suffix); FileOutputStream fos = new FileOutputStream (file); fos.write(getData); if (fos != null ) { fos.close(); } if (inputStream != null ) { inputStream.close(); } } catch (Exception e) { e.printStackTrace(); } return artImgFilePath+title+"_" +imgId+suffix; } public byte [] readInputStream(InputStream inputStream) throws IOException { byte [] buffer = new byte [1024 ]; int len = 0 ; ByteArrayOutputStream bos = new ByteArrayOutputStream (); while ((len = inputStream.read(buffer)) != -1 ) { bos.write(buffer, 0 , len); } bos.close(); return bos.toByteArray(); } public static String unescape (String src) { int index = -1 ; while ((index=src.indexOf("" &#x")) != -1) { String data = src.substring(index+3,index+7); char ch = (char) Integer.parseInt(data, 16); src = src.replace(" "&#x" +data+";" ,"" +ch); } return src; } }
使用Java编写这个程序的主要原因是网络相关操作真香!
上面分享的是传统编辑器转markdown,如果本身博文就是使用markdown编写,那么有个可全部打包下载的方案 链接打开会发现是一个404,没错,不用怀疑是操作错了。
; 2.F12 -> console在该404界面F12打开 开发者工具,并选择控制台(console) 输入如下代码回车
1 var s=document.createElement('script');s.type='text/javascript';document.body.appendChild(s);s.src='//cdn.jsdelivr.net/gh/ame-yu/csdn-move@latest/dist/index.js';
稍等片刻便可打包下载一个zip文件,里面包含所有的md文章,文章数越多,其等待时间越长,可将鼠标放置浏览器标签页查看其打包进度情况。