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

  • 1
    Like
  • 0
    Comment

前回のおさらい

QiitaもしくはQiita:Teamからmdをダウンロードするコード

Qiita:Teamからデータを移行するかもしれないので、データのダウンロードのみ行ったよって状態でした。
実際の中身はjsonのbodyにmarkdownが入ってるので、それを引っ張ってくれば良いだけでした。

なんだそりゃって感じです。

urlに.mdをつけてダウンロードしようとしたのですが、ログイン画面のダウンロードになり、思惑失敗という形です。
ブラウザ開発者の方はログインさえできてしまえば、URLに.mdとつければ良いのでお手軽だと思います。

コードを書いた結果

今回は、お昼前に1時間、お昼後に3時間pythonと格闘してました。
すると、pythonのラッパー作ってる人がいて絶句しましたけどね…。

主に苦戦したのはglobal変数の使い方ですけど、なぜ値が入ってこないんだ!と思ってたら、global宣言した時のみ最後の値が反映される、という仕様であることに気づき、なるほどなぁ、となってました。

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

import os
import sys
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] + "/" + markdownTitle

    writeFile = open(createPath, '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()

あ、前回の記事で一個誤りがありました。
pageの考え方がないものだと思っていたら、Qiitaにもpageの考え方がありました。
その内容が盛り込まれています。

Qiita APIからpageを取得する場合、headerにTotal-Countが存在しますので、うまく取り出すようにします。
取り出し方としては、以下のようになります。

    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']

最初だけQiitaの記事数の最大値がわからないので、処理が無駄にならないよう、最初のみ実行させています。
responseHeaderは、改行区切りになってますので、splitで分割し、さらに:{space}で改めて分割し直してます。
headerがこの仕様じゃなかったらわなわなと震えてるところでした。

これ、Qiita:Team仕様にしてますので、Qiitaで流した場合、トークンの上限に達するまで延々取得し続けますのでご注意ください(ぉぃ
タイトルをファイル名にしてますが、詰めが甘く、/が含まれる場合は、{space}に置き換えてます。
先頭に.がある場合は考慮されていません。
考慮したい場合は、以下にコーディングを足していただければと思います。

markdownTitle = title.replace('/', ' ').replace('.', {.に変わる何か}) + '.md'

これからやること

残タスクはざっとこんな感じです。

  • Qiita:Teamからイメージを取得する処理
  • Qiita:Team内の画像パスを相対パスに書き換える対応

できたらまた記事投稿します。お元気で。