指定したURLのプレビューボタンをクリックしPDFをダウンロードするpythonコードの作成(失敗編)

指定したURLのプレビューボタンをクリックしPDFをダウンロードするpythonコードの作成

amazonS3からファイルの取得はできたけど
動的サイトからのリンク取得はこの方法ではできなかった

以下ログ

指定したURLにアクセスし
プレビューと書かれたボタンをクリック、表示されるPDFファイルをダウンロードするpythonコード

chatGPTで作成していく

pip install requests beautifulsoup4

で必要ライブラリのインストール

import requests
from bs4 import BeautifulSoup

# ステップ2: 指定されたURLにGETリクエストを送信し、HTMLを取得
url = "https://任意のURL"
response = requests.get(url)
html = response.content

# ステップ3: BeautifulSoupを使用してHTMLを解析し、プレビューボタンのリンクを見つける
soup = BeautifulSoup(html, 'html.parser')
preview_button = soup.find('a', text='プレビュー')  # ここではaタグでテキストが'プレビュー'の要素を探していますが、実際の構造に応じて変更する必要があります。

# ステップ4: プレビューボタンのリンクを取得し、PDFファイルをダウンロード
if preview_button:
    pdf_url = preview_button['href']  # href属性からPDFのURLを取得
    pdf_response = requests.get(pdf_url)
    with open('document.pdf', 'wb') as f:
        f.write(pdf_response.content)
    print("PDFファイルがダウンロードされました。")
else:
    print("プレビューボタンが見つかりませんでした。")

で実行したが

/Users/snowpool/aw10s/mail_auto/get_pdf.py:11: DeprecationWarning: The 'text' argument to find()-type methods is deprecated. Use 'string' instead.
  preview_button = soup.find('a', text='プレビュー')  # ここではaタグでテキストが'プレビュー'の要素を探していますが、実際の構造に応じて変更する必要があります。
プレビューボタンが見つかりませんでした。

となる

ChatGPTでこの結果を調べると

警告メッセージに基づき、text引数の代わりにstring引数を使用する必要があります。また、プレビューボタンが見つからなかった問題に関しては、ページのHTML構造を確認せずに正確な解決策を提供するのは難しいですが、一般的なアドバイスをいくつか提供できます。
* 		string引数の使用: findメソッドでtextの代わりにstringを使用してみてください。
* 		正しい要素を特定する: プレビューボタンを特定するために、ページのHTMLソースを確認し、ボタンの正確なタグ名、クラス名、またはIDを特定します。この情報を元に、findまたはfind_allメソッドを適切に使用してください。
* 		動的コンテンツの考慮: もしプレビューボタンがJavaScriptによって動的に生成されている場合、requestsとBeautifulSoupだけでは取得できないかもしれません。この場合は、seleniumのようなブラウザ自動化ツールを使用して実際のブラウザセッションを介してページを読み込み、要素を探す必要があります。

となる

以下は、string引数を使用した修正されたコードの例

import requests
from bs4 import BeautifulSoup

# ステップ2: 指定されたURLにGETリクエストを送信し、HTMLを取得
url = "https://任意のURL"
response = requests.get(url)
html = response.content

# ステップ3: BeautifulSoupを使用してHTMLを解析し、プレビューボタンのリンクを見つける
soup = BeautifulSoup(html, 'html.parser')
preview_button = soup.find('a', string='プレビュー')  # `text`の代わりに`string`を使用

# ステップ4: プレビューボタンのリンクを取得し、PDFファイルをダウンロード
if preview_button:
    pdf_url = preview_button['href']  # href属性からPDFのURLを取得
    pdf_response = requests.get(pdf_url)
    with open('document.pdf', 'wb') as f:
        f.write(pdf_response.content)
    print("PDFファイルがダウンロードされました。")
else:
    print("プレビューボタンが見つかりませんでした。")

でもだめ

seleniumで取得してみる

pip install selenium


seleniumをインストール

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
import time

# Chromeのダウンロード設定
chrome_options = Options()
prefs = {
    "download.default_directory": "/path/to/download/directory",  # ダウンロードフォルダーのパスを設定
    "download.prompt_for_download": False,  # ダウンロード前に確認を求めない
    "download.directory_upgrade": True,
    "plugins.always_open_pdf_externally": True  # PDFファイルを自動的にダウンロード
}
chrome_options.add_experimental_option("prefs", prefs)

# Chrome WebDriverのパス
webdriver_path = '/path/to/chromedriver'  # ChromeDriverのパス

# WebDriverサービスを設定
service = Service(webdriver_path)

# WebDriverの初期化
driver = webdriver.Chrome(service=service, options=chrome_options)

# Webページにアクセス
driver.get("https://任意のURL")

# プレビューボタンを探してクリック(要素のXPathを使用)
# 実際のボタンのXPathに応じて調整してください
try:
    preview_button = driver.find_element(By.XPATH, '//button[contains(text(),"プレビュー")]')
    preview_button.click()
    time.sleep(5)  # ダウンロード完了を待つ
except Exception as e:
    print("エラーが発生しました:", e)

# ブラウザを閉じる
driver.quit()

でもだめ

ならば chrome developer tools で一度サイトの構成を調べる

<a href="https://s3.ap-northeast-1.amazonaws.com/storage.cocoo.education/ファイルの保存先" target="_blank">プレビュー</a>

となっていたが
これの構成で seleniumでダウンロードしようとしてもエラー

なので

import requests

# PDFファイルのURL
pdf_url = "https://s3.ap-northeast-1.amazonaws.com/storage.cocoo.education/ファイルの保存先"

# リクエストを送信してPDFファイルを取得
response = requests.get(pdf_url)

# レスポンスのステータスコードが200(成功)の場合、ファイルを保存
if response.status_code == 200:
    with open("downloaded_file.pdf", "wb") as file:
        file.write(response.content)
    print("PDFファイルが正常にダウンロードされました。")
else:
    print(f"ファイルのダウンロードに失敗しました。ステータスコード: {response.status_code}")

として直接リンクのURLからファイルを取得

これは成功

なので、
GMAILからリンクURLを抜き出しサイトへアクセスする機能
次にそのページからリンクボタンのURLを抜き出す機能
最後にPDFをダウンロードする機能
と分けて作成する

import requests
from bs4 import BeautifulSoup

# 初期ページのURL
initial_url = "https://任意のURL"

# 初期ページからHTMLを取得
response = requests.get(initial_url)
html = response.content

# HTMLを解析
soup = BeautifulSoup(html, 'html.parser')

# 'プレビュー'リンクを探す
preview_link = soup.find('a', text='プレビュー')
if preview_link:
    href_value = preview_link['href']
    print("プレビューのリンク:", href_value)
else:
    print("プレビューリンクが見つかりませんでした。")

しかし

/Users/snowpool/aw10s/mail_auto/get_pdf_url.py:15: DeprecationWarning: The 'text' argument to find()-type methods is deprecated. Use 'string' instead.
  preview_link = soup.find('a', text='プレビュー')
プレビューリンクが見つかりませんでした。

となる

このため
BeautifulSoupの最新バージョンでは、findメソッド(および関連メソッド)でtext引数の代わりにstring引数を使用するよう推奨
とのことのため

import requests
from bs4 import BeautifulSoup

# 初期ページのURL
initial_url = "https://任意のURL"

# 初期ページからHTMLを取得
response = requests.get(initial_url)
html = response.content

# HTMLを解析
soup = BeautifulSoup(html, 'html.parser')

# 'プレビュー'リンクを探す('string'引数を使用)
preview_link = soup.find('a', string='プレビュー')
if preview_link:
    href_value = preview_link['href']
    print("プレビューのリンク:", href_value)
else:
    # 'プレビュー'を含むテキストを持つリンクを探す場合の代替手段
    preview_links = soup.find_all('a')
    for link in preview_links:
        if 'プレビュー' in link.text:
            print("プレビューのリンク:", link['href'])
            break
    else:
        print("プレビューリンクが見つかりませんでした。")

へ変更したが

プレビューリンクが見つかりませんでした。
となる

webページの構造が予想と異なるか、リンクが動的に生成されている可能性があり
のようなケースでは、ブラウザの自動操作が可能なSeleniumのようなツールを使用する必要がある

念の為Javascriptで書かれているかチェック

import requests
from bs4 import BeautifulSoup

# 初期ページのURL
initial_url = "https://任意のURL"

# 初期ページからHTMLを取得
response = requests.get(initial_url)
html = response.content

# HTMLを解析
soup = BeautifulSoup(html, 'html.parser')

# ページ内のすべてのaタグを探索
links = soup.find_all('a')
found = False
for link in links:
    if link.text and 'プレビュー' in link.text:
        print("プレビューのリンク:", link['href'])
        found = True
        break

if not found:
    print("プレビューリンクが見つかりませんでした。")

の結果

プレビューリンクが見つかりませんでした

となったため
Seleniumを使うことにする

seleniumを使うにはwebdriverが必要

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です