【Python基礎】ElementTreeを使ったXMLファイルの解析方法

  • URLをコピーしました!
目次

ElementTree

前回、bar_chart_raceのオプションを色々いじってみました。

今回はXMLファイルの解析方法を紹介しますが、実はXMLファイルの解析は前にBeautifulSoupを使った方法を紹介しています。

そこで今回はPythonの標準ライブラリであるElementTreeを使って、XMLファイルの解析をする方法を紹介します。

今回、XMLファイルは、3PySciのRSSファイルを使用します。

3PySciサイトの右上のWiFiマークが横になったようなマークを右クリックして、「リンク先のファイルをダウンロード」してください。

ダウンロードした「feed.rss」をテキストエディタで開くとこんな感じです。

<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>3PySci</title>
	<atom:link href="https://3pysci.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://3pysci.com</link>
	<description>大人のためのSTEM遊び場〜Python、3Dプリンタ、ガジェット〜</description>
	<lastBuildDate>Wed, 02 Aug 2023 11:57:12 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>

(以下略)

それでは始めていきましょう。

XMLファイルの読み込み

まずはXMLファイルを読み込んでいきます。

「xml.etree.ElementTree」をインポートし、「parse(“ファイルパス”)」でファイルを読み込みます。

その後、「getroot()」でXMLファイルの最初の層(ノード)の要素を取得できます。

最初の段(ノード)の要素とは例えば下のようにXMLファイルがあったとします。

<data>
    <item1>
        <content1>abc</content1>
        <content2>def</content2>
        <content3>ghi</content3>
    </item1>
    <item2>
        <content1>abc</content1>
        <content2>def</content2>
        <content3>ghi</content3>
    </item2>
    <item3>
        <content1>abc</content1>
        <content2>def</content2>
        <content3>ghi</content3>
    </item3>
</data>

この場合「data」が取得できて表示することができますが、その下のノードのデータ「item1」や「content1」などはまだ表示できる状態にはなりません。

ということで試してみましょう。

取得したデータを表示するには「tag(タグ名)」や「attrib(属性)」、「text(テキスト)」などを用います。

import xml.etree.ElementTree as ET

tree =ET.parse("feed.rss")

root = tree.getroot()

print(root.tag)
print(root.attrib)
print(root.text)

実行結果
rss
{'version': '2.0'}


タグは「rss」、属性は「{‘version’: ‘2.0’}」、テキストは「 」(空白)が得られました。

次にもう一つ下のノード(先ほどの例では「item1」、「item2」、「item3」にあたる層)を取得してみましょう。

その場合はfor文を使って取得し、表示は先ほどと同じように「tag」、「attrib」、「text」を使って表示します。

import xml.etree.ElementTree as ET

tree =ET.parse("feed.rss")

root = tree.getroot()

for child in root:
    print(child.tag)
    print(child.attrib)
    print(child.text)

実行結果
channel
{}

下のノードにある情報を取得することができました。

さらに下のノードにある情報を取得するには、さらにfor文を使って取得していきます。

import xml.etree.ElementTree as ET

tree =ET.parse("feed.rss")

root = tree.getroot()

for child in root:
    for grandchild in child:
        print(grandchild.tag)
        print(grandchild.attrib)
        print(child.text)

実行結果
title
{}

	
{http://www.w3.org/2005/Atom}link
{'href': 'https://3pysci.com/feed/', 'rel': 'self', 'type': 'application/rss+xml'}

	
link
{}

(中略)

item
{}

	

特定の要素を取得する方法

とりあえずXMLファイルを読めるようになりましたが、重要なのは次の段階です。

XMLファイルから特定の要素を抽出すること、つまり欲しい情報を取得することです。

それには3つの方法があり「iter(“タグ”)」で取得する方法、「findall(“タグ”)」で取得する方法、「find(“タグ”)」で取得する方法です。

iterで取得する方法

まずは「iter(“タグ”)」で取得する方法です。

これは特定のノード以下のノード全てにおいて、タグの中で指定したタグと同じものを抽出します。

import xml.etree.ElementTree as ET

tree =ET.parse("feed.rss")

root = tree.getroot()

for title in root.iter("title"):
    print(title.text)

実行結果
3PySci
3PySci
【PyScript】PyScriptの始め方とHTML上に文字を出力する方法[Python]
【jQuery】AjaxでPythonを実行する際、matplotlib、numpy、pandasが動かない問題[JavaScript]-未解決
【sympy】数式(関数)を扱うライブラリsympy:数値の代入や式の展開・因数分解、解の求め方、微分・積分[Python]
【Python基礎】datetimeモジュールで曜日を扱う方法
【Python基礎】リストのコピーで注意すること
【Python基礎】リストの順番を並び替えるsort、sorted(ソート)、そしてreverse、reversed(逆順)の違い
【Python基礎】rangeで降順の数値のリストを作成する方法
【JavaScript基礎】大きな数や小数をカンマ区切りにする方法(.toLocaleString)
【jQuery】AjaxでJSONデータの取得、PythonからJSON形式で複数のデータを受け取る方法[JavaScript]
【jQuery】ボタン、入力欄、ドロップダウンメニュー、ラジオボタン、チェックボックスの値の取得[JavaScript]

この方法だと別の意味で同じタグを使っている場合(上記の例では最初の二つの「title」はブログのタイトル、他の「title」は記事名のタイトル)、一緒くたに取得されてしまいます。

そのため、もし区別が必要なら特定のノードに含まれるタグを抽出してから、さらに欲しいタグで抽出するという操作が必要になります。

import xml.etree.ElementTree as ET

tree =ET.parse("feed.rss")

root = tree.getroot()

for item in root.iter("item"):
    for title in item.iter("title"):
        print(title.text)

実行結果
【PyScript】PyScriptの始め方とHTML上に文字を出力する方法[Python]
【jQuery】AjaxでPythonを実行する際、matplotlib、numpy、pandasが動かない問題[JavaScript]-未解決
【sympy】数式(関数)を扱うライブラリsympy:数値の代入や式の展開・因数分解、解の求め方、微分・積分[Python]
【Python基礎】datetimeモジュールで曜日を扱う方法
【Python基礎】リストのコピーで注意すること
【Python基礎】リストの順番を並び替えるsort、sorted(ソート)、そしてreverse、reversed(逆順)の違い
【Python基礎】rangeで降順の数値のリストを作成する方法
【JavaScript基礎】大きな数や小数をカンマ区切りにする方法(.toLocaleString)
【jQuery】AjaxでJSONデータの取得、PythonからJSON形式で複数のデータを受け取る方法[JavaScript]
【jQuery】ボタン、入力欄、ドロップダウンメニュー、ラジオボタン、チェックボックスの値の取得[JavaScript]

findallで取得する方法

次に「findall(“タグ”)」で取得する方法です。

こちらは現在のノードに対して、指定したタグをオブジェクト形式のリストで取得します。

import xml.etree.ElementTree as ET

tree =ET.parse("feed.rss")

root = tree.getroot()

for child in root:
    items = child.findall("item")
    print(items)

実行結果
[<Element 'item' at 0x10c2d4770>, <Element 'item' at 0x10c2d49f0>, 
<Element 'item' at 0x10c2d6660>, <Element 'item' at 0x10c28d940>, 
<Element 'item' at 0x10c1cdbc0>, <Element 'item' at 0x10c1ce4d0>, 
<Element 'item' at 0x10bdb57b0>, <Element 'item' at 0x10bdb6890>, 
<Element 'item' at 0x10c28b240>, <Element 'item' at 0x10c288b80>]

ちなみに「item」タグは2番目のノードにあるため、最初のノードで「findall」しても見つかりません。

import xml.etree.ElementTree as ET

tree =ET.parse("feed.rss")

root = tree.getroot()

items = root.findall("item")
print(items)

実行結果
[]

つまり先ほどの「iter」の例のように記事のタイトル飲みを取得しようと思ったらこうなります。

import xml.etree.ElementTree as ET

tree =ET.parse("feed.rss")

root = tree.getroot()

for child in root:
    for item in child.findall("item"):
        for title in item.findall("title"):
            print(title.text)

実行結果
【PyScript】PyScriptの始め方とHTML上に文字を出力する方法[Python]
【jQuery】AjaxでPythonを実行する際、matplotlib、numpy、pandasが動かない問題[JavaScript]-未解決
【sympy】数式(関数)を扱うライブラリsympy:数値の代入や式の展開・因数分解、解の求め方、微分・積分[Python]
【Python基礎】datetimeモジュールで曜日を扱う方法
【Python基礎】リストのコピーで注意すること
【Python基礎】リストの順番を並び替えるsort、sorted(ソート)、そしてreverse、reversed(逆順)の違い
【Python基礎】rangeで降順の数値のリストを作成する方法
【JavaScript基礎】大きな数や小数をカンマ区切りにする方法(.toLocaleString)
【jQuery】AjaxでJSONデータの取得、PythonからJSON形式で複数のデータを受け取る方法[JavaScript]
【jQuery】ボタン、入力欄、ドロップダウンメニュー、ラジオボタン、チェックボックスの値の取得[JavaScript]

findで取得する方法

「findall」は現在のノードに含まれる特定のタグを全てリスト形式で取得できました。

「find(“タグ”)」は指定したタグのうち、現在のノードの一番最初のもののみを取得します。

import xml.etree.ElementTree as ET

tree =ET.parse("feed.rss")

root = tree.getroot()

for child in root:
    item = child.find("item")
    print(item.find("title").text)

実行結果
【PyScript】PyScriptの始め方とHTML上に文字を出力する方法[Python]

前に紹介したBeautifulSoupでも同じような使い方でしたので、どちらがいいかは慣れや状況によって使い分ければいいのかなと思います。

次回はtimeモジュールを使って処理時間を正確に計測する方法を紹介します。

ではでは今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

目次