Qiita
team
移行

Qiita:Teamから画像を保存し、ついでにパスを書き換えるまで

More than 1 year has passed since last update.

前回のおさらい

Qiita:TeamからMarkdownを保存するまで

Qiita:TeamからMarkdownを保存するまでを前回作成しました。

  • 残った部分は画像の抽出部分
  • 画像を保存する処理
  • 画像パスを書き換え

この三つができれば完了となります。

コードを書いた結果

先週出来上がってはいたのですが、Gitlabに実際pushしてみたら見栄えがどうなるかを確認してみたかったので、ちょっと間を空けてみました。

で、本日、Gitlabにpushした際、画像のパスが誤っていたのですが、どうやら年/月/files/ファイル名としなければ、Gitlabは認識してくれないっぽいです。
相対パスじゃないんだ…。

コードはこんな感じになったのですが、個人的にイケてないのは、正規表現ですね。
真面目に正規表現を書いてみたのですが、もっとうまいことやれる気がしてならないコーディングです。

#!/usr/bin/env python
# coding: utf-8

import os
import sys
import re
import json
import urllib.request
import urllib.parse

url = ''
apiKey = ''
teamName = ''
api = '/api/v2/items?per_page=100'
pageApi = '&page='
pageCount = 0
maxCount = 0

def argmentscheck():
    global url
    global apiKey
    global teamName
    global api

    url = ''
    apiKey = ''
    teamName = ''
    api = '/api/v2/items?per_page=100'

    if len(sys.argv) == 2:
        apiKey = sys.argv[1]
        url = 'https://qiita.com'
        print('Qiitaからデータを抜き出します')
    elif len(sys.argv) == 3:
        apiKey = sys.argv[1]
        teamName = sys.argv[2]
        url = 'https://' + teamName + '.qiita.com'
        print('Qiita:Teamの' + teamName + 'からデータを抜き出します')
    else :
        print('引数の数が何かおかしいです')

def createDirectory(createDay, markdownUrl):
    directoryArray = createDay.split('-')
    createPath = "./" + directoryArray[0] + "/" + directoryArray[1]

    if not(os.path.exists(createPath)):
        os.makedirs(createPath)

def getPerPageJsonDownload():
    global pageApi
    global pageCount
    global maxCount

    headers = {"Authorization" : "Bearer " + apiKey}
    requestUrl = url + api

    if pageCount:
        requestUrl = url + api + pageApi + str(pageCount)

    request = urllib.request.Request(requestUrl, None, headers)
    response = urllib.request.urlopen(request)
    responseHeader = str(response.info())

    if maxCount == 0:
        headerList = []
        headerDict = {}
        for headerOneline in responseHeader.split('\n'):
            for oneWord in headerOneline.split(': '):
                if len(oneWord):
                    headerList.append(oneWord)
        headerDict = dict(zip(headerList[0::2], headerList[1::2]))
        maxCount = headerDict['Total-Count']

    jsonRaw = response.read().decode('utf-8')
    json.dumps(jsonRaw, ensure_ascii=False)
    return jsonRaw

def fileWriting(createDay, markdown, title):
    markdownTitle = title.replace('/', ' ') + '.md'
    directoryArray = createDay.split('-')

    createPath = "./" + directoryArray[0] + "/" + directoryArray[1] + "/" + "files/"
    filePath = "./" + directoryArray[0] + "/" + directoryArray[1] + "/" + markdownTitle

    if not(os.path.exists(createPath)):
        os.makedirs(createPath)

    pattern = r"https://qiita.com[a-zA-Z0-9/-].*\.(?:png|jpg|jpeg)"
    pattern += r"|https://qiita-image-store.s3.amazonaws.com[a-zA-Z0-9/-].*\.(?:png|jpg|jpeg)"
    if len(teamName):
        pattern += r"|https://" + teamName + r".qiita.com[a-zA-Z0-9/-].*\.(?:png|jpg|jpeg)"

    matchedList = re.findall(pattern, markdown)
    headers = {"Authorization" : "Bearer " + apiKey}

    for oneImage in matchedList:
        url = oneImage.split(" ")[0].split(")")[0]
        request = urllib.request.Request(url)

        if (re.search(r"qiita.com", url)):
            request = urllib.request.Request(url, None, headers)

        response = urllib.request.urlopen(request)
        fileName = url.split('/')[-1]
        writeFile = open(createPath + fileName, 'wb')
        writeFile.write(response.read())
        writeFile.close()
        markdown = markdown.replace(url, createPath + fileName)

    writeFile = open(filePath, 'w')
    writeFile.write(markdown)
    writeFile.close()

def main():
    global pageCount

    jsonRaw = getPerPageJsonDownload()
    jsons = json.loads(jsonRaw)
    for count in range(round(int(maxCount)/len(jsons))):
        pageCount += 1
        for oneWrote in jsons:
            createDirectory(oneWrote['created_at'], oneWrote['url'])
            fileWriting(oneWrote['created_at'], oneWrote['body'], oneWrote['title'] )
        jsonRaw = getPerPageJsonDownload()
        jsons = json.loads(jsonRaw)

if __name__ == '__main__':
    argmentscheck()
    main()


ポイントはここです。

    pattern = r"https://qiita.com[a-zA-Z0-9/-].*\.(?:png|jpg|jpeg)"
    pattern += r"|https://qiita-image-store.s3.amazonaws.com[a-zA-Z0-9/-].*\.(?:png|jpg|jpeg)"
    if len(teamName):
        pattern += r"|https://" + teamName + r".qiita.com[a-zA-Z0-9/-].*\.(?:png|jpg|jpeg)"

    matchedList = re.findall(pattern, markdown)
    headers = {"Authorization" : "Bearer " + apiKey}

    for oneImage in matchedList:
        url = oneImage.split(" ")[0].split(")")[0]
        request = urllib.request.Request(url)

        if (re.search(r"qiita.com", url)):
            request = urllib.request.Request(url, None, headers)

        response = urllib.request.urlopen(request)
        fileName = url.split('/')[-1]
        writeFile = open(createPath + fileName, 'wb')
        writeFile.write(response.read())
        writeFile.close()
        markdown = markdown.replace(url, createPath + fileName)

最初、横着して、以下のように書いたのですが、png,jpeg,jpgしか取れず、なんだとー!?と思いながら、全部書く羽目になりました。

r"https://qiita.com.*\.png|jpg|jpeg"

よくよく考えると | って置き換えてくれるわけじゃないのね…と正直、衝撃を受けてました。

長ったらしいし、うまい書き方を求めます。
正規表現をシンプルにする方法を教えていただきました。

ただ多分他の人が書いた記事によってはうまく動かないパターンもあるんだろうなって思ってます。
主眼をQiita:Teamに向けてることもあり、やはりQiitaでは動かないですね…。

また近いうちに直しますが、今週はちょっと無理っぽいです。

まとめ

これで一応一つ実績が積めたわけですが、標準ライブラリを使うならpython3はすっごい楽なのでオススメです。
次はAWSのlambdaを使って処理したいなーと思います。
lambdaで何しようかな……。
Githubにもあげておこう。