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

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

ただいまの
回答率

88.11%

スクレイピングしたaタグのhref値を取得しようとするとKeyError

解決済

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 9,715

score 11

前提・実現したいこと

Pythonでスクレイピングをする、というQiitaのページを参考に
Webページ内のaタグのhref値を表示するコードを書きました。
参考コードの対象URLにアクセスした場合は正しく動くのですが
別のサイトにアクセスするよう書き換えたところエラーが出て動かなくなってしまいました。

1.問題の起こる原因
2.回避方法(事前の判別方法)
を、教えていただきたいです。

参考コード

import urllib.request
from bs4 import BeautifulSoup

url = "https://qiita.com/chanmaru"
res = urllib.request.urlopen(url)
soup = soup = BeautifulSoup(res, 'html.parser')

a_list = soup.findAll("a")
for a in a_list:
    href = a.attrs['href']
    print(a.string, '-->', href)

自分が書いたコード

import requests
from bs4 import BeautifulSoup

#対象URL(気象庁アメダス)
URL = "http://www.jma.go.jp/jp/amedas_h/today-44132.html?areaCode=000&groupCode=30"

#リソースを開く
res = requests.get(URL)

#取得したデータ(テキスト形式)でインスタンス作成
#soup = BeautifulSoup(res.text, 'html.parser')
#obj.textで渡すと文字化けするのでobj.contentで渡すようにする
soup = BeautifulSoup(res.content, 'html.parser')
#多分html.parserを省略して以下のように書いても動く
#soup = BeautifulSoup(res.content)

#a要素を全て取得
a_list = soup.find_all("a")

#find_all()はリストを出力するのでfor文で1要素ずつ値を出力
for a in a_list:
    #取得したaタグを表示
    #print(a.string)

    #aタグのhref属性値を抽出する
    href = a.attrs['href']
    #aタグの文字列と、そこからリンクしているURLを表示
    print(a.string, '-->', href)

発生している問題・エラーメッセージ

例外が発生しました: KeyError
'href'
...(ファイルパス略)
    href = a.attrs['href']

試したこと

対象URLを何度か変更してみて、問題が起こったときに該当箇所のhtmlを見ると、
aタグにhref値が設定されていないことが原因のようでした。(合っているかは解りません)
また、その通りだとした場合、href値が存在するなら取得/しなければ取得せず次の処理へ、という
分岐を行いたいのですがどうやって判別すれば良いのかも解りません。
試しにif a.attrs['href']:とか書いてみましたが同じエラーが出るだけでした…

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+3

要素 in 辞書で、辞書に要素が含まれるかが判断できます。
以下のように修正ください。

    # 略
    if 'href' in a.attrs:
        #aタグのhref属性値を抽出する
        href = a.attrs['href']

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/01/31 10:13

    in演算子を使えば良かったのですね。
    存在しないhref値にアクセスしようとしたことがエラーの原因、という認識でよろしいでしょうか。
    ありがとうございました。

    キャンセル

  • 2019/01/31 10:27

    > 存在しないhref値にアクセスしようとしたことがエラーの原因、という認識でよろしいでしょうか。
    はい。そのとおりです。KeyError=辞書(a.attrs)にキー(href)が存在しない

    キャンセル

  • 2019/01/31 19:26

    重ねてありがとうございます。

    キャンセル

0

a.get('href')

でしたらなければNoneが返ってきます

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

同じタグがついた質問を見る