見出し画像

noteエクスポート機能によるxmlファイルから、テキスト部分だけを抽出することにした話。

背景

めでたく、noteにエクスポート機能が実装された。

問題は、これが「WXR形式(*)のXMLファイル」で出力されるということ。
以下、私の記事を出力した結果なのだが、文字装飾はじめとするタグまで一括でCSVデータに含まれてしまう…。

出力したばかりの記事データ。xml形式。

これをバックアップ目的に保管するにしても、KDPはじめとする自費出版用のデータに置き換えるにしても、嵩張るし重いし見づらいし、文字構成するのも面倒くさい。何とかならないものかと、Pythonで処理する方法を模索することにした。 
結果、①余計なタグをすべて削除し ②必要な情報のみ抽出 ③すべての記事について①・②を行い結合、csv形式で出力する
コードを書くことに、成功した。


実行

以下が「タイトル」「本文」「記事の状態」を縦一列にで並べてCSV形式で出力するコードだ。 コピペOK。

import xml.etree.ElementTree as ET
import re
import numpy as np
import pandas as pd

# 1 抽出する内容毎に「解析結果格納用リスト」をlist形式で作成する
# 2 xmlファイルの要素解析を行う。内容に対応する属性をもつタグの中から値だけを抽出する
# 3 #3を縦方向に連結、CSVとして出力する

# 1 上から順に「タイトル」「内容」「状態」格納用のlistを作成
title_list = []
content_list = []
status_list = []

# XMLファイルパース
tree = ET.parse('出力したxmlファイルのパスを入力')
root = tree.getroot()

# 以下 2は xmlファイル内 すべてのタグについて抽出を行う

# 2 xmlファイル titleタグ内から タイトルの値を抽出する
for item in root:
    # 子要素の中身を解析
    name = ""
    for child in item.iter():
        # 特定要素の抽出
        if child.tag == 'title':
            # 値を出力
            rank = child.text
            print({rank})
            cdata = [rank]
            title_list.append(cdata)

# 2 xmlファイル content_encodedタグ内から 内容の値を抽出する
for item in root:
    # 子要素の中身を解析
    name = ""
    for child in item.iter():
        # 特定要素の抽出
        if child.tag == 'content_encoded':
            # 値を出力。 続いて、htmlタグを抹消
            rank = child.text
            rank = re.sub(re.compile('<.*?>'), '', str(rank))
            rank = rank.replace('&nbsp;', ' ').replace('\t', ' ').replace('\n', ' ')
            print({rank})
            cdata = [rank]
            content_list.append(cdata)

# 2 xmlファイル wp_statusタグ内から 状態(「公開」「下書き」「予約投稿」)の値を抽出する
for item in root:
    # 子要素の中身を解析
    name = ""
    for child in item.iter():
        # 特定要素の抽出
        if child.tag == 'wp_status':
            # 値を出力
            rank = child.text
            print({rank})
            cdata = [rank]
            status_list.append(cdata)

# 3 記事毎にタイトル→内容→状態の順番で結合する
data = np.column_stack([np.array(title_list),np.array(content_list),np.array(status_list)])
np.savetxt('出力するtxtデータファイル名パスを入力', data, delimiter = ",", fmt = "%s")

※「# 2 xmlファイル content_encodedタグ内から 内容の値を抽出する」ではimgやblockquoteなど内容部分に含まれるコードも一括削除している。
※日時などを追加で抽出してもよい。その場合は
 1.対応するリストを新規作成、
 2.child.tag == 'wp_postdate'で要素解析処理を追加し
 3.dataの列にて、np.array()処理を末尾に追加すること。


結果

出力した結果は、下記の通り。

右が元のデータ。
左が出力後のデータ。コードが綺麗に削除され、カンマ区切りで記事のタイトル、内容、状態が縦一列に並べられている。

これでサクサク、テキストのみをうっとりと眺めることができる。wordにコピペするもよし、テキストマイニングを試すもよし、ご自由に、どうぞ。


応用

①100,200の記事を一度に閲覧する場合は「メモ帳」以外のテキストエディタ:たとえば、EmEditorから開く場合もあるだろう。
このEmEditor、アウトライン機能が使える優れもの。自分は上記コードの「# 2 xmlファイル titleタグ内から タイトルの値を抽出する」に

 # 値を出力
            rank = child.text
            rank= 'title_' +str(rank)
            print({rank})
            cdata = [rank]
            title_list.append(cdata)

と一行追加し、

「アウトライン」プロパティに「title_」を検索条件で設定

note記事タイトルで定義したアウトラインを使って、記事毎にジャンプしつつ、記事の再確認を行っている。

②コード自体も、defメソッドをつかって上下を圧縮したり、列:タイトル→記事→状態で横方向に結合したり改善の余地があるだろう。トライしてみたい。

この映画の話は面白かったでしょうか?気に入っていただけた場合はぜひ「スキ」をお願いします!