noteエクスポート機能によるxmlファイルから、テキスト部分だけを抽出することにした話。
背景
問題は、これが「WXR形式(*)のXMLファイル」で出力されるということ。
以下、私の記事を出力した結果なのだが、文字装飾はじめとするタグまで一括でCSVデータに含まれてしまう…。
これをバックアップ目的に保管するにしても、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(' ', ' ').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")
結果
出力した結果は、下記の通り。
これでサクサク、テキストのみをうっとりと眺めることができる。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メソッドをつかって上下を圧縮したり、列:タイトル→記事→状態で横方向に結合したり改善の余地があるだろう。トライしてみたい。
この映画の話は面白かったでしょうか?気に入っていただけた場合はぜひ「スキ」をお願いします!