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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Python

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

Q&A

解決済

1回答

2708閲覧

Pythonでじゃらんの施設名をスクレイピングするも、30件の内14件しか取得できない

hogemaTV

総合スコア2

Python

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

0グッド

0クリップ

投稿2021/11/07 10:13

編集2021/11/07 10:15

1ページにつき30件を表示しているwebページから、スクレイピングして取得した結果を見ると14件しか取得できなくて
困っています。

下記がスクレイピング対象のページです。
https://www.jalan.net/uw/uwp2011/uww2011search.do?actionId=G&keyword=%97%4C%94%6E&dateUndecided=1&stayYear=2021&stayMonth=11&stayDay=08&minPrice=0&maxPrice=999999&distCd=06&rootCd=7712&dispStartIndex=0&activeSort=0&screenId=UWW2011

下記が実装中のコードです。AWSのLambda上で書いています。

import requests from bs4 import BeautifulSoup import urllib.parse import json def lambda_handler(event,context): keyword = event['queryStringParameters']['keyword'] urlKeyword = urllib.parse.quote(keyword, encoding='shift-jis') url = f"https://www.jalan.net/uw/uwp2011/uww2011init.do?keyword={urlKeyword}&dispStartIndex=0" r = requests.get(url) c = r.content soup = BeautifulSoup(c, "lxml", from_encoding="Shift_JIS") all=soup.find_all("h2",{"class":"p-searchResultItem__facilityName"}) print(all) facilities=[] for item in all: d={} d["facilityName"]=item.text facilities.append(d) return { 'statusCode': 200, 'headers': { "Access-Control-Allow-Origin": "*" }, 'body': json.dumps(facilities) }

print(all)の段階でデータが14件しか取得できていません。

またリクエストで取得しきれていないのかと思い、r = requests.get(url)の直下にtime.sleep(5)を仕込んでみても改善されませんでした。

よろしくお願いします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

JavaScriptでHTML取得後に追加されているのではないでしょうか。

requests.getではJavaScript実行機能は無いです。
print(r.text)してみましょう。そこに無いと無理です。

そういうページなのであれば、Selenium等を使って、ブラウザにJavaScriptを実行させます。

#追記
原因は、lxmlパーサーがShift_JISにちゃんと対応してないっぽい事でした。コメント参照。
utf-8に変換してからパースすることで解決。
厳密には、HTMLヘッダのContent-Typeも書き換えてからパースすべきでしょうが、多分そこは見てない。

投稿2021/11/07 10:26

編集2021/11/10 12:07
otn

総合スコア85901

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

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

hogemaTV

2021/11/07 10:37

Selenium調査・実装してみます。ありがとうございます。
hogemaTV

2021/11/10 11:18 編集

その後中々時間が取れずまだSeleniumを学習段階ですが、 今の私の実装でデータが少なくなってしまう原因箇所はデバッグでわかりました。 ✖ soup = BeautifulSoup(c, "lxml", from_encoding="Shift_JIS") 〇 soup = BeautifulSoup(c, "html.parser", from_encoding="Shift_JIS") ということでした。 しかし、html.parserですとスピードが遅くてAPIGatewayの最大タイムアウト29秒以内に 終わらないのでやはり提案頂いたSeleniumを試してみたいと思います。
otn

2021/11/10 11:53 編集

Seleniumは遅いですよ。 パーサーで結果が違うと言うことは、lxml が Shift_JIS にちゃんと対応していないのでしょうか。 下記でどうでしょう?Shift_JIS(CP932) から utf-8 に変換してから処理。 soup = BeautifulSoup(c.decode("CP932"), "lxml") Shift_JISといいつつ、JIS第二水準範囲外の文字を使っているケースも多いので、CP932と書いておくのがいいです。
hogemaTV

2021/11/10 12:01

いけました!!ありがとうございました!!
otn

2021/11/10 12:03

私も勉強になりました。lxmlのドキュメントを調べて正式な仕様(制約事項)なのか調べるところまでする気は起きないですが。
melian

2021/11/10 12:29

html パーサで実行すると30件取れてますね。 >>> soup = BeautifulSoup(c, "html.parser") >>> all=soup.find_all("h2",{"class":"p-searchResultItem__facilityName"}) >>> len(all) 30 from_encoding="Shift_JIS" は指定しなくても問題ないです。
hogemaTV

2021/11/10 12:43 編集

html パーサで30件取れはするのですが、APIGatewayのタイムアウトでひっかかってしまいます(質問の要件にAPIGatewayのことを書いておらず申し訳ないです) ということもあり、otnさんが提案したlxmlでパース前にutf-8に変換でいけました。 この質問の答えとしては、30件手に入れることができるhtml パーサももちろん正しいです。
melian

2021/11/10 12:42

そうだったのですね、失礼しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問