初めてのウェブスクレイピング

Uncategorized

今回は、とあるビジコンにてデータを集める際、楽天トラベルのWebサイトから宿泊施設の価格や設備情報を自動で取得する仕組みを作成したので、その取り組みについてまとめます。

取り組んだこと

今回取り組んだのは、以下のような内容です。

楽天トラベルから宿泊価格設備(Wi-Fi、モニター、会議室、プロジェクターなど)の有無のデータを抽出する仕組みを作成しました。

以下の地域に対して行いました。

  • 沖縄全域
  • 神奈川県
  • 埼玉県
  • 千葉県

条件としては

  • 2027年2月12日チェックイン
  • 1名素泊まり1泊

の検索結果に表示される宿泊施設を対象としました。

初期コード

最初に作成したコードは、WebページのHTMLを取得し、その中から必要な情報を抜き出すという非常にシンプルな構造でした。

処理の流れは次の通りです。

  1. Webページにアクセスする
    Pythonのrequestsというライブラリを使って、楽天トラベルの検索ページにアクセスします。
  2. HTMLの解析
    BeautifulSoupというライブラリを用いて構造的に解析します。
  3. 情報の取り出し
    価格、ホテル名、URLなどをひとずつ取得して表形式にまとめる。

試行錯誤

コード自体は回ったのですが、出力結果を見ると以下のような問題がありました。

  1. 割引価格を拾ってしまう
    本来の宿泊料金ではなく、割引額やクーポンの値段を取得してしまっていました。一つの宿に対しても、さまざまなプランがあり、それによって元の宿泊料金、クーポンの金額、割引後の金額、また税込金額なども混在する状態であり、ほしい宿泊料金を確実に持ってくるのが困難な状況でした。
  2. ホテル名が正しく取得できない
    1つ目の問題に対処しようとする中で、取得方法をさまざま変えている際、検索画面から情報を取得していて、「もっと見る」というリンクのテキストをホテル名として取得してしまうことがありました。

これに対して、ホテル名はすぐ修正できましたが、価格の取得が非常に難しかったです。楽天トラベルにはAPIが存在するため、APIを使えば取得できないかとも考えましたが、日付を指定した状態での宿泊料金の取得が難しかったため、APIは断念しました。

最終コード

そこで、ブラウザの開発者ツールを用いて実際に楽天トラベルのサイト構造を自分の目で見ることにしました。これによって、価格がHTMLではなく、JavaScriptのデータとして存在していることがわかりました。そこから以下のような処理を組み立てました。

  1. 楽天トラベルにアクセス
  2. HTMLを取得
  3. HTML内の var ds = {…};を取り出す
    楽天トラベルのページに検索結果が次のような形で埋め込まれていました。
var ds = {
  "displayedHotels": [...],
  "hotels": {
    "163087": {
      "plans": {
        "6216136": {
          "rooms": {
            "twntwn": {
              "sumTotalChargeTaxInclusive": 18525
            }
          }
        }
      }
    }
  }
};
  1. 最安プランを選ぶ
    1つのホテルには複数のプランや部屋があるため同じホテルでも最も安い価格を選べるようにプログラミングしました。
  2. hotel_id を用いて詳細ページにアクセスし、設備情報をキーワードで判定
    詳細ページから取得した文章から設備の有無を判定しました。例えばWi-Fiのコードは以下のようにしました。
def detect_wifi(text):
    t = clean_text(text).lower()

    yes_words = [
        "wifi", "wi-fi", "無線lan",
        "無料wifi", "無料wi-fi",
        "インターネット接続"
    ]

    if any(w.lower() in t for w in yes_words):
        return "あり"

    return "不明"
  1. カスタムページについても同様に行う

面白かったこと

地域指定をする際、神奈川県、埼玉県、千葉県について同時に行ったのですが、千葉県のみ情報が見つからないということが起きました。千葉県を指定する際のコードをchibaとしていたのですが、実際にはtibaとしないとヒットしないということがありました。

コメント

タイトルとURLをコピーしました