public_markdown博客圖片自動上傳

0.目的

為了實現(xiàn)博客的多平臺(簡書只恨、掘金译仗、知乎等)自動化發(fā)布抬虽,需要將本地的markdown中的圖片自動轉(zhuǎn)為圖床鏈接官觅,盡管已經(jīng)有PicGO這種神器,但是自動調(diào)用PicGo上傳圖床有以下兩個問題

  • 本地保留:大量圖片為直接從visio中復(fù)制過來阐污,如果直接上傳本地沒有保留副本
  • 隱私性:有些筆記不做公開休涤,不希望圖片公開

因此使用另一種方法解決自動化發(fā)布問題,即優(yōu)先在本地完成文章,設(shè)置編輯器為將圖片保存在本地功氨,編寫一個自動化替換腳本實現(xiàn)三個功能:

  • 將圖片上傳到圖床(選擇Gitee)
  • 將文章中的鏈接替換為圖床鏈接

1.Gitee圖床

Gitee是國內(nèi)的代碼托管網(wǎng)站序苏,和Github相比具有訪問塊的優(yōu)勢,要將Gitee作為圖床捷凄,需要在Gitee中建立一個公開倉庫并獲取Token忱详,首先建立公開倉庫:

image-20211204153342474

隨后點擊頭像,在安全設(shè)置中選擇私人令牌跺涤,勾選需要的權(quán)限匈睁,點擊提交即可生成token,后續(xù)腳本可以使用這個token通過gitee的API進(jìn)行自動的圖像上傳桶错。自此Gitee圖床搭建完畢航唆,可以嘗試向該倉庫中上傳圖片,如下所示:

image-20211204154619404

該圖片的位置為<倉庫名稱>/raw/master/<圖片路徑>院刁,例如上述圖片位于:<倉庫路徑>/raw/master/assert/player_structure.png

2.自動化上傳

Gitee有API處理新建文件糯钙。根據(jù)API文檔,新建文件的請求類型為POST退腥,請求地址如下所示:

https://gitee.com/api/v5/repos/{owner}/{repo}/contents/{path}

路徑中所需要的內(nèi)容如下所示:

  • owner:倉庫所屬空間的地址任岸,對個人用戶即為用戶名
  • repo:倉庫路徑,即圖床的名稱
  • path:上傳文件的目標(biāo)路徑阅虫,例如上一部分中為assert/player_structure.png

POST的formDate中需要帶的參數(shù)如下所示:

  • access_token:數(shù)據(jù)類型為string演闭,為用戶生成的token
  • content:文件內(nèi)容,數(shù)據(jù)類型為string颓帝,使用base64編碼
  • message:提交信息米碰,數(shù)據(jù)類型為string

這里使用Python3+requests庫構(gòu)建POST請求,構(gòu)建代碼如下所示:

def uploader_picture_gitee(post_data):
    url = "https://gitee.com/api/v5/repos/{owner}/{repo}/contents/{path}".format(
        owner=post_data["owner"],repo=post_data["repo"],path=post_data["path"])
    formdata = {
        "access_token":post_data["token"],
        "content":post_data["content"],
        "message":post_data["message"]
    }
    r = requests.post(url=url,data=formdata)
    if r.status_code == 201:
        print("INFO:upload {} successful".format(post_data["path"]))
        return r.json()["content"]["download_url"]
    return None

其中post_data是包括所有參數(shù)的dict购城,其中owner吕座、repo和token來自預(yù)先寫好的json文件,讀取部分代碼如下所示:

def get_config(cfg_path):
    with open(cfg_path,"r") as f:
        data = json.load(f)
    return data

另外path瘪板、content和message需要根據(jù)圖片文件生成吴趴,其中path由原文件名加上時間戳防止重復(fù),content內(nèi)容需要以二進(jìn)制讀取圖片文件侮攀,并將其使用base64編碼锣枝,該部分代碼如下所示:

def get_picture(pic_path):
    with open(pic_path,'rb') as f:
        data = base64.b64encode(f.read())
    picture_name = os.path.split(pic_path)[-1]
    time_name = int(time.time() * 1000)
    return {
        "content":data,
        "path":"assert/{}_{}".format(time_name,picture_name),
        "message":"{}-upload{}".format(time_name,picture_name)
    }

3.markdown圖片替換

需要將markdown中的圖片語句![]()中的內(nèi)容替換為上傳后的URL,使用正則表達(dá)式識別兰英,正則表達(dá)式如下所示:

r"^\s*!\[.*?\]\(.*?\)"

當(dāng)識別出上述內(nèi)容后撇叁,判斷當(dāng)前行為圖片,這里僅對單獨出現(xiàn)的圖片做處理畦贸,不考慮和文字出現(xiàn)在同一行的圖片陨闹。代碼如下所示:

def handle_markdown(mk_path,cfg_path):
    # read config
    cfg = get_config(cfg_path)

    # read markdown
    with open(mk_path,'r',encoding='utf-8') as f:
        data = f.read().split("\n")

    # search pic and upload
    for i,line in enumerate(data):
        m = re.search(r"^\s*!\[(.*?)\]\((.*?)\)",line)
        if m is not None:
            pic_name,pic_path = m.groups()
            if "://" in pic_path:
                print("INFO:{} is url,ignore".format(pic_path))
                continue
            pic = get_picture(pic_path)
            url = uploader_picture_gitee({**cfg,**pic})
            if url is None:
                raise ValueError("upload {} failed".format(pic_name))
            data[i] = "![{}]({})".format(pic_name,url)

    
    # add thanks
    data.append("> 感謝gitee提供圖片托管服務(wù)楞捂,BlogHelper提供快捷發(fā)布服務(wù)")
    data.append("> 該版本由自動發(fā)布工具生成,原始內(nèi)容為原創(chuàng)趋厉,轉(zhuǎn)載需聯(lián)系作者獲得授權(quán)")

    # generate new markdown
    root,name = os.path.split(mk_path)
    new_path = os.path.join(root,"public_{}".format(name))
    with open(new_path,'w') as f:
        f.write("\n".join(data))

該部分代碼處理的內(nèi)容如下所示:

  • 讀取配置信息
  • 讀取markdown文件
  • 掃描markdown的每一行寨闹,若在這一行發(fā)現(xiàn)圖片插入語句,則判斷其是否為url君账,若不是url則讀取圖片并將其上傳繁堡,并替換為返回的URL
  • 在尾部添加版權(quán)聲明和感謝信息
  • 生成新文件文件名并寫入內(nèi)容

4.發(fā)布

至此,生成了將圖片替換為圖床URL的可發(fā)布版本乡数,通過BlogHelper可自動發(fā)布到各個平臺

感謝gitee提供圖片托管服務(wù)帖蔓,BlogHelper提供快捷發(fā)布服務(wù)
該版本由自動發(fā)布工具生成,原始內(nèi)容為原創(chuàng)瞳脓,轉(zhuǎn)載需聯(lián)系作者獲得授權(quán)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末塑娇,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子劫侧,更是在濱河造成了極大的恐慌埋酬,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烧栋,死亡現(xiàn)場離奇詭異写妥,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)审姓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門珍特,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人魔吐,你說我怎么就攤上這事扎筒。” “怎么了酬姆?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵嗜桌,是天一觀的道長。 經(jīng)常有香客問我辞色,道長骨宠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任相满,我火速辦了婚禮层亿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘立美。我一直安慰自己匿又,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布悯辙。 她就那樣靜靜地躺著琳省,像睡著了一般。 火紅的嫁衣襯著肌膚如雪躲撰。 梳的紋絲不亂的頭發(fā)上针贬,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機(jī)與錄音拢蛋,去河邊找鬼桦他。 笑死,一個胖子當(dāng)著我的面吹牛谆棱,可吹牛的內(nèi)容都是我干的快压。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼垃瞧,長吁一口氣:“原來是場噩夢啊……” “哼蔫劣!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起个从,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤脉幢,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后嗦锐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嫌松,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年奕污,在試婚紗的時候發(fā)現(xiàn)自己被綠了萎羔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡碳默,死狀恐怖贾陷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嘱根,我是刑警寧澤昵宇,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站儿子,受9級特大地震影響瓦哎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜柔逼,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一蒋譬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧愉适,春花似錦犯助、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽惠爽。三九已至,卻和暖如春瞬哼,著一層夾襖步出監(jiān)牢的瞬間婚肆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工坐慰, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留较性,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓结胀,卻偏偏與公主長得像赞咙,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子糟港,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容