擼了幾行騷代碼,解放了雙手!

大家好,我是二哥呀~

作爲一名技術博主,經常需要把同一份 MD 文件同步到不同的博客平臺,以求獲得更多的曝光,從而幫助到更多的小夥伴——瞧我這“達則兼濟天下”的雄心壯志。像 CSDN 和掘金這兩個博客平臺都有自己的外鏈圖片解析功能。

當我把 MD 源文檔複製到 CSDN 或者掘金的編輯器中,它們會自動地幫我把外鏈轉成內鏈,這樣我就不用再重新上傳圖片,也不需要配置自己的圖牀了,否則圖片會因爲防盜鏈的原因顯示不出來。

舉個例子,現在有這樣一段 MD 文檔,裏面有一張圖片。

![](https://upload-images.jianshu.io/upload_images/1179389-0155ada60932b724.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

把上面的 MD 文檔複製到掘金編輯器的時候,就會出現「圖片解析中...」!但會一直卡在這裏,再也解析不下去了。

這是因爲圖片加了防盜鏈,掘金這麼牛逼的社區在解析的時候也會失敗。CSDN 的轉鏈功能更牛逼一點,基本上可以無視防盜鏈。

還有一些博客平臺是沒有轉鏈功能的,比如說二哥的靜態小破站《Java 程序員進階之路》。怎麼辦呢?我一開始的解決方案是:

  • 先將圖片手動一張張下載到本地
  • 再將本地圖片上傳到 GitHub 指定的倉庫
  • 修改 MD 文檔中的圖片鏈接,使用 CDN 加速服務

這樣就能解決問題,但是需要手動去做這些重複的動作,尤其遇到一篇文章有二三十張圖片的時候就很煩。這有點喪失我作爲程序員的尊嚴啊!

首先要解決的是圖片下載的問題,可以利用爬蟲技術:爬蟲爬得早,局子進的早。

二、關於 Java 爬蟲

Java 爬蟲的類庫非常多,比如說 crawler4j,我個人更喜歡 jsoup,它更輕量級。jsoup 是一款用於解析 HTML 的 Java 類庫,提供了一套非常便捷的 API,用於提取和操作數據。

官網地址:https://jsoup.org/

jsoup 目前在 GitHub 上已經收穫 9.3k+ 的 star,可以說是非常的受歡迎了。

jsoup 有以下特性:

  • 可以從 URL、文件或者字符串中抓取和解析
  • 可以使用 DOM 遍歷或者 CSS 選擇器查找和提取數據
  • 可以操作 HTML 元素、屬性和文本
  • 可以輸出整潔的 HTML

三、實戰 jsoup

第一步,添加 jsoup 依賴到項目中

<dependency>
  <!-- jsoup HTML parser library @ https://jsoup.org/ -->
  <groupId>org.jsoup</groupId>
  <artifactId>jsoup</artifactId>
  <version>1.14.3</version>
</dependency>

第二步, 獲取網頁文檔

就拿二哥之前發表的一篇文章《二哥的小破站終於上線了,顏值賊高》來舉例吧。通過以下代碼就可以拿到網頁文檔了。

Document doc = Jsoup.connect("https://blog.csdn.net/qing_gee/article/details/122407829").get();
String title = doc.title();

Jsoup 類是 jsoup 的入口類,通過 connect 方法可以從指定鏈接中加載 HTML 文檔(用 Document 對象來表示)。

第三步,獲取圖片節點

再通過以下代碼可以獲取文章所有的圖片節點:

Elements images = doc.select(".article_content img[src~=(?i)\\.(png|jpe?g|gif)]");
for (Element image : images) {
    System.out.println("src : " + image.attr("src"));
}

輸出結構如下所示:

四、下載圖片

拿到圖片的 URL 地址後,事情就好辦了,可以直接通過 JDK 的原生 API 下載圖片到指定文件夾。

String downloadPath = "/tobebetterjavaer-beian-";
for (Element image : images) {
    URL url = new URL(image.attr("src"));
    InputStream inputStream = url.openStream();
    OutputStream outputStream = new FileOutputStream(downloadPath + i + ".png");
    byte[] buffer = new byte[2048];
    int length = 0;
    while ((length = inputStream.read(buffer)) != -1) {
        outputStream.write(buffer, 0, length);
    }
}

如果想加快節奏的話,可以把上面的代碼封裝一下,然後開個多線程,簡單點的話,可以每張圖片起一個線程,速度槓槓的。

new Thread(new MyRunnable(originImgUrl, destinationImgPath)).start()

五、使用 CDN 加速圖片

圖片下載到本地後,接下來的工作就更簡單了,讀取原 MD 文檔,修改圖片鏈接,使用 CDN 進行加速。我的圖牀採用的是 GitHub+jsDelivr CDN 的方式,不過由於 jsDelivr 的國內節點逐漸撤離了,圖片在某些網絡環境下訪問的時候還是有點慢,後面打算用 OSS+CDN 的方式,更靠譜一點。

讀取文件可以藉助一下 hutool 這款 GitHub 上開源的工具類庫,省去很多繁瑣的 IO 操作。

官網:https://hutool.cn/

第一步,將 hutool 添加到 pom.xml 文件中

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.20</version>
</dependency>

第二步,按照行讀取 MD 文件,需要用到 hutool 的 FileReader 類:

FileReader fileReader = FileReader.create(new File(docPath +fileName),
                Charset.forName("utf-8"));
List<String> list = fileReader.readLines();

第三步,通過正則表達式來匹配是否有需要替換的圖片標籤,MD 中的圖片標記關鍵字爲 ![]()

![](https://upload-images.jianshu.io/upload_images/1179389-71c15111525af102.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

如果匹配到,就替換爲 jsDelivr CDN 鏈接的地址,寫文件時需要用到 hutool 的FileWriter 類。

FileWriter writer = new FileWriter(docPath + fileName);
for (String line : list) {
    Matcher m = pattern.matcher(line);
    if (m.matches()) {
        writer.append("![](" + imgCdnPre +  num + imgSuffix +")\n");
    } else {
        writer.append(line+"\n");
   }
}
writer.flush();

到此爲止,整個代碼的編寫工作就告一段落了。很簡單,兩個類庫,幾行代碼就搞定了!

轉換前的 MD 文件如下所示:

運行代碼轉換後,發現圖片地址已經變成 jsDelivr CDN 圖庫了。

使用 GitHub 桌面版把圖片和 MD 文檔提交到 GitHub 倉庫後,就可以看到圖片已經加載完成可以訪問了。

六、一點小心得

不得不說,懂點技術,還是非常爽的。擼了幾行代碼,解放了雙手,可以乾點正經事了(狗頭)。

這不,重新把《Java 程序員進階之路》的小破站整理排版了一下,新增了不少優質的內容。學習 Java 的小夥伴可以開卷了,有需要增加的內容也歡迎提交 issue 啊!

再次感謝各位小夥伴的厚愛,我也會一如既往地完善這個專欄,我們下期見~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章