質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.20%

h2内のリンクを取得したい。webスクレイピング

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,042

Yukiya025

score 80

 <h2> のテキストは取得できた! しかしリンクを取得する方法がわからない

Pythonを使ったwebスクレイピングで<h2> のテキストとそのリンクをcsvファイルで取得しようとしています。
<h2> のテキストは取得できたのですが、リンク (href) の中身(#id2など)を取得する方法がわかりません。

 望む結果

<h2> のテキストとリンクをcsvファイルで取得

0,(訳注)石鹸は食べられない¶,#id2
1,この文書について¶,#id3
...(略)

 <h2> の中身

<h2>(訳注)石鹸は食べられない<a class="headerlink" href="#id2" title="Permalink to this headline"></a></h2>
<h2>この文書について<a class="headerlink" href="#id3" title="Permalink to this headline"></a></h2


以下のような例もあるし、h2にhrefもあるのでhrefを取得する方法はあるはず。。。と思いつつもこけています。現在for文をひとつ使っているので、その中でリンク取得するのではないかと推測しているのですがうまくいきません(T_T)

for link in soup.find_all('a'):
    print(link.get('href'))

 現在のコード

# -*- coding: utf-8 -*-
from bs4 import BeautifulSoup
import requests
import csv

"""
csvファイルに<h2>のテキストとリンクを保存したい
"""
r = requests.get("http://kondou.com/BS4/index.html") 
soup_content = BeautifulSoup(r.content, "html.parser")

alltxt = soup_content.get_text()
with open('h2textlink.csv', 'w+',newline='',encoding='utf-8') as f:
    n = 0
    for subheading in soup_content.find_all('h2'):
        sh = subheading.get_text()

        writer = csv.writer(f, lineterminator='\n')
        writer.writerow([n, sh])
        n += 1
pass

 現在の出力結果

0,(訳注)石鹸は食べられない¶
1,この文書について¶
2,助けてほしいときは¶
3,インストール後の問題¶
4,パーサーのインストール¶
...(略)

 h2のテキストとリンク取得完了!

おかげさまでできました! (≧∀≦)

# -*- coding: utf-8 -*-
from bs4 import BeautifulSoup
import requests
import csv

"""
csvファイルに<h2>のテキストとリンクを保存
"""
r = requests.get("http://kondou.com/BS4/index.html") 
soup_content = BeautifulSoup(r.content, "html.parser")

alltxt = soup_content.get_text()
with open('h2textlink.csv', 'w+',newline='',encoding='utf-8') as f:
    writer = csv.writer(f, lineterminator='\n')
    std_link = 'http://kondou.com/BS4/'
    for n, subheading in enumerate(soup_content.find_all('h2')):
        sh = subheading.get_text()
        h2link = subheading.a['href']

        writer.writerow([n, sh, std_link + h2link])
pass

 コード実行結果

0,(訳注)石鹸は食べられない¶,http://kondou.com/BS4/#id2
1,この文書について¶,http://kondou.com/BS4/#id3
2,助けてほしいときは¶,http://kondou.com/BS4/#id5
3,インストール後の問題¶,http://kondou.com/BS4/#id9
...(略)
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

ドキュメント自体でスクレイピングの練習をするのは良いアイデアですね。

h3内のリンクを取得したい。

hrefは、h3内のaタグの属性ですから、次のように取得できます。

subheading.find('a')['href']

あるいは次のように書くこともできます。

subheading.a['href']

なお、writerオブジェクトはループ外で一回だけ生成すれば充分です。
変数nに関しても、enumerateを使うともうちょっとスマートに書けるでしょう。

コメントを受けて

(・_・) これはリンク先のドキュメント読んで、googleで「for文 enumerate」で検索したもののよく分からずでした。。。 ごめんなさいorz

こんなふうに使います。

for n, subheading in enumerate(soup_content.find_all('h2')):
    ...

こうすれば、n = 0 や n += 1 を排することができます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/28 18:53

    LouiS0616様、ありがとうございます(*≧∀≦) 助かりました!
    > writerオブジェクトはループ外で一回だけ生成すれば充分です。
    了解です^^/
    >変数nに関しても、enumerateを使うともうちょっとスマートに
    (・_・) これはリンク先のドキュメント読んで、googleで「for文 enumerate」で検索したもののよく分からずでした。。。 ごめんなさいorz

    キャンセル

  • 2018/08/28 18:58

    解決されたようで何よりです。
    enumerateの件について、少しだけ追記しておきました。

    キャンセル

  • 2018/08/28 19:17

    ありがとうございます(≧∀≦)!!! soup_content.find_all('h2')をごっそりenumerateの引数にするんですか∑o(*'o'*)o forに 2つ(nとsubheading)の引数? 指定できるなんてびっくりです (ノ*゚▽゚)ノ

    コード修正しました!

    せっかくなら関係のあるサイト&きちんとHTMLが整理されていそうなサイトをスクレイピングしようと思ってBeautifulSoup4のドキュメントに決めました:)

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.20%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる