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

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

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

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

Python

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

selenium

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

Q&A

解決済

1回答

1195閲覧

Pythonのスクレイピングで画像をダウンロードできない

fullmoon311

総合スコア62

スクレイピング

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

Python

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

selenium

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

0グッド

0クリップ

投稿2022/12/18 13:15

編集2022/12/18 13:50

前提

あるサイトをスクレイピングしているのですが、その中で画像もダウンロードさせるような処理を入れたいのですが、img src="" のsrcの中身がxxx.jsp?key=atai となっているためダウンロード出来ません。
ダウンロードは不可能でしょうか?何か方法はありますか?

ちなみに出来れば、ダウンロードせずに画像認識させて読み取った文字を文字列としてcsvに書き込む処理をしたいです。
個別ではPCに手動で画像を保存したものを画像認識させて、文字列として返すことに成功しております。

実現したいこと

ここに実現したいことを箇条書きで書いてください。

  • ▲▲機能を動作するようにする

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

例外が発生しました: UnidentifiedImageError cannot identify image file <_io.BytesIO object at 0x0000023644506BB0>

該当のソースコード

python

1# 1.動的サイトにアクセス 2url = "https://www.xxx/aaa/page" 3driver.get(url) 4 5# クリック前のハンドルリスト 6handles_befor = driver.window_handles 7 8# ドロップダウンを選択する 9# 分類 10genres = driver.find_element(By.NAME,'searchCategory') 11select1 = Select(genres) 12all_options = select1.options 13count = len(all_options) 14 15 16# [検索]ボタン押す 17driver.find_element(By.ID,'search').click() 18# メーカー毎の商品リストをfor文で回しながら取得 19pages = driver.find_element(By.XPATH, '//*[@id="fm"]/div[2]/span[2]') 20# ページャー数分、回す 21pagenum = pages.text 22for num in range(int(pagenum)): 23 # tbodyの中身取得 24 tbody = driver.find_element(By.XPATH,'//*[@id="xxx_list"]/table/tbody') 25 trlist = tbody.find_elements(By.TAG_NAME,'tr') 26 27 trnum = str(1) 28 for tr in trlist: 29 tdlist = tr.find_elements(By.TAG_NAME,'td') 30 trtext = [] 31 for td in tdlist: 32 test = td.text 33 if(test == '選ぶ'): 34 break 35 trtext.append(test) 36 # 1アイテム毎にCSVに書き込む 37 filename = "xxx.csv" 38 with open(filename, mode="a", encoding="utf-8") as f: 39 trs = ','.join(trtext) 40 f.write(trs) 41 # 改行コード 42 f.write('\n') 43 time.sleep(2) 44 #[選ぶ]をクリック 45 imgxpath = '//*[@id="result_list"]/table/tbody/tr['+ trnum +']/td[5]/a' 46 driver.find_element(By.XPATH, imgxpath).click() 47 # 画像URL取得 48 img = driver.find_element(By.XPATH,'//*[@id="aaa"]/p/img') 49 src = img.get_attribute('src') 50 #imgurlをダウンロード 51 if src: 52 src = urljoin(url, src) 53 # 画像のバイト列取得 54 img_content = requests.get(src).content 55 # 画像に変換 56 img_file = io.BytesIO(img_content) 57 # 画像の表示 ここでエラー発生 58 img_open = Image.open(img_file) 59 # 画像の保存 60 img_open.save(f'{trnum}_{trtext[2]}.png') 61

試したこと

ここに問題に対して試したことを記載してください。

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

ここにより詳細な情報を記載してください。

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

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

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

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

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

melian

2022/12/18 13:31

質問のコードでは省かれていますが、おそらく、以下の様な処理があるのだと思います。 url = 'https://...' driver.get(url) ここで、url がスクレイピング対象の URL だとすると、urljoin を使うことで正規化された URL を取得することができます。 from urllib.parse import urljoin src = img.get_attribute('src') #imgurlをダウンロード if src:  src = urljoin(url, src)   :
fullmoon311

2022/12/18 13:40

すみません。 driver.get()では、画像URLではなく検索ボタン押す前のURLとなっております。 src が 画像URLとなっており、 このsrcの中身が""aaa/bb/xx.jsp?key=atai" という風になっております。
melian

2022/12/18 13:45

ページ移動はしていないので、 url = "https://www.xxx/aaa/page" としておいて urljoin を実行すればよいかと思います。
fullmoon311

2022/12/18 13:52

ありがとうございます。 urlと定義し、 if src: src = urljoin(url, src) としましたが、やはり同じところでエラーが発生いたします。 img_open = Image.open(img_file) ←ここで発生
melian

2022/12/18 14:10

なるほど、src の中身の URL はもともと正規化されている形式なのですね。そうなりますと、urljoin の処理は不要になります。原因としては、ダウンロードしたファイルは画像ではないか、Pillow では認識できないフォーマットの画像という事になりそうです。
fullmoon311

2022/12/18 14:13

ちなみにoctoparseというツールでダウンロードさせたところ、確かにダウンロード出来たものの画像とは認識されませんでした。 これは実現は出来ないもので、あきらめた方が良いでしょうか?
fullmoon311

2022/12/18 14:14 編集

手動で画像をマウスでドラッグしたら、pngで保存され、これ自体の画像認識は出来ました。
melian

2022/12/18 14:21

正確な URL を教えてもらえるのであれば、こちらで動作確認できるのですが、どうしますか?
fullmoon311

2022/12/18 14:47 編集

プライバシーにかかわるので避けたいのですが、あとで削除してもよいでしょうか? URLは下記です。 xxx 画像は検索後に出てくる「選ぶ」ボタンとなります。 そのあとの金額の画像6,000円という画像を文字列としてcsvに保存したいです。 まずはダウンロードできるか試していました。
melian

2022/12/18 14:34

ありがとうございます、削除していただいて構いません。こちらで動作確認します。
fullmoon311

2022/12/18 14:48

ありがとうございます。削除リクエストとなりましたので、伏せました。 お手数おかけします。よろしくお願い致します。
guest

回答1

0

ベストアンサー

モジュールのインポート

※ 予め BeautifulSoup をインストールしておいて下さい。

python

1import re 2from bs4 import BeautifulSoup 3from urllib.parse import urljoin

Ticket ID の取得

詳細ページの取得や画像のダウンロードを行う際に必要な Ticket ID を取得します。

python

1# クリック前のハンドルリスト 2handles_befor = driver.window_handles 3 4### ここから 5# Ticket ID 6ses = requests.session() 7r = ses.get(url) 8soup = BeautifulSoup(r.text, 'html.parser') 9ticket_id = soup.select_one('input[type="hidden"][name="ticket"]')['value'] 10### ここまで 11 12# ドロップダウンを選択する

画像のダウンロード

詳細ページのパースに BeautifulSoup を使用しています。また、個人的に XPATH よりは CSS selector に慣れているので、そちらを使っています。

python

1# ページャー数分、回す 2pagenum = pages.text 3for num in range(int(pagenum)): 4 # tbodyの中身取得 5 tbody = driver.find_element(By.XPATH,'//*[@id="result_list"]/table/tbody') 6 trlist = tbody.find_elements(By.TAG_NAME,'tr') 7 8 ### ここから最後まで 9 for trnum, tr in enumerate(trlist, start=1): 10 tdlist = tr.find_elements(By.TAG_NAME,'td') 11 trtext = [] 12 for td in tdlist: 13 test = td.text 14 if(test == '選ぶ'): 15 break 16 trtext.append(test) 17 # 1アイテム毎にCSVに書き込む 18 filename = "xxx.csv" 19 with open(filename, mode="a", encoding="utf-8") as f: 20 trs = ','.join(trtext) 21 f.write(trs) 22 # 改行コード 23 f.write('\n') 24 time.sleep(2) 25 26 # 画像URLを取得 27 href = tdlist[4].find_element(By.XPATH, 'a').get_attribute('href') 28 product_id = re.search(r"\('(.+?)',", href)[1] 29 r = ses.get(url + f'?ticket={ticket_id}&productId={product_id}&pid=j_detail') 30 soup = BeautifulSoup(r.text, 'html.parser') 31 img = soup.select_one('div#satei_frame > p > img') 32 if img: 33 # 画像の保存 34 imgurl = urljoin(url, img['src']) 35 r = ses.get(imgurl) 36 img_file = f'{trnum}_{trtext[2].replace("/", "_")}.png' 37 with open(img_file, 'wb') as f: 38 f.write(r.content)

投稿2022/12/18 21:19

melian

総合スコア19803

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

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

fullmoon311

2022/12/18 22:56

ありがとうございます。 BeautifulSoupは事前にダウンロードしていましたが、使いどころがいまいち分からず初めて使いました。 画像認識と合わせ、文字列読み込みcsvに追加書き込み後、画像の削除まで一連の流れが出来ました! 本当に感謝いたします。 勉強致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問