Beautiful-soup-navigating-by-tags
美しいスープ-タグでナビゲート
この章では、タグによるナビゲーションについて説明します。
以下は私たちのhtmlドキュメントです-
>>> html_doc = """
<html><head><title>Tutorials Point</title></head>
<body>
<p class="title"><b>The Biggest Online Tutorials Library, It's all Free</b></p>
<p class="prog">Top 5 most used Programming Languages are:
<a href="https://www.finddevguides.com/java/java_overview" class="prog" id="link1">Java</a>,
<a href="https://www.finddevguides.com/cprogramming/index" class="prog" id="link2">C</a>,
<a href="https://www.finddevguides.com/python/index" class="prog" id="link3">Python</a>,
<a href="https://www.finddevguides.com/javascript/javascript_overview" class="prog" id="link4">JavaScript</a> and
<a href="https://www.finddevguides.com/ruby/index" class="prog" id="link5">C</a>;
as per online survey.</p>
<p class="prog">Programming Languages</p>
"""
>>>
>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup(html_doc, 'html.parser')
>>>
上記のドキュメントに基づいて、ドキュメントの一部から別の部分への移動を試みます。
下っていく
HTMLドキュメントの要素の重要な要素の1つはタグです。これには、他のタグ/文字列(タグの子)が含まれる場合があります。 Beautiful Soupは、タグの子をナビゲートおよび反復するさまざまな方法を提供します。
タグ名を使用して移動する
解析ツリーを検索する最も簡単な方法は、名前でタグを検索することです。 <head>タグが必要な場合は、soup.headを使用します-
>>> soup.head
<head>&t;title>Tutorials Point</title></head>
>>> soup.title
<title>Tutorials Point</title>
<body>タグ内の特定のタグ(最初の<b>タグなど)を取得します。
>>> soup.body.b
<b>The Biggest Online Tutorials Library, It's all Free</b>
属性としてタグ名を使用すると、その名前の最初のタグのみが表示されます-
>>> soup.a
<a class="prog" href="https://www.finddevguides.com/java/java_overview" id="link1">Java</a>
すべてのタグの属性を取得するには、find_all()メソッドを使用できます-
>>> soup.find_all("a")
[<a class="prog" href="https://www.finddevguides.com/java/java_overview" id="link1">Java</a>, <a class="prog" href="https://www.finddevguides.com/cprogramming/index" id="link2">C</a>, <a class="prog" href="https://www.finddevguides.com/python/index" id="link3">Python</a>, <a class="prog" href="https://www.finddevguides.com/javascript/javascript_overview" id="link4">JavaScript</a>, <a class="prog" href="https://www.finddevguides.com/ruby/index" id="link5">C</a>]>>> soup.find_all("a")
[<a class="prog" href="https://www.finddevguides.com/java/java_overview" id="link1">Java</a>, <a class="prog" href="https://www.finddevguides.com/cprogramming/index" id="link2">C</a>, <a class="prog" href="https://www.finddevguides.com/python/index" id="link3">Python</a>, <a class="prog" href="https://www.finddevguides.com/javascript/javascript_overview" id="link4">JavaScript</a>, <a class="prog" href="https://www.finddevguides.com/ruby/index" id="link5">C</a>]
.contentsと.children
contentsでリスト内のタグの子を検索できます-.
>>> head_tag = soup.head
>>> head_tag
<head><title>Tutorials Point</title></head>
>>> Htag = soup.head
>>> Htag
<head><title>Tutorials Point</title></head>
>>>
>>> Htag.contents
[<title>Tutorials Point</title>
>>>
>>> Ttag = head_tag.contents[0]
>>> Ttag
<title>Tutorials Point</title>
>>> Ttag.contents
['Tutorials Point']
BeautifulSoupオブジェクト自体には子があります。 この場合、<html>タグはBeautifulSoupオブジェクトの子です-
>>> len(soup.contents)
2
>>> soup.contents[1].name
'html'
文字列には何も含めることができないため、.contentsはありません-
>>> text = Ttag.contents[0]
>>> text.contents
self.__class__.__name__, attr))
AttributeError: 'NavigableString' object has no attribute 'contents'
それらをリストとして取得する代わりに、.childrenジェネレーターを使用してタグの子にアクセスします-
>>> for child in Ttag.children:
print(child)
Tutorials Point
。子孫
descendants属性を使用すると、タグのすべての子を反復的に反復できます-.
その直接の子とその直接の子の子など-
>>> for child in Htag.descendants:
print(child)
<title>Tutorials Point</title>
Tutorials Point
<head>タグには子が1つだけありますが、子孫は<title>タグと<title>タグの子の2つです。 beautifulsoupオブジェクトには直接の子(<html>タグ)は1つしかありませんが、子孫はたくさんあります-
>>> len(list(soup.children))
2
>>> len(list(soup.descendants))
33
。ストリング
タグに子が1つだけあり、その子がNavigableStringである場合、子は.stringとして利用可能になります-
>>> Ttag.string
'Tutorials Point'
タグの唯一の子が別のタグであり、そのタグに.stringがある場合、親タグはその子と同じ.stringを持つと見なされます-
>>> Htag.contents
[<title>Tutorials Point</title>]
>>>
>>> Htag.string
'Tutorials Point'
ただし、タグに複数のものが含まれている場合、.stringの参照先が明確でないため、.stringはNoneに定義されています-
>>> print(soupl.string)
None
.stringsおよびstripped_strings
タグ内に複数のものが存在する場合でも、文字列だけを見ることができます。 .stringsジェネレータを使用します-
>>> for string in soup.strings:
print(repr(string))
'\n'
'Tutorials Point'
'\n'
'\n'
"The Biggest Online Tutorials Library, It's all Free"
'\n'
'Top 5 most used Programming Languages are: \n'
'Java'
',\n'
'C'
',\n'
'Python'
',\n'
'JavaScript'
' and\n'
'C'
';\n \nas per online survey.'
'\n'
'Programming Languages'
'\n'
余分な空白を削除するには、.stripped_stringsジェネレータを使用します-
>>> for string in soup.stripped_strings:
print(repr(string))
'Tutorials Point'
"The Biggest Online Tutorials Library, It's all Free"
'Top 5 most used Programming Languages are:'
'Java'
','
'C'
','
'Python'
','
'JavaScript'
'and'
'C'
';\n \nas per online survey.'
'Programming Languages'
上がっていく
「家系図」の類推では、すべてのタグとすべての文字列に親があります。それを含むタグ:
。親
要素の親要素にアクセスするには、.parent属性を使用します。
>>> Ttag = soup.title
>>> Ttag
<title>Tutorials Point</title>
>>> Ttag.parent
<head>title>Tutorials Point</title></head>
私たちのhtml_docでは、タイトル文字列自体に親があります。それを含む<title>タグが
>>> Ttag.string.parent
<title>Tutorials Point</title>
<html>のようなトップレベルのタグの親はBeautifulsoupオブジェクト自体です-
>>> htmltag = soupl
>>> type(htmltag.parent)
<class 'bs4.BeautifulSoup'>
Beautifulsoupオブジェクトの.parentはなしとして定義されています-
>>> print(soup.parent)
None
。親
すべての親要素を反復するには、.parents属性を使用します。
>>> link = soup.a
>>> link
<a class="prog" href="https://www.finddevguides.com/java/java_overview" id="link1">Java</a>
>>>
>>> for parent in link.parents:
if parent is None:
print(parent)
else:
print(parent.name)
p
body
html
[document]
横向き
以下は1つの簡単なドキュメントです-
>>> sibling_soup = BeautifulSoup("<a><b>finddevguides</b><c><strong>The Biggest Online Tutorials Library, It's all Free</strong></b></a>")
>>> print(sibling_soup.prettify())
<html>
<body>
<a>
<b>
finddevguides
</b>
<c>
<strong>
The Biggest Online Tutorials Library, It's all Free
</strong>
</c>
</a>
</body>
</html>
上記のドキュメントでは、<b>タグと<c>タグは同じレベルにあり、どちらも同じタグの子です。 <b>タグと<c>タグはどちらも兄弟です。
.next_siblingおよび.previous_sibling
next_siblingおよび.previous_siblingを使用して、解析ツリーの同じレベルにあるページ要素間を移動します。.
>>> sibling_soup.b.next_sibling
<c><strong>The Biggest Online Tutorials Library, It's all Free</strong></c>
>>>
>>> sibling_soup.c.previous_sibling
<b>finddevguides</b>
<b>タグには.next_siblingがありますが、.previous_siblingはありません。これは、ツリーの同じレベルの<b>タグの前には何もないため、同じケースが<c>タグの場合です。
>>> print(sibling_soup.b.previous_sibling)
None
>>> print(sibling_soup.c.next_sibling)
None
2つの文字列は同じ親を持っていないため、兄弟ではありません。
>>> sibling_soup.b.string
'finddevguides'
>>>
>>> print(sibling_soup.b.string.next_sibling)
None
.next_siblingsおよび.previous_siblings
タグの兄弟を反復するには、.next_siblingsと.previous_siblingsを使用します。
>>> for sibling in soup.a.next_siblings:
print(repr(sibling))
',\n'
<a class="prog" href="https://www.finddevguides.com/cprogramming/index" id="link2">C</a>
',\n'
>a class="prog" href="https://www.finddevguides.com/python/index" id="link3">Python</a>
',\n'
<a class="prog" href="https://www.finddevguides.com/javascript/javascript_overview" id="link4">JavaScript</a>
' and\n'
<a class="prog" href="https://www.finddevguides.com/ruby/index"
id="link5">C</a>
';\n \nas per online survey.'
>>> for sibling in soup.find(id="link3").previous_siblings:
print(repr(sibling))
',\n'
<a class="prog" href="https://www.finddevguides.com/cprogramming/index" id="link2">C</a>
',\n'
<a class="prog" href="https://www.finddevguides.com/java/java_overview" id="link1">Java</a>
'Top 5 most used Programming Languages are: \n'
行き来する
ここで、前の「html_doc」の例の最初の2行に戻りましょう-
&t;html><head><title>Tutorials Point</title></head>
<body>
<h4 class="tagLine"><b>The Biggest Online Tutorials Library, It's all Free</b></h4>
HTMLパーサーは、上記の文字列を受け取り、「<html>タグを開く」、「<head>タグを開く」、「<title>タグを開く」、「文字列を追加する」などの一連のイベントに変換します。 「</title>タグを閉じる」、「</head>タグを閉じる」、「<h4>タグを開く」などです。 BeautifulSoupは、ドキュメントの初期解析を再構築するためのさまざまな方法を提供します。
.next_elementおよび.previous_element
タグまたは文字列の.next_element属性は、直後に解析されたものを指します。 .next_siblingに似ていることもありますが、完全に同じではありません。 以下は、「html_doc」サンプルドキュメントの最後の<a>タグです。
>>> last_a_tag = soup.find("a", id="link5")
>>> last_a_tag
<a class="prog" href="https://www.finddevguides.com/ruby/index" id="link5">C</a>
>>> last_a_tag.next_sibling
';\n \nas per online survey.'
ただし、<a>タグの直後に解析された<a>タグの.next_elementは、その文の残りの部分ではありません。それは単語「C」です。
>>> last_a_tag.next_element
'C'
上記の動作は、元のマークアップでは、セミコロンの前に文字「C」が表示されていたためです。 パーサーは、<a>タグ、次に文字「C」、次に終了</a>タグ、次にセミコロンと文の残りの部分を検出しました。 セミコロンは<a>タグと同じレベルにありますが、文字「C」が最初にありました。
previous_element属性は、.next_elementの正反対です。 この要素の直前に解析された要素を指します。.
>>> last_a_tag.previous_element
' and\n'
>>>
>>> last_a_tag.previous_element.next_element
<a class="prog" href="https://www.finddevguides.com/ruby/index" id="link5">C</a>
.next_elementsおよび.previous_elements
これらのイテレータを使用して、要素に前後に移動します。
>>> for element in last_a_tag.next_e lements:
print(repr(element))
'C'
';\n \nas per online survey.'
'\n'
<p class="prog">Programming Languages</p>
'Programming Languages'
'\n'