前提・実現したいこと
Python3.xにてBeautifulSoupを用い、以下のような構造のHTMLファイルから見出し, 本文をそれぞれ抽出したいと考えています。
HTML
1<h3>見出し1</h3> 2<p>本文1</p> 3<p>本文1</p> 4<p>本文1</p> 5<h3>見出し2</h3> 6<p>本文2</p> 7<p>本文2</p> 8<p>本文2</p> 9<h3>見出し3</h3> 10<p>本文3</p> 11<p>本文3</p> 12<p>本文3</p>
期待する出力
H3_list = [見出し1, 見出し2, 見出し3]
P_list = [本文1, 本文2, 本文3]
発生している問題・エラーメッセージ
見出しの抽出は、下記のコードで容易に可能なのですが、それぞれが独立していてブロック構造になっていない本文を抽出するコードが思いつかない状況です。
Python
1H3_list = html.find_all('h3')
追加質問(見出しのタグが複数有る場合に特定の見出しタグと関連する本文のみを抽出する)
追加の質問になります。
HTML
1<h3>見出し1</h3> 2<p>本文1</p> 3<p>本文1</p> 4<p>本文1</p> 5<h3>見出し2</h3> 6<p>本文2</p> 7<p>本文2</p> 8<p>本文2</p> 9<h3>見出し3</h3> 10<p>本文3</p> 11<p>本文3</p> 12<p>本文3</p> 13<h4>見出し4</h4> 14<p>本文4</p> 15<p>本文4</p> 16<p>本文4</p>
この場合、上記と同様の出力を行うためのコードについても併せてご回答いただけると幸いでございます。
お手数をおかけしますが、よろしくお願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
jun68yktさんとhayataka2049さんのコードを参考にさせてもらいました。
H3直後のPを検索してH3とPのリストを作成しています。
find_next_siblingsでH3と同じ兄弟要素のみにしています
python
1from bs4 import BeautifulSoup 2 3data = """ 4<!DOCTYPE html> 5<html lang="ja"> 6<head> 7 <meta charset="UTF-8"> 8 <title>test</title> 9</head> 10<body> 11 <h3>見出し1</h3> 12 <p>本文1-A</p> 13 <p>本文1-B</p> 14 <p>本文1-C</p> 15 <h3>見出し2</h3> 16 <p>本文2-A</p> 17 <p>本文2-B</p> 18 <p>本文2-C</p> 19 <h3>見出し3</h3> 20 <p>本文3-A</p> 21 <p>本文3-B</p> 22 <p>本文3-C</p> 23 <h4>見出し4</h4> 24 <p>本文4-A</p> 25 <p>本文4-B</p> 26 <p>本文4-C</p> 27</body> 28</html> 29""" 30h3_list = [] 31p_list = [] 32 33soup = BeautifulSoup(data, "html.parser") 34 35# H3直後のPを検索 36for h3_p in soup.select("h3 + p"): 37 38 # ひとつ前のH3タグを追加 39 h3_list.append(h3_p.find_previous_sibling("h3")) 40 41 # Pを追加 42 temp = [h3_p] 43 44 # 次のタグを検索 45 for tag in h3_p.find_next_siblings(): 46 47 # Pなら追加、P以外なら終了 48 if tag.name == "p": 49 temp.append(tag) 50 else: 51 break 52 53 # Pリストを追加 54 p_list.append(temp) 55 56print(h3_list) 57print(p_list)
上のだとH3の下にPがないと取れないので修正
python
1# H3を検索 2for h3 in soup.select("h3"): 3 4 # H3タグを追加 5 h3_list.append(h3) 6 p_list.append([]) 7 8 # 次のタグを検索 9 for tag in h3.find_next_siblings(): 10 11 # Pなら追加、P以外なら終了 12 if tag.name == "p": 13 p_list[-1].append(tag) 14 else: 15 break
投稿2018/10/22 14:56
編集2018/10/22 15:21総合スコア1286
0
ベストアンサー
こんにちは。
以下を作成し、Python 3.7, BeautifulSoup 4.6.3 にて実行してみました。
python
1from bs4 import BeautifulSoup 2 3html = ''' 4<!DOCTYPE html> 5<html lang="ja"> 6<head> 7 <meta charset="UTF-8"> 8 <title>test</title> 9</head> 10<body> 11 <h3>見出し1</h3> 12 <p>本文1-A</p> 13 <p>本文1-B</p> 14 <p>本文1-C</p> 15 <h3>見出し2</h3> 16 <p>本文2-A</p> 17 <p>本文2-B</p> 18 <p>本文2-C</p> 19 <h3>見出し3</h3> 20 <p>本文3-A</p> 21 <p>本文3-B</p> 22 <p>本文3-C</p> 23</body> 24</html> 25''' 26 27soup = BeautifulSoup(html, 'lxml') 28 29H3_list = soup.findAll('h3') 30P_list = [[] for _ in range(len(H3_list))] 31 32for i, h3 in enumerate(H3_list): 33 e = h3 34 while True: 35 e = e.findNext(['p', 'h3']) 36 if e is None or e.name == 'h3': 37 break 38 P_list[i].append(e) 39 40print(H3_list) 41print(P_list) 42
上記を実行すると、以下が表示されます。
[<h3>見出し1</h3>, <h3>見出し2</h3>, <h3>見出し3</h3>] [[<p>本文1-A</p>, <p>本文1-B</p>, <p>本文1-C</p>], [<p>本文2-A</p>, <p>本文2-B</p>, <p>本文2-C</p>], [<p>本文3-A</p>, <p>本文3-B</p>, <p>本文3-C</p>]]
追記
追加のご質問への回答となるコードは以下です。
python
1(削除しました。)
上記を実行すると以下が表示されます。
(削除しました)
追記2
python
1from bs4 import BeautifulSoup 2 3html = ''' 4<!DOCTYPE html> 5<html lang="ja"> 6<head> 7 <meta charset="UTF-8"> 8 <title>test</title> 9</head> 10<body> 11 <h3>見出し1</h3> 12 <p>本文1-A</p> 13 <p>本文1-B</p> 14 <p>本文1-C</p> 15 <h3>見出し2</h3> 16 <p>本文2-A</p> 17 <p>本文2-B</p> 18 <p>本文2-C</p> 19 <h3>見出し3</h3> 20 <p>本文3-A</p> 21 <p>本文3-B</p> 22 <p>本文3-C</p> 23 <h4>見出し4</h4> 24 <p>本文4-A</p> 25 <p>本文4-B</p> 26 <p>本文4-C</p> 27</body> 28</html> 29''' 30 31soup = BeautifulSoup(html, 'lxml') 32 33H3_list = soup.findAll('h3') 34P_list = [[] for _ in range(len(H3_list))] 35 36for i, e in enumerate(H3_list): 37 while True: 38 e = e.findNext(['p', 'h3', 'h4']) 39 if e is None or e.name != 'p': 40 break 41 P_list[i].append(e) 42 43print(H3_list) 44print(P_list)
上記を実行すると以下が表示されます。
[<h3>見出し1</h3>, <h3>見出し2</h3>, <h3>見出し3</h3>] [[<p>本文1-A</p>, <p>本文1-B</p>, <p>本文1-C</p>], [<p>本文2-A</p>, <p>本文2-B</p>, <p>本文2-C</p>], [<p>本文3-A</p>, <p>本文3-B</p>, <p>本文3-C</p>]]
投稿2018/10/21 15:04
編集2018/10/21 17:00総合スコア9058
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/10/21 16:32
2018/10/21 16:39
2018/10/21 16:49
2018/10/21 16:59
2018/10/21 17:34
2018/10/21 22:24
0
こういうのでどうでしょうか。
python
1from bs4 import BeautifulSoup 2 3data = """ 4<html> 5<body> 6<h3>見出し1</h3> 7<p>本文1</p> 8<p>本文1</p> 9<p>本文1</p> 10<h3>見出し2</h3> 11<p>本文2</p> 12<p>本文2</p> 13<p>本文2</p> 14<h3>見出し3</h3> 15<p>本文3</p> 16<p>本文3</p> 17<p>本文3</p> 18</body> 19</html> 20""" 21 22soup = BeautifulSoup(data) 23body = soup.find("body") 24 25h3_list = [] 26p_list = [] 27for tag in body.children: 28 if tag.name == "h3": 29 h3_list.append(tag) 30 p_list.append([]) 31 elif tag.name == "p": 32 p_list[-1].append(tag) 33 else: 34 pass 35 36print(h3_list) 37print(p_list) 38""" => 39[<h3>見出し1</h3>, <h3>見出し2</h3>, <h3>見出し3</h3>] 40[[<p>本文1</p>, <p>本文1</p>, <p>本文1</p>], [<p>本文2</p>, <p>本文2</p>, <p>本文2</p>], [<p>本文3</p>, <p>本文3</p>, <p>本文3</p>]] 41"""
投稿2018/10/21 14:30
総合スコア30933
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/10/24 11:49