儲存CSDN 中的部落格文章為本地檔案

青蛙愛輪滑發表於2019-03-31

儲存CSDN 中的部落格文章為本地檔案


2019年3月31日21:49:39 【原創】
python 學習部落格目錄

1. 執行環境

最近發現我CSDN裡的部落格中,外鏈的圖片全部無法載入,部落格總使用的圖片論壇是 https://i.imgur.com/,圖片連結形如 https://i.imgur.com/WxbYfSu.png,圖片是使用 markdown 軟體寫部落格時上傳的。

目前在國內的 IP 無法訪問 i.imgur.com 網站,不知道啥情況。

現在的問題是國內的IP無法訪部落格裡的圖片,所以決定掛個國外的代理將圖片儲存至本地,以後有時間再寫個指令碼再批量替換,畢竟部落格數量還是很多的。

有幾點不足:

  1. 未下載 css 和 js 檔案,其實實現起來很簡單,可以複製程式碼中的正則自己擴充套件。
  2. 下載後的HTML檔案中的js和css都是需要聯網,不聯網只能看到文章內容,不能看到美化佈局。

廢話不多說,環境是 python3 的,沒有多餘的庫需要安裝,忘記是不是需要 pillow 庫了。

pip install Pillow

2. 流程分解

  1. URL儲存在檔案中

    在這裡插入圖片描述

  2. getHtml() 函式,作用是掛代理訪問 URL;

     def getHtml(url):
         proxies = {"https": "127.0.0.1:1080"}
         response = requests.get(url, proxies = proxies)
         return response.text
    
  3. getImg() 函式,作用是格式化過濾儲存文章內容為圖片;

     # 過濾自動跳轉
         pattern1 = re.compile(r'<div style="display:none;">(.*?)</div>',flags=re.S)
         match1 = pattern1.sub('',body)
         #print(match1)
    
  4. 頁面中的title作為檔名,同時也是路徑名;

     # 獲取title作為檔名使用
     title = ''
     title_list = re.findall('<title>(.*?) - kevinhanser - CSDN部落格</title>',match4)
     #print(title_list)
     title = str(title_list[0])
     print(title)
    
  5. 將body中的關於圖片的路徑連結都替換為本地的圖片路徑,使在本地檢視文章時也可以載入圖片;

     # 定位body中的圖片位置
         #match5 = pattern5.findall(match4)
         pattern5 = re.compile(r'<p>(.*)i.imgur.com')
         # 替換body中的圖片檔名為本地的(./image/+title)
         match5 = pattern5.sub('<img src="'+'./image/'+title,match4)
    
  6. for 迴圈中是將圖片名使用正則匹配出來,然後構造完整的圖片連結下載並儲存為同名檔案。

     # 儲存圖片,將img_url儲存為img_path,儲存為本地檔案
       if not os.path.exists(img_path):
             with urllib.request.urlopen(img_url, timeout=120) as response, open(img_path, 'wb') as f_save:
                     f_save.write(response.read())
                     f_save.flush()
                     f_save.close()
    

3. 程式碼部分

#coding=utf-8
import urllib   #urllib模組提供了讀取Web頁面資料的介面.
import os       # 系統相關
import re       # 正規表示式
from PIL import Image
import os,stat
import urllib.request
import requests
import time
# python3

def getHtml(url):
    proxies = {"https": "127.0.0.1:1080"}
    response = requests.get(url, proxies = proxies)
    return response.text

def getImg(body):
    # 過濾自動跳轉
    pattern1 = re.compile(r'<div style="display:none;">(.*?)</div>',flags=re.S)
    match1 = pattern1.sub('',body)
    #print(match1)
    
	 # 過濾推薦及廣告
    pattern2 = re.compile(r'</article>(.*)</script>',flags=re.S)
    match2 = pattern2.sub('</div>',match1)
    #print(match2)
    
    # 過濾CSDN的最上頭的橫幅
    pattern2_tmp = re.compile(r'b site By baidu end\n    </script>\n    (.*?)    <script src="https://csdnimg.cn/rabbit/exposure-click/main-1.0.6.js"></script>',flags=re.S)
    match2_tmp = pattern2_tmp.sub('',match2)
    #print(match2_tmp)
    
    # 過濾css,使頁面全屏
    pattern3 = re.compile(r'https://csdnimg.cn/release/phoenix/themes/skin-yellow/skin-yellow-2eefd34acf.min.css',flags=re.S)
    match3 = pattern3.sub('',match2_tmp)
    #print(match3)
    
    # 過濾使頁面最大,而不是居中固定寬度
    pattern4 = re.compile(r'container',flags=re.S)
    match4 = pattern4.sub('container_bak',match3)
    #print(match4)    
    #container
    
    # 獲取title作為檔名使用
    title = ''
    title_list = re.findall('<title>(.*?) - kevinhanser - CSDN部落格</title>',match4)
    #print(title_list)
    title = str(title_list[0])
    print(title)
    
    # python2中使用.decode('string_escape')編碼為中文
    #title = str(title_list[0]).decode('string_escape')
    
    # 獲取圖片名
    picture_list = re.findall('https://i.imgur.com/(.*?).png',match4)
    picture = picture_list
    #print picture
    
    # 定位body中的圖片位置
    #match5 = pattern5.findall(match4)
    pattern5 = re.compile(r'<p>(.*)i.imgur.com')
    # 替換body中的圖片檔名為本地的(./image/+title)
    match5 = pattern5.sub('<img src="'+'./image/'+title,match4)
    
    # 將body寫成檔案,編碼為中文
    f = open(title+'.html','w',encoding='utf8')
    f.write(match5)
    f.close()
    
    #部落格中無圖片則提示
    if len(picture) == 0:
        print("%s 中無圖片" % title)
    
    #部落格中有圖片則儲存,使用title作為目錄路徑名
    for i in range(len(picture)):
        if not os.path.exists('./image/'+title):
            os.makedirs('./image/'+title)
            
        #print picture[i]
        img_path = './image/'+title+'/'+picture[i]+'.png'
        img_url = 'https://i.imgur.com/'+picture[i]+'.png'
        print("%s 開始..." % img_url)
        #print(img_path)
        
        # 儲存圖片,將img_url儲存為img_path,儲存為本地檔案
        if not os.path.exists(img_path):
            with urllib.request.urlopen(img_url, timeout=120) as response, open(img_path, 'wb') as f_save:
                    f_save.write(response.read())
                    f_save.flush()
                    f_save.close()
        
            # 請求過快會報錯,前面有重試機制
            #time.sleep(15)
            
        print(picture[i]+'.png'+"圖片載入完成")             


if __name__ == '__main__':
    
    # kali.txt 文件中存放的是CSDN部落格的URL連結
    f = open("kali.txt","r")
    URL_list = f.readlines()
    f.close()
    print(URL_list)
    
    for url in URL_list:	        
        # 設定錯誤重試機制
        attempts = 0
        success = False
        print(url)
        while attempts < 30 and not success:
            try:
                # 呼叫函式,主要就這兩個
                body = getHtml(url.strip("\n"))     # 獲取頁面body
                getImg(body)                        # 對body進行操作
                success = True
            except:
                attempts += 1
                # 重試超時
                if attempts % 5 == 0:
                    time.sleep(10) 
                elif attempts == 30:
                    break 

相關文章