俺人〜OREGIN〜俺、バカだから人工知能に代わりに頑張ってもらうまでのお話

俺って、おバカさんなので、とっても優秀な人工知能を作って代わりに頑張ってもらうことにしました。世界の端っこでおバカな俺が夢の達成に向けてチマチマ頑張る、そんな小さなお話です。現在はG検定、E資格に合格し、KaggleやProbSpaceのコンペに参画しながら、Pythonや機械学習、統計学、Dockerなどの勉強中です。学習したことをブログにアウトプットすることで、自分の身に着けていきたいと思います。まだまだ道半ばですが、お時間がありましたら見て行ってください。

XMLを解析して要素を出力(Pythonによるスクレイピング&機械学習テクニック)

今回は、 Pythonによるスクレイピング&機械学習開発テクニック増補改訂 Scrapy、BeautifulSoup、scik [ クジラ飛行机 ]の第3章を参考にさせていただきながら、urllib.request+BeautifulSoupで、Web上から、XMLファイルをダウンロードして解析後、要素を出力できるようになりました。

Docker上に構築した開発環境で実行しています。

Dockerでの開発環境の構築については、過去記事をご参照ください。

oregin-ai.hatenablog.com

では、振り返っていきたいと思います。

XMLを解析して要素を出力する。

1.全体像

今回は、XMLファイルの例として、横浜市の防災拠点のXMLファイルを使いました。

URL【https://www.city.yokohama.lg.jp/kurashi/bousai-kyukyu-bohan/bousai-saigai/bosai/data/data.files/hinanjo.xml

この、XMLファイルをダウンロードして、解析を行った後、区ごとに防災拠点を出力するコードを作っていきます。

コード全体は以下の通りで、「xml-bousai.py」に保存しました。

from bs4 import BeautifulSoup
import urllib.request as req
import os.path

 

# ①XMLファイルをダウンロード
url = 'https://www.city.yokohama.lg.jp/kurashi/bousai-kyukyu-bohan/bousai-saigai/bosai/data/data.files/hinanjo.xml'

savename = 'shelter.xml'
if not os.path.exists(savename):
    req.urlretrieve(url, savename)

 

# ➁BeautifulSoupで解析
xml = open(savename, 'r', encoding='utf-8').read()
soup = BeautifulSoup(xml, 'html.parser')

 

#③種類ごとにデータを取得
info = {}

for i in soup.find_all('locationinformation'):
    name = i.find('name').string
    ward = i.find('ward').string
    addr = i.find('address').string
    note = i.find('definition').string

    if not (ward in info):
        info[ward] = []
    info[ward].append(name)

 

#④区(ward)ごとに防災拠点を出力
for ward in  info.keys():
    print('+', ward)
    for name in info[ward]:
        print('| -', name)

 

では、コードを順番に見ていきます。

2.XMLファイルをダウンロード

urllib.request(import時にreqに設定)を使って、防災拠点のXMLファイルのURLからファイルをダウンロードして、「shelter.xml」に保存します。

サーバに負荷をかけないように、ダウンロードしたファイルが存在したら新たにダウンロードしないようにします。

url = 'https://www.city.yokohama.lg.jp/kurashi/bousai-kyukyu-bohan/bousai-saigai/bosai/data/data.files/hinanjo.xml'

savename = 'shelter.xml'
if not os.path.exists(savename):
    req.urlretrieve(url, savename)

3. BeautifulSoupで解析

保存したXMLファイルを読み込んで、BeautifulSoupでXMLを解析します。

openするときに、encordingで文字コード「utf-8」を指定します。文字コードが違っていると文字化けしてしまうので、ダウンロード元の情報を確認して、適切な文字コードを指定する必要があります。

xml = open(savename, 'r', encoding='utf-8').read() 

 次に、BeautifulSoupで構文解析用のパーサに'html.parser'を指定して、XMLファイルを解析します。

soup = BeautifulSoup(xml, 'html.parser')

4.種類ごとにデータを取得

では、解析された結果「soup」を使って各タグに囲まれた要素を取得していきます。

今回のXMLファイルの内容は以下の通りです。

f:id:kanriyou_h004:20200502181103p:plain

図1.XMLファイルの内容

find_all()メソッドで、すべての<LocationInformation>タグで囲まれた要素を取得して、それぞれの要素 i から、find()メソッドで<Name>,<Ward>,<Adress>,<Definition>タグに囲まれた要素を取得します。(NameとWardしか使いませんが)

ここで注意が必要なのは、解析構文用のパーサに'html.parser'を指定して、HTMLとみなして解析しているので、アルファベットの大文字、小文字の区別がなく、すべて小文字で指定する必要がある点です。

info = {}

for i in soup.find_all('locationinformation'):
    name = i.find('name').string
    ward = i.find('ward').string
    addr = i.find('address').string
    note = i.find('definition').string

また、取得した結果について、辞書形式の info に、区(word)ごとの名称(name)のリストを格納していきます。

    if not (ward in info):
        info[ward] = []
    info[ward].append(name)

5.区(ward)ごとに防災拠点を出力

最後に、info.keys()で、infoに格納された区(ward)リストを取得して、区(ward)ごとに、防災拠点の名前(name)を出力していきます。

for ward in  info.keys():
    print('+', ward)
    for name in info[ward]:
        print('| -', name)

5.コマンドラインから実行してみる。

先ほど作成したファイルを実行してみます。

python3 xml-bousai.py

以下の通り、XMLファイルを取得・解析して、区ごとの防災拠点を出力できました! 

f:id:kanriyou_h004:20200502183106p:plain

図2.コマンドラインから実行

これで、Web上に公開されているXML形式のデータについても、巡回して取得できるようになりました。

このほかにも、JSONやYAMLなどいろいろな形式で公開されているデータがあるので、順次、使えるようになっていきたいです。

 

次回以降も、Pythonによるスクレイピング&機械学習開発テクニック増補改訂 Scrapy、BeautifulSoup、scik [ クジラ飛行机 ]で、スクレイピングと機械学習開発に取り組んでいきたいと思います。

 

 

 【過去記事】

2019年8月31日(土)にE資格を受験して、合格しました!

E資格対策として勉強の進め方や、参考書などをまとめました。

これから受験される方がいらっしゃいましたらご参考まで。

oregin-ai.hatenablog.com 

 

 2019年3月9日(土)にG検定を受験し、見事合格できました!

受験の体験記や勉強法などを別のブログにまとめました。

これから受験される方がいらっしゃいましたらご参考まで。

g-kentei.hatenablog.com

 【E資格対策に使った参考書】