Python BeautifulSoupによるxml解析

前回、
AmazonAPI Pythonによるxmlデータの取得 - 備忘録
によって、Amazonからの商品情報をxml形式で受け取りました。

今回は、xmlSQLcsvに保存できる程度に綺麗に変換してみようと思います。


前回のコードですが、最後の行を変更しています

#coding:utf-8
import amazon import Amazon

access_key_id=""
secret_access_key=""
associate_tag=""

amazon=Amazon(access_key_id,secret_access_key,associate_tag)
xml=amazon.itemSearch("Books",Keywords=u"数学",ItemPage="1",ResponseGroup="Large")
print xml

f:id:alstd:20150102144347p:plain
変数xmlに大量の文字情報が貯められていますが、このままでは使い物にならないため、整理したり、必要な情報だけを取り出すことをxmlパース(解析)と言います。

Pythonにはhtmlパースを行うためのライブラリ、BeautifulSoupがあって、これはxmlにもある程度実用することができますし、AmazonAPI形式ならば今のところ手の届かない処理はありませんでした。


まず、BeautifulSoupのインストールは

sudo pip install beautifulsoup

です。


では、早速著者情報を抜き取り、SQLに保存してみましょう。

#coding:utf-8
from amazon import Amazon
from BeautifulSoup import BeautifulStoneSoup
import sqlite3

access_key_id="AKIAI3BTABUGQXERS6FA"
secret_acess_keys="tv0V27jJ+4ArXKtOzjQQbfHPdiibYlOS0qHsjZRU"
associate_tag="alamz-22"

con=sqlite3.connect("sample.sqlite3",isolation_level=None)
sql=u"""
create table IF NOT EXISTS Amazon_Books(
	ISBN varchar(63),
	author varchar(255),
	title varchar(255)
);
"""
con.execute(sql)

amazon = Amazon(access_key_id, secret_acess_keys,associate_tag)

xml = amazon.itemSearch("Books", Keywords=u"物理学", ItemPage="1",ResponseGroup="Large")
#print amazon.url
#print xml

#xmlにはBeautifulStoneSoup(xml)、htmlにはBeautifulSoup(html)
soup = BeautifulStoneSoup(xml)

#xmlの中からitemsを見つけ出し、itemsリストにBeautifulStoneSoupクラスとして保存
items = soup.find("items")

#何件あるかの結果は、xml内のtotalresultsタグにあり、その中身をcontents[0]で抜き出す。
print "%s件見つかりました" % soup.find("totalresults").contents[0].encode('utf-8')

#何ページあるかの結果は、xml内のtotalpagesタグにあり、その中身をcontents[0]で抜き出す。
total_pages = soup.find("totalpages").contents[0]

#xmlのitemタグ1つは、1商品の情報を囲っている。つまり、1商品の情報ごとをループ処理していく。
for item in soup.findAll("item"):
	print "\n\n------------------------------"
	ISBN=item.asin.contents[0];
	author=[]
	if item.author==None:
		author.append("None")
	else:
		for i in range(len(item.author)):
			author.append(item.author.contents[i])
	title=item.title.contents[0]

	author_str="" 
	for i in author:
		author_str+=i.encode('utf-8')+","
	author_str=author_str.rstrip(',')

	print ISBN,author_str,title

	sql='''
	insert into Amazon_Books values("%s","%s","%s");''' % (ISBN.encode('utf-8'),author_str,title.encode('utf-8'))
	print sql
	con.execute(sql)

con.close()

sample.sqlite3を確認すると、

***@***:~/AmazonAPI$ sqlite3 sample.sqlite3
SQLite version 3.8.2 2013-12-06 14:53:30
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> Select * from Amazon_Books;
4785320745|小出 昭一郎|物理学
4163757708|ウォルター ルーウィン|これが物理学だ! マサチューセッツ工科大学「感動」講義
4004200857|朝永 振一郎|物理学とは何だろうか〈上〉 (岩波新書)
4000077112|ファインマン|ファインマン物理学〈1〉力学
B009AJ8266|寺田 寅彦|物理学と感覚
4569573908|None|「量子論」を楽しむ本―ミクロの世界から宇宙まで最先端物理学が図解でわかる! (PHP文庫)
4480016007|山口 栄一|死ぬまでに学びたい5つの物理学 (筑摩選書)
4121022807|小山 慶太|入門 現代物理学 - 素粒子から宇宙までの不思議に挑む (中公新書)
B00B7UNYD2|ウォルター・ルーウィン|これが物理学だ! マサチューセッツ工科大学「感動」講義
4004200865|朝永 振一郎|物理学とは何だろうか〈下〉 (岩波新書 黄版 86)

確かに保存されています。


BeautifulSoupは他にも、サイトのHTMLから情報を抜き出すときに使われたりします。
APIに対応していなくとも無理やり情報を抜き出せるという訳です。
使いこなせると便利ですので、細々とした点まで覚えておいて損はないと思います。


参考にしたサイトです。
Beautiful Soupドキュメント — BeautifulSoup Document 0.1 ドキュメント
kondou.com - Beautiful Soup 4.2.0 Doc. 日本語訳 (2013-11-19最終更新)


SQLはいわゆるリスト内にリストを保存するような構造を持てないそうです。
例えば、authorは2人、5人、0人だったりと可変ですが、事前にデータ型を決める以上一人につき一つのセルを与えることができない、という意味です。
このときのコツとして、Pythonプログラムのauthor_strの処理のように0人ならNone、複数なら','つきで加えた一つの文にする、といった手法が取れます。
注意すべき点として、例えばauthorとしてR.P.Feynmanといった変数を保存したとき、'.'区切りならば、RさんとPさんとFeynmanさんが共著したかのような解釈となります。
区切り文字はデータとして使いそうにないものを選びましょう。