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

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

ただいまの
回答率

88.04%

指定URLのhtmlからhrefタグの中身を取り出したい(スクレイピング)

解決済

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 450

score 1

前提・実現したいこと

以下の朝日新聞のURLから「次の記事」と「前の記事」のURLを取り出したいです。
https://www.asahi.com/articles/DA3S14526484.html?iref=pc_rensai_article_long_16_prev

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

BeautifulSoup4を使って取り出そうとするのですが、select,find_allでも取り出すことができないです。
何か間違えますか?

該当のソースコード

import requests
from bs4 import BeautifulSoup

res = requests.get(url)
soup = BeautifulSoup(res.text, "html.parser")

prev = soup.select("#PrevLink > div > a").get("href")
next = souop.select("#PrevLink > div > a").get("href")

試したこと

lxmlのxpathや、find_allも試みましたがうまく取得することができませんでした。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

checkベストアンサー

+3

Seleniumを使うとこんなコードで取れました
参考:https://qiita.com/Azunyan1111/items/b161b998790b1db2ff7a

from bs4 import BeautifulSoup
import requests as re
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.set_headless(True)
driver = webdriver.Chrome(chrome_options=options)
driver.get("https://www.asahi.com/articles/DA3S14526484.html?iref=pc_rensai_article_long_16_prev")

html = driver.page_source.encode('utf-8')
soup = BeautifulSoup(html, "html.parser")
print(soup.find(id='NextLink').find('a')['href'])
print(soup.find(id='PrevLink').find('a')['href'])

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/06/29 08:38

    Seleniumと呼ばれるものを初めて知りました!ありがとうございます!

    キャンセル

+3

Selemium を使わない方法を紹介します。
今回の場合は BeautifulSoup4 も使いません。

目的の情報にたどり着くための調査方法

開発者ツール Network タブ

1
開発者ツールの Network タブを開きます


画面左上の検索ボックスで、目的の情報が表示されている DOM 要素に関係するキーワードで検索します
今回の場合は DOM の id "NextLink" で検索をかけています


検索の結果、ブラウザがリクエストしたコンテンツの中身が検索ボックスのすぐ下に表示されるので、
クリックします

4
すると、タイムラインの特定のリクエストの行が濃いグレーで表示されるので、
クリックします

5
[Preview] タブをクリックします

6
Ctrl + F で検索ボックスが表示されるので、再度 DOM 要素に関係するキーワードで検索し、
コードをねばり強く見ていきます

すると、いつかは目的の情報を取得している箇所が見つかります

コード

import re
import requests

# 現在のページの URL
url_current_page = "https://www.asahi.com/articles/DA3S14526484.html?iref=pc_rensai_article_long_16_prev"

# 連載の情報の URL
#
# 正確に URL を生成する場合は次のコードを参考に Python で書き直します (ここでは省略します)
# https://www.asahicom.jp/js/asahi-article.js 73行目
# this.rensaiJson = "/rensai/json/" + rensaiId +".json?" + Math.floor((new Date()).getTime() / (1000 * 60 * 60 * 4));//4h
url_page_list = "https://www.asahi.com/rensai/json/da16.json?110650"

# 記事 ID の取得処理
#
# 次のコードを参考に Python で書き直します:
# https://www.asahicom.jp/js/asahi-article.js 371 行目
# // 記事ID取得関数
# getKijiid:function(path,suffix){
#   let b = path.replace(/^.*[\/\\]/g, '');
#   if (typeof(suffix) == 'string' && b.substr(b.length - suffix.length) == suffix) {
#     b = b.substr(0, b.length - suffix.length);
#   }
# return b;
# },
path_current_page = re.sub(r'.*[\///]', '', url_current_page)
index_last = path_current_page.rfind(".html")
page_id_current = path_current_page[:index_last]
print(page_id_current)

# JSON をリクエストし、辞書型として取得
res_page_list = requests.get(url_page_list)
json = res_page_list.json()

# 直前のページ、直後のページ取得処理
# 
# 次のコードを参考に Python で書き直します:
# https://www.asahicom.jp/js/asahi-article.js 95 行目
# $.each(articleItems,function(i,data){
#   if(articleItems[i].id == articleId){
#     nowPage = articleItems[i];
#   }else{
#     if(nowPage){
#       prevPage = articleItems[i];
#       return false;
#     }else{
#       nextPage = articleItems[i];
#     }
#   }
# });
now_page = None
for item in json["items"]:
    # print(item)
    if item["id"] == page_id_current:
        now_page = item
    else:
        if now_page is not None:
            prev_page = item
            break
        if now_page is None:
            next_page = item

print(prev_page)
print(now_page)
print(next_page)

実行結果:

$ pipenv run python test.py
DA3S14526484
{'count': 1497, 'description': 'ちぐはぐな対応に不信を抱いた人も多いのではないか。政府の新型コロナウイルス対策に医学的見地から助言してきた専門家会議を廃止し、新たな会議体を設けると、おととい西村康稔担当相が表明した。改 
組することに異', 'id': 'DA3S14526483', 'image': None, 'limited': None, 'release_date': '20200626050000', 'title': '(社説)専門家会議\u3000最後の提言\u3000政府は胸に'}
{'count': 1498, 'description': '中国とインドとの長年に及ぶ国境問題が再燃している。ともに約14億人の人口を抱え、核兵器を保有する大国である。ぶつかり合えば、世界全体を揺るがしかねない。両国は最大限の自制に努めるべきだ。 
中国西部チベッ', 'id': 'DA3S14526484', 'image': None, 'limited': None, 'release_date': '20200626050000', 'title': '(社説)中国とインド\u3000成長大国の責任自覚を'}
{'count': 1499, 'description': '不透明さを批判されている政府事業の民間への委託について、問題の事業を所管する経済産業省が、有識者による改善策の検討を始めた。経産省が委託のやり方を見直すのは当然である。しかし委託契約は他 
の省庁でも行わ', 'id': 'DA3S14527841', 'image': None, 'limited': None, 'release_date': '20200627050000', 'title': '(社説)民間への委託\u3000統一ルールが必要だ'}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/06/29 08:37

    コード付きの解答ありがとうございます!

    キャンセル

+2

当該のリンクは元のソースには記載されておらず、ページ読み込み後javascirptで追加されています。
(res.textの内容を検索すれば#PrevLinkも存在しないことがわかります)
bs4で手軽に取得はできません。
Seleniumを使う方法なら取得できるかもしれませんね。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/06/29 08:37

    javascriptで後から追加されていたのですね。。。教えていただきありがとうございます!

    キャンセル

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

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

関連した質問

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