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

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

新規登録して質問してみよう
ただいま回答率
85.48%
スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Chromium OS

Chromium OSは、Google社が提供するWebアプリケーションの動作に特化したOS、および開発プロジェクトを指します。Linuxディストリビューションとなっており、Chrome OSのオープンソース版です。

AWS Lambda

AWS Lambdaは、クラウド上でアプリを実行できるコンピューティングサービス。サーバーのプロビジョニングや管理を要せず複数のイベントに対してコードを実行します。カスタムロジック用いた他AWSサービスの拡張やAWSの規模やパフォーマンスを用いたバックエンドサービスを作成できます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

Q&A

解決済

2回答

2941閲覧

Lambda+seleniumでの不可解なエラー

Castella

総合スコア0

スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Chromium OS

Chromium OSは、Google社が提供するWebアプリケーションの動作に特化したOS、および開発プロジェクトを指します。Linuxディストリビューションとなっており、Chrome OSのオープンソース版です。

AWS Lambda

AWS Lambdaは、クラウド上でアプリを実行できるコンピューティングサービス。サーバーのプロビジョニングや管理を要せず複数のイベントに対してコードを実行します。カスタムロジック用いた他AWSサービスの拡張やAWSの規模やパフォーマンスを用いたバックエンドサービスを作成できます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

0グッド

0クリップ

投稿2021/11/05 06:13

前提・実現したいこと

AWS LambdaでIT用語のクローリング・スクレイピングを行い、PDFファイルにまとめるプログラムを作成しています。

仕様
・これは別のLambda関数から同期呼び出しを受けて動くプログラムです。
・別プログラムで得たjsonファイル(IT用語と推測されるキーフレーズ集)を取得します。
今回はデバッグ用に作った仮のファイルをS3からダウンロードして使用するものとします。
・入手したjsonファイルは該当箇所を抜き出してリスト型変数に格納されます。
・リスト型変数を使ってIT用語辞典から個別にキーフレーズを検索しキーフレーズの意味を辞書型で記録します。
・結果が存在しない、あるいは検索結果が不適切だった場合後程検索できるようにgoogleの検索結果URLを生成します。
・PDFファイルを生成し以上のことをぺージを分けて書き込みます。(こちらは動作することを確認したので今回は省略します)

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

検索したいキーフレーズである文字列(str)を検索窓にsend_keys()しているのにdict,つまり辞書型として認識されAttributeErorrが返ってきてしまいます。
こちらが該当する周辺の行です。

python

1 for ph in v: 2 input_element = driver.find_element_by_class_name("gsib_a") 3 input_element.send_keys(f"{ph}") #エラー箇所 4 input_element.send_keys(Keys.RETURN)

類似した症状が無いか検索をしたのですが私が見た限りではありませんでした。
しかもAnacondaの開発環境では問題なく動くことが分かっています。

有識者の中で類似の事例や解決策を知っている方どうかご教示願います。

エラー文全文

Executionresults

1Response 2{ 3 "errorMessage": "'dict' object has no attribute 'send_keys'", 4 "errorType": "AttributeError", 5 "stackTrace": [ 6 " File \"/var/task/lambda_function.py\", line 141, in lambda_handler\n input_element.send_keys(f\"{ph}\")\n" 7 ] 8} 9 10Function Logs 11START RequestId: (省略) Version: $LATEST 12a:[{'keyPhrases': ['デジタル・トランスフォーメーション時代', 'イノベーティブ', 'ソリューション', 'コンビタンス', '顧客管理', 'アジャイル', 'プロトタイプ開発', 'ローンチ', 'パートーナー', '価値創造', '当社', '事', '知識', 'スキル', 'グローバル', '多様性', 'ビジネス', '人財'], 'id': '1', 'warnings': []}] 13c:{'keyPhrases': ['デジタル・トランスフォーメーション時代', 'イノベーティブ', 'ソリューション', 'コンビタンス', '顧客管理', 'アジャイル', 'プロトタイプ開発', 'ローンチ', 'パートーナー', '価値創造', '当社', '事', '知識', 'スキル', 'グローバル', '多様性', 'ビジネス', '人財'], 'id': '1', 'warnings': []} 14v:['デジタル・トランスフォーメーション時代', 'イノベーティブ', 'ソリューション', 'コンビタンス', '顧客管理', 'アジャイル', 'プロトタイプ開発', 'ローンチ', 'パートーナー', '価値創造', '当社', '事', '知識', 'スキル', 'グローバル', '多様性', 'ビジネス', '人財'] 15デジタル・トランスフォーメーション時代 16イノベーティブ 17ソリューション 18コンビタンス 19顧客管理 20アジャイル 21プロトタイプ開発 22ローンチ 23パートーナー 24価値創造 25当社 2627知識 28スキル 29グローバル 30多様性 31ビジネス 32人財 33ph:デジタル・トランスフォーメーション時代 34変数型:<class 'str'> 35[ERROR] AttributeError: 'dict' object has no attribute 'send_keys' 36Traceback (most recent call last): 37  File "/var/task/lambda_function.py", line 141, in lambda_handler 38    input_element.send_keys(f"{ph}") 39END RequestId: (省略) 40REPORT RequestId: (省略) Duration: 19843.01 ms Billed Duration: 19844 ms Memory Size: 800 MB Max Memory Used: 581 MB 41

該当のソースコード(クローリング・スクレイピングまで)

Python

1from selenium import webdriver 2from selenium.webdriver import Chrome, ChromeOptions, Remote 3from selenium.webdriver.common.keys import Keys 4#import chromedriver_binary 5 6from reportlab.lib.units import mm 7from reportlab.pdfgen import canvas 8from reportlab.lib.pagesizes import A4, portrait 9from reportlab.pdfbase import pdfmetrics 10from reportlab.pdfbase.ttfonts import TTFont 11from reportlab.pdfbase.cidfonts import UnicodeCIDFont 12 13import urllib.parse 14import os 15import boto3 16import json 17import shutil 18import time 19 20#イメージファイルを/tmp/上に移動させるプログラム 21def move_bin( 22 fname: str, src_dir: str = "/var/task/bin", dest_dir: str = "/tmp/bin" 23) -> None: 24 if not os.path.exists(dest_dir): 25 os.makedirs(dest_dir) 26 dest_file = os.path.join(dest_dir, fname) 27 shutil.copy2(os.path.join(src_dir, fname), dest_file) 28 os.chmod(dest_file, 0o775) 29 30 31def lambda_handler(event,content): 32 33 s3 = boto3.client("s3") 34 bucket = event["bucket"] 35 now=event["time_stamp"] 36 37 move_bin("headless-chromium","/opt/headless/python/bin/") 38 move_bin("chromedriver","/opt/headless/python/bin/") 39 #Lambda上で動かすためのオプション 40 options = ChromeOptions() 41 options.add_argument("--headless") 42 options.add_argument("--disable-gpu") 43 options.add_argument("--hide-scrollbars") 44 options.add_argument("--single-process") 45 options.add_argument("--ignore-certificate-errors") 46 options.add_argument("--window-size=880x996") 47 options.add_argument("--no-sandbox") 48 options.add_argument("--homedir=/tmp") 49 options.binary_location = "/tmp/bin/headless-chromium" 50 driver = webdriver.Chrome("/tmp/bin/chromedriver",chrome_options=options) 51 52 #作業用ディレクトリを作成(/tmp/HHMMSS/) 53 work_dir="/tmp/"+now+"/" 54 if not os.path.exists(work_dir): 55 os.mkdir(work_dir) 56 57 #印字用フォントの設定(第1引数:フォント、第2引数:サイズ) 58 #フォントをS3から作業用ディレクトリに落とす(layerから落とすよう後程変更する) 59 s3.download_file(bucket,"meiryo.ttc",work_dir+"meiryo.ttc") 60 #フォントの読み込み 61 pdfmetrics.registerFont(TTFont("Meiryo", work_dir+"meiryo.ttc")) 62 #pdfmetrics.registerFont(TTFont("HGRGE", "./HGRME.TTC")) 63 64 #lambdaのディレクトリを取得 65 #lambdaの作業ディレクトリである/tmp/ディレクトリにパスを通す 66 file = "sample.pdf" 67 file_path =work_dir+file 68 69 #cc = canvas.Canvas(file) 70 71 #/tmp/HHMMSS/sample.pdf 72 73 #xに初期値を設定 74 x=40 #座標600が最大 75 y=800 #座標840が最大 76 s="" 77 78 #空のPDFファイルを作成 79 page = canvas.Canvas(file_path, pagesize=portrait(A4)) 80 81 d={} 82 83 #キーフレーズのファイルを読込 84 #デバッグ用jsonファイル 85 dummy_json_key ="Static_json/dummyjson" 86 s3.download_file(bucket,dummy_json_key,work_dir+"key.json") 87 88 with open (work_dir+"key.json",mode="r") as f: 89 d=json.load(f) 90 91 92 a=d["documents"[:]] 93 print(f"a:{a}") 94 c=a[0] 95 print(f"c:{c}") 96 v=c["keyPhrases"] 97 print(f"v:{v}") 98 99 for phrase in v: 100 print(phrase) 101 102 count=0 103 page.setFont("Meiryo", 20) 104 c=0 105 length=len(v) 106 page.setStrokeColorRGB(1.0, 0.0, 0.0) 107 108 # キーフレーズの意味検索 109 kp = 0 110 111 112 # IT用語辞典のトップ画面を開く。 113 driver.get('https://e-words.jp/') 114 time.sleep(5) 115 116 # タイトルにe-wordsが含まれていることを確認する。 117 assert 'IT用語辞典 e-Words' in driver.title 118 119 kaisetu_dict = {} 120 url_dict = {} 121 ph_dict = {} 122 kp = 0 123 u = 0 124 p = 0 125 126 ''' 127 文字化け確認用 128 driver.get_screenshot_as_file(work_dir+"check.png") 129 assertcheck=open(work_dir+"check.png","rb") 130 s3.put_object(Bucket=bucket,Key='check.png',Body=assertcheck) 131 assertcheck.close() 132 ''' 133 134 for ph in v: 135 input_element = driver.find_element_by_class_name("gsib_a") 136 input_element.send_keys(f"{ph}") 137 input_element.send_keys(Keys.RETURN) 138 time.sleep(5) 139 140 # タイトルにキーフレーズが含まれていることを確認する。 141 # assert 'python' in driver.title 142 143 # スクリーンショットを撮る。 144 #driver.save_screenshot('search_results.png') 145 146 # 検索結果を表示する。 147 for a in driver.find_elements_by_css_selector('main > div > div > div > div > div > div > div > div > div > div > div > div > div > div > a'): 148 # b = a.find_element_by_xpath('..') 149 # print(a.text) 150 b = a.get_attribute('href') 151 152 break 153 154 # 検索結果があった場合 155 kensaku = driver.find_elements_by_css_selector('main > div > div > div > div > div > div > div > div > div > div > div > div > div') 156 if kensaku[0].text != "一致する結果はありません": 157 158 # 一番上の検索結果を表示 159 driver.get(b) 160 time.sleep(5) 161 for c in driver.find_elements_by_css_selector('article > div > p'): 162 163 # 検索結果の吟味 164 cheak = ph in c.text 165 if cheak == False: 166 ph_dict[p] =ph 167 url = "https://www.google.com/search?q="+ph 168 url_dict[u] = url 169 u = u + 1 170 p = p + 1 171 print(url) 172 break 173 174 kaisetu = ph + ":" + c.text + "\n" 175 176 #辞書型配列を作る 177 kaisetu_dict[kp] = kaisetu 178 kp = kp + 1 179 print(kaisetu) 180 181 182 else: 183 driver.get('https://e-words.jp/') 184 time.sleep(1) 185 continue 186 187 driver.quit() # ブラウザーを終了する。 188(以下略)

試したこと

・適当な変数を用意し、(変数)=''.join(v)をした
・f文字列を使わずに表記した
・for文直前で明示的に宣言したりsend_keys()内でキャストしたりした
・変数を使わずsend_keys()内に直打ちをした
→いずれも同様のエラー

補足情報(FW/ツールのバージョンなど)

参考サイト
【Python】AWS Lambdaでheadless chrome+seleniumを実行する方法
AWS Lambdaで列車運行情報を定期的にLINEへ通知してみた【Python】
Selenium API(逆引き)

各環境
・開発環境
ANACONDA
Python3.6,3.7
Chrome(非ヘッドレスモード)
Chrome-driver
selenium
reportlab(割愛)

・本番環境
AWS Lambda
Python3.7
Headless-Chromium
Chrome-driver
selenium
reportlab(割愛)

Layers
Amazon cloud9からEC2を利用しzipフォルダを作成
・Headless(Headless-Chromium及び対応するChromedriver格納)
・MakeNote(seleniumとReportlabs格納)
・Fonts(.fonts格納)

環境変数
・HOME = /opt/

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

自己解決しました。
どうやら参考元のプログラムはSelenium3.141.0でないと動作しないようです。
私の環境ではSelenium4.0.0だったので変更したら動作するようになりました。

投稿2021/11/08 01:43

Castella

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

input_elementがdict(辞書)型であるとすればkeyを指定する必要があるのではないでしょうか?
こちらのサイトなど参考になれば

投稿2021/11/06 08:16

odataiki

総合スコア938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問