「Beautiful Soup」の版間の差分
ナビゲーションに移動
検索に移動
(ページの作成:「==Beautiful Soup (HTML XML解析)== [Python] *http://www.crummy.com/software/BeautifulSoup/ *Document **http://www.crummy.com/software/BeautifulSoup/documentation.h…」) |
|||
| 1行目: | 1行目: | ||
==Beautiful Soup (HTML XML解析)== | ==Beautiful Soup (HTML XML解析)== | ||
| − | [Python] | + | [[Python]] |
*http://www.crummy.com/software/BeautifulSoup/ | *http://www.crummy.com/software/BeautifulSoup/ | ||
| 35行目: | 35行目: | ||
import BeautifulSoup # To get everything | import BeautifulSoup # To get everything | ||
| − | + | <blockquote>No module named BeautifulSoup エラーとなる場合</blockquote> | |
from bs4 import BeautifulSoup # To get everything | from bs4 import BeautifulSoup # To get everything | ||
==解析== | ==解析== | ||
*文字列およびファイルハンドルによる文書解析 | *文字列およびファイルハンドルによる文書解析 | ||
soup = BeautifulSoup(open("index.html")) | soup = BeautifulSoup(open("index.html")) | ||
| − | soup = BeautifulSoup(" | + | soup = BeautifulSoup("<html>data</html>") |
*URLを指定して解析 | *URLを指定して解析 | ||
| 71行目: | 71行目: | ||
*もっとも知られているのが、class | *もっとも知られているのが、class | ||
*Beautiful Soupでは、リストとして扱う | *Beautiful Soupでは、リストとして扱う | ||
| − | css_soup = BeautifulSoup(' | + | css_soup = BeautifulSoup('<p class="body strikeout"></p>') |
css_soup.p['class'] | css_soup.p['class'] | ||
# ["body", "strikeout"] | # ["body", "strikeout"] | ||
*XMLでは、複数値として扱わない | *XMLでは、複数値として扱わない | ||
| − | xml_soup = BeautifulSoup(' | + | xml_soup = BeautifulSoup('<p class="body strikeout"></p>', 'xml') |
xml_soup.p['class'] | xml_soup.p['class'] | ||
# u'body strikeout' | # u'body strikeout' | ||
| 85行目: | 85行目: | ||
# u'Extremely bold' | # u'Extremely bold' | ||
type(tag.string) | type(tag.string) | ||
| − | # | + | # <class 'bs4.element.NavigableString'> |
*unicode() で、Unicode 文字列に変換できる | *unicode() で、Unicode 文字列に変換できる | ||
unicode_string = unicode(tag.string) | unicode_string = unicode(tag.string) | ||
| 91行目: | 91行目: | ||
# u'Extremely bold' | # u'Extremely bold' | ||
type(unicode_string) | type(unicode_string) | ||
| − | # | + | # <type 'unicode'> |
===BeautifulSoup=== | ===BeautifulSoup=== | ||
*文書全体を表す | *文書全体を表す | ||
| 99行目: | 99行目: | ||
===コメント=== | ===コメント=== | ||
*Commentオブジェクトは、NavigableStringの特殊型 | *Commentオブジェクトは、NavigableStringの特殊型 | ||
| − | markup = " | + | markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>" |
soup = BeautifulSoup(markup) | soup = BeautifulSoup(markup) | ||
comment = soup.b.string | comment = soup.b.string | ||
type(comment) | type(comment) | ||
| − | # | + | # <class 'bs4.element.Comment'> |
==treeのナビゲート== | ==treeのナビゲート== | ||
===下がる=== | ===下がる=== | ||
| 112行目: | 112行目: | ||
====.contents と .children==== | ====.contents と .children==== | ||
head_tag.contents | head_tag.contents | ||
| − | [ | + | [<title>The Dormouse's story</title>] |
for child in title_tag.children: | for child in title_tag.children: | ||
| 121行目: | 121行目: | ||
for child in head_tag.descendants: | for child in head_tag.descendants: | ||
print(child) | print(child) | ||
| − | # | + | # <title>The Dormouse's story</title> |
# The Dormouse's story | # The Dormouse's story | ||
====.string==== | ====.string==== | ||
| 143行目: | 143行目: | ||
title_tag = soup.title | title_tag = soup.title | ||
title_tag | title_tag | ||
| − | # | + | # <title>The Dormouse's story</title> |
title_tag.parent | title_tag.parent | ||
| − | # | + | # <head><title>The Dormouse's story</title></head> |
====.paretns==== | ====.paretns==== | ||
link = soup.a | link = soup.a | ||
link | link | ||
| − | # | + | # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a> |
for parent in link.parents: | for parent in link.parents: | ||
if parent is None: | if parent is None: | ||
| 163行目: | 163行目: | ||
====.next_sibling と .prebious_sibling==== | ====.next_sibling と .prebious_sibling==== | ||
sibling_soup.b.next_sibling | sibling_soup.b.next_sibling | ||
| − | # | + | # <c>text2</c> |
sibling_soup.c.previous_sibling | sibling_soup.c.previous_sibling | ||
| − | # | + | # <b>text1</b> |
====.next_siblings と .prebious_siblings==== | ====.next_siblings と .prebious_siblings==== | ||
for sibling in soup.a.next_siblings: | for sibling in soup.a.next_siblings: | ||
| 207行目: | 207行目: | ||
*以下はほぼ同等 | *以下はほぼ同等 | ||
soup.find_all('title', limit=1) | soup.find_all('title', limit=1) | ||
| − | # [ | + | # [<title>The Dormouse's story</title>] |
soup.find('title') | soup.find('title') | ||
| − | # | + | # <title>The Dormouse's story</title> |
=====CSSクラスで検索===== | =====CSSクラスで検索===== | ||
soup.find("b", { "class" : "lime" }) | soup.find("b", { "class" : "lime" }) | ||
| − | # | + | # <b class="lime">Lime</b> |
====find_parents() と find_parent()==== | ====find_parents() と find_parent()==== | ||
====find_next_siblings() と find_next_sibling()==== | ====find_next_siblings() と find_next_sibling()==== | ||
| 220行目: | 220行目: | ||
paraText = soup.find(text='This is paragraph ') | paraText = soup.find(text='This is paragraph ') | ||
paraText.findNextSiblings('b') | paraText.findNextSiblings('b') | ||
| − | # [ | + | # [<b>one</b>] |
paraText.findNextSibling(text = lambda(text): len(text) == 1) | paraText.findNextSibling(text = lambda(text): len(text) == 1) | ||
| 233行目: | 233行目: | ||
soup.select("body a") | soup.select("body a") | ||
====直下のタグ==== | ====直下のタグ==== | ||
| − | soup.select("head | + | soup.select("head > title") |
====CSS class==== | ====CSS class==== | ||
soup.select(".sister") | soup.select(".sister") | ||
| 253行目: | 253行目: | ||
tag.string = "New link text." | tag.string = "New link text." | ||
===append()=== | ===append()=== | ||
| − | soup = BeautifulSoup(" | + | soup = BeautifulSoup("<a>Foo</a>") |
soup.a.append("Bar") | soup.a.append("Bar") | ||
===BeautifulSoup.new_string() と .new_tag()=== | ===BeautifulSoup.new_string() と .new_tag()=== | ||
====new_string()==== | ====new_string()==== | ||
| − | soup = BeautifulSoup(" | + | soup = BeautifulSoup("<b></b>") |
tag = soup.b | tag = soup.b | ||
tag.append("Hello") | tag.append("Hello") | ||
| 263行目: | 263行目: | ||
tag.append(new_string) | tag.append(new_string) | ||
tag | tag | ||
| − | # | + | # <b>Hello there.</b> |
tag.contents | tag.contents | ||
# [u'Hello', u' there'] | # [u'Hello', u' there'] | ||
====new_tag()==== | ====new_tag()==== | ||
| − | soup = BeautifulSoup(" | + | soup = BeautifulSoup("<b></b>") |
original_tag = soup.b | original_tag = soup.b | ||
| 273行目: | 273行目: | ||
original_tag.append(new_tag) | original_tag.append(new_tag) | ||
original_tag | original_tag | ||
| − | # | + | # <b><a href="http://www.example.com"></a></b> |
new_tag.string = "Link text." | new_tag.string = "Link text." | ||
original_tag | original_tag | ||
| − | # | + | # <b><a href="http://www.example.com">Link text.</a></b> |
===insert()=== | ===insert()=== | ||
| − | markup = ' | + | markup = '<a href="http://example.com/">I linked to <i>example.com</i></a>' |
soup = BeautifulSoup(markup) | soup = BeautifulSoup(markup) | ||
tag = soup.a | tag = soup.a | ||
| 285行目: | 285行目: | ||
tag.insert(1, "but did not endorse ") | tag.insert(1, "but did not endorse ") | ||
tag | tag | ||
| − | # | + | # <a href="http://example.com/">I linked to but did not endorse <i>example.com</i></a> |
tag.contents | tag.contents | ||
| − | # [u'I linked to ', u'but did not endorse', | + | # [u'I linked to ', u'but did not endorse', <i>example.com</i>] |
===insert_before() と insert_after()=== | ===insert_before() と insert_after()=== | ||
===clear()=== | ===clear()=== | ||
| − | markup = ' | + | markup = '<a href="http://example.com/">I linked to <i>example.com</i></a>' |
soup = BeautifulSoup(markup) | soup = BeautifulSoup(markup) | ||
tag = soup.a | tag = soup.a | ||
| 296行目: | 296行目: | ||
tag.clear() | tag.clear() | ||
tag | tag | ||
| − | # | + | # <a href="http://example.com/"></a> |
===extract()=== | ===extract()=== | ||
*タグもしくは文字列をツリーから削除 | *タグもしくは文字列をツリーから削除 | ||
| − | markup = ' | + | markup = '<a href="http://example.com/">I linked to <i>example.com</i></a>' |
soup = BeautifulSoup(markup) | soup = BeautifulSoup(markup) | ||
a_tag = soup.a | a_tag = soup.a | ||
| 306行目: | 306行目: | ||
a_tag | a_tag | ||
| − | # | + | # <a href="http://example.com/">I linked to</a> |
i_tag | i_tag | ||
| − | # | + | # <i>example.com</i> |
===decompose()=== | ===decompose()=== | ||
*タグをツリーから取り除く | *タグをツリーから取り除く | ||
| − | markup = ' | + | markup = '<a href="http://example.com/">I linked to <i>example.com</i></a>' |
soup = BeautifulSoup(markup) | soup = BeautifulSoup(markup) | ||
a_tag = soup.a | a_tag = soup.a | ||
| 319行目: | 319行目: | ||
a_tag | a_tag | ||
| − | # | + | # <a href="http://example.com/">I linked to</a> |
===replace_with()=== | ===replace_with()=== | ||
*タグおよび文字列をツリーから取り除き、別のタグおよび文字列に置き換える | *タグおよび文字列をツリーから取り除き、別のタグおよび文字列に置き換える | ||
===wrap()=== | ===wrap()=== | ||
*要素をタグでラップする | *要素をタグでラップする | ||
| − | soup = BeautifulSoup(" | + | soup = BeautifulSoup("<p>I wish I was bold.</p>") |
soup.p.string.wrap(soup.new_tag("b")) | soup.p.string.wrap(soup.new_tag("b")) | ||
| − | # | + | # <b>I wish I was bold.</b> |
===unwrap()=== | ===unwrap()=== | ||
*タグをはがす | *タグをはがす | ||
| − | markup = ' | + | markup = '<a href="http://example.com/">I linked to <i>example.com</i></a>' |
soup = BeautifulSoup(markup) | soup = BeautifulSoup(markup) | ||
a_tag = soup.a | a_tag = soup.a | ||
| 335行目: | 335行目: | ||
a_tag.i.unwrap() | a_tag.i.unwrap() | ||
a_tag | a_tag | ||
| − | # | + | # <a href="http://example.com/">I linked to example.com</a> |
==出力== | ==出力== | ||
===Pretty-printing=== | ===Pretty-printing=== | ||
2020年2月15日 (土) 08:00時点における版
目次
- 1 Beautiful Soup (HTML XML解析)
- 2 インストール
- 3 Import
- 4 解析
- 5 オブジェクト
- 6 コメントと特殊な文字列
- 7 treeのナビゲート
- 7.1 下がる
- 7.2 上がる
- 7.3 横に移動
- 7.4 後ろ向き前向き
- 7.5 ツリーの検索
- 7.6 関数
- 7.7 CSS selectors
- 8 ツリーの操作
- 9 出力
- 10 例
Beautiful Soup (HTML XML解析)
インストール
PIPからインストール
# pip install BeautifulSoup
ダウンロードして解凍
piroto@eisai /cygdrive/c/Users/piroto/Downloads $ tar -xvf beautifulsoup4-4.1.2.tar.gz
インストール
$ cd beautifulsoup4-4.1.2 $ python setup.py install
パーサーのインストール
- Beautiful Soup は Pythonの標準ライブラリに含まれているHTML パーサーをサポートしています。
- その他にもサードパーティー製のパーサーもサポートしています。
- その一つが、lxmlパーサーで、以下の様にインストールできます。
$ apt-get install python-lxml $ easy_install lxml $ pip install lxml
- 以下の様なパーサーがあります
- Python 標準ライブラリのパーサー
- lxml HTMLパーサー
- lxml XMLパーサー
- html5lib
Import
from BeautifulSoup import BeautifulSoup # For processing HTML from BeautifulSoup import BeautifulStoneSoup # For processing XML import BeautifulSoup # To get everything
<blockquote>No module named BeautifulSoup エラーとなる場合</blockquote>
from bs4 import BeautifulSoup # To get everything
解析
- 文字列およびファイルハンドルによる文書解析
soup = BeautifulSoup(open("index.html"))
soup = BeautifulSoup("<html>data</html>")
- URLを指定して解析
import urllib2
from BeautifulSoup import BeautifulSoup
soup = BeautifulSoup(urllib2.urlopen('http://xxxxx.com'))
オブジェクト
- Beautiful Soup は複雑なHTML文書を、Python オブジェクトのツリーに変換する
- 以下の4種類のオブジェクトを扱うだけでよい
Tag
- XML、HTMLのタグに一致する
tag = soup.b
Name
- すべてのタグは、.name でアクセスできる名前を持つ
- タグの名称を変更すると、内容も変更される
tag.name
Attributes
- タグはいくつかの属性をもつ。
- 以下の様にアクセス可能
tag['class']
- .attrs で直接アクセスできる
- 追加、削除、変更ができる
tag['class'] = 'verybold' tag['id'] = 1 del tag['class'] del tag['id']
複数値属性
- HTML4では、いくつかの属性で、複数の値を持つことができる
- もっとも知られているのが、class
- Beautiful Soupでは、リストとして扱う
css_soup = BeautifulSoup('<p class="body strikeout"></p>')
css_soup.p['class']
# ["body", "strikeout"]
- XMLでは、複数値として扱わない
xml_soup = BeautifulSoup('<p class="body strikeout"></p>', 'xml')
xml_soup.p['class']
# u'body strikeout'
- 文字列は、Beautiful Soup で、NavigableStringを利用する
- Python のUnicode文字列とほぼ同じ
- treeをナビゲートしたり検索したりする機能がサポートされている
tag.string # u'Extremely bold' type(tag.string) # <class 'bs4.element.NavigableString'>
- unicode() で、Unicode 文字列に変換できる
unicode_string = unicode(tag.string) unicode_string # u'Extremely bold' type(unicode_string) # <type 'unicode'>
BeautifulSoup
- 文書全体を表す
- Tagオブジェクトとして文書を扱う
- .name は、特別に、"[document]"となる
コメントと特殊な文字列
コメント
- Commentオブジェクトは、NavigableStringの特殊型
markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>" soup = BeautifulSoup(markup) comment = soup.b.string type(comment) # <class 'bs4.element.Comment'>
treeのナビゲート
下がる
タグ名を使ったナビゲート
soup.head
soup.title
soup.find_all('a')
.contents と .children
head_tag.contents [<title>The Dormouse's story</title>]
for child in title_tag.children: print(child)
.descendants
- .contents および .children は、タグの直接の子供しか考慮していない
- ネストした子供を順次取り出す
for child in head_tag.descendants:
print(child)
# <title>The Dormouse's story</title>
# The Dormouse's story
.string
title_tag.string # u'The Dormouse's story'
.strings と stripped_strings
strings
for string in soup.strings:
print(repr(string))
# u"The Dormouse's story"
# u'\n\n'
# u"The Dormouse's story"
# u'\n\n'
stripped_strings
for string in soup.stripped_strings:
print(repr(string))
# u"The Dormouse's story"
# u"The Dormouse's story"
上がる
.parent
title_tag = soup.title title_tag # <title>The Dormouse's story</title> title_tag.parent # <head><title>The Dormouse's story</title></head>
.paretns
link = soup.a link # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a> for parent in link.parents: if parent is None: print(parent) else: print(parent.name) # p # body # html # [document] # None
横に移動
.next_sibling と .prebious_sibling
sibling_soup.b.next_sibling # <c>text2</c> sibling_soup.c.previous_sibling # <b>text1</b>
.next_siblings と .prebious_siblings
for sibling in soup.a.next_siblings:
print(repr(sibling))
for sibling in soup.find(id="link3").previous_siblings:
print(repr(sibling))
後ろ向き前向き
.next_element と .previous_element
.next_elements と .previous_elements
ツリーの検索
string
soup.find_all('b')
正規表現
import re
for tag in soup.find_all(re.compile("^b")):
print(tag.name)
# body
# b
リスト
soup.find_all(["a", "b"])
関数
findAll()
タグ名を渡す
soup.findAll('b')
正規表現を使う
import re
tagsStartingWithB = soup.findAll(re.compile('^b'))
リストまたは辞書を渡す(結果は同一だが後者が高速)
soup.findAll(['title', 'p'])
oup.findAll({'title' : True, 'p' : True})
Trueを渡すとすべてのタグを返す
allTags = soup.findAll(True)
一つの引数をもち真偽値を返す呼び出し可能オブジェクトを渡すとフィルタできる
soup.findAll(lambda tag: len(tag.attrs) == 2)
find()
- 結果が一つしかないと分かっている場合など、最後までスキャンする必要はない利用
find(name, attrs, recursive, string, **kwargs)
- 以下はほぼ同等
soup.find_all('title', limit=1)
# [<title>The Dormouse's story</title>]
soup.find('title')
# <title>The Dormouse's story</title>
CSSクラスで検索
soup.find("b", { "class" : "lime" })
# <b class="lime">Lime</b>
find_parents() と find_parent()
find_next_siblings() と find_next_sibling()
- あるオブジェクトのnextSiblingメンバー変数を辿り、指定したTagあるいはNavigableTextを集めてきます。
paraText = soup.find(text='This is paragraph ')
paraText.findNextSiblings('b')
# [<b>one</b>]
paraText.findNextSibling(text = lambda(text): len(text) == 1)
# u'.'
find_previous_siblings() と find_previous_sibling()
find_all_next() と find_next()
find_all_previous() と find_previous()
CSS selectors
タグ
soup.select("title")
配下のタグ
soup.select("body a")
直下のタグ
soup.select("head > title")
CSS class
soup.select(".sister")
ID
soup.select("#link1")
soup.select("a#link2")
属性
soup.select('a[href]')
属性値
soup.select('a[href="http://example.com/elsie"]')
ツリーの操作
タグ名と属性の変更
tag.name = "blockquote" tag['class'] = 'verybold' tag['id'] = 1 del tag['class'] del tag['id']
.stringの変更
tag.string = "New link text."
append()
soup = BeautifulSoup("<a>Foo</a>")
soup.a.append("Bar")
BeautifulSoup.new_string() と .new_tag()
new_string()
soup = BeautifulSoup("<b></b>")
tag = soup.b
tag.append("Hello")
new_string = soup.new_string(" there")
tag.append(new_string)
tag
# <b>Hello there.</b>
tag.contents
# [u'Hello', u' there']
new_tag()
soup = BeautifulSoup("<b></b>")
original_tag = soup.b
new_tag = soup.new_tag("a", href="http://www.example.com")
original_tag.append(new_tag)
original_tag
# <b><a href="http://www.example.com"></a></b>
new_tag.string = "Link text." original_tag # <b><a href="http://www.example.com">Link text.</a></b>
insert()
markup = '<a href="http://example.com/">I linked to <i>example.com</i></a>' soup = BeautifulSoup(markup) tag = soup.a tag.insert(1, "but did not endorse ") tag # <a href="http://example.com/">I linked to but did not endorse <i>example.com</i></a> tag.contents # [u'I linked to ', u'but did not endorse', <i>example.com</i>]
insert_before() と insert_after()
clear()
markup = '<a href="http://example.com/">I linked to <i>example.com</i></a>' soup = BeautifulSoup(markup) tag = soup.a tag.clear() tag # <a href="http://example.com/"></a>
extract()
- タグもしくは文字列をツリーから削除
markup = '<a href="http://example.com/">I linked to <i>example.com</i></a>' soup = BeautifulSoup(markup) a_tag = soup.a i_tag = soup.i.extract() a_tag # <a href="http://example.com/">I linked to</a> i_tag # <i>example.com</i>
decompose()
- タグをツリーから取り除く
markup = '<a href="http://example.com/">I linked to <i>example.com</i></a>' soup = BeautifulSoup(markup) a_tag = soup.a soup.i.decompose() a_tag # <a href="http://example.com/">I linked to</a>
replace_with()
- タグおよび文字列をツリーから取り除き、別のタグおよび文字列に置き換える
wrap()
- 要素をタグでラップする
soup = BeautifulSoup("<p>I wish I was bold.</p>")
soup.p.string.wrap(soup.new_tag("b"))
# <b>I wish I was bold.</b>
unwrap()
- タグをはがす
markup = '<a href="http://example.com/">I linked to <i>example.com</i></a>' soup = BeautifulSoup(markup) a_tag = soup.a a_tag.i.unwrap() a_tag # <a href="http://example.com/">I linked to example.com</a>
出力
Pretty-printing
prettify()
Non-pretty printing
unicode() もしくは str()を使う
XML
from BeautifulSoup import BeautifulStoneSoup
def get_translation(itemid):
ItemId から、訳語を取得する
url = r'http://btonic.est.co.jp/NetDic/NetDicV09.asmx/GetDicItemLite?Dic=EJdict&Item={0}&Loc=&Prof=XHTML'
url = url.format(itemid)
f = urllib2.urlopen(url)
soup = BeautifulStoneSoup(f.read())
#print soup.prettify()
try:
ret = soup.body('div')[1].text
except:
ret =
return ret
例
ページを解析し指定タグのテキストのみ取り出す
soup = BeautifulSoup(urllib2.urlopen(url))
for p in soup('p'):
print p.text
タグの文字列を取得する
soup = BeautifulSoup(urllib2.urlopen(url)) .join(soup.findAll(text=True))
必要なタグのみ解析する
tags = SoupStrainer(['title','img','h1','h2','h3','h4','h5','h6','p','meta','link']) soup = BeautifulSoup(urllib2.urlopen(url), parseOnlyThese=tags)
タグに囲まれた文字列値がある場合出力
soup = BeautifulSoup(urllib2.urlopen(url))
if hasattr(soup, "title") and hasattr(soup.title, "string"):
print soup.title.string
Image タグから リンクを抜き出す
soup = BeautifulSoup(urllib2.urlopen(url))
for tag in soup.findAll():
if tag.name == 'img':
print tag['src']
© 2006 矢木浩人