UberEatsの管理画面をスクレイプしてみた

UberEatsの管理画面は結構スクレイプし難い

所用でUberEatsの管理画面をスクレイプする必要があり、プログラムを組みました。ただ、なかなかスクレイプが面倒だったので、知見をまとめておきたいと思います。

今回、やりたいことの要件としては、レポートのファイルでは取ることの出来ない、注文メニュー顧客の誰がフィードバックレビューしたかという情報を取ることで、そこにフォーカスした話しになります。

レポートに関して

まず、レポートに関しては、多少面倒ではありますが、手動でのデータ取得にしました。

基本的には、注文履歴をベースにデータを作りました。注文履歴のUUIDをベースに、そこに紐付ける形で、商品エラーやフィードバックを入れ込むようなデータ構造にしています。

ログイン

スクレイプで、まずログイン画面ですが、GoogleのreCAPTCHAが使用されています。普段アクセスしているIPでないものがアクセスすると、質問に答えるよう言われます。

最初は、全てrequestsを使用して、どこかサーバーに置くことも考えていたのですが、自身のマシンを使うようSeleniumベースでやることにしました。そうすることで、reCAPTCHAは発動されず、普通にSeleniumでアカウントを入力する形で、管理画面に入ることが出来ました。

注文メニューの取得

注文メニューはレポートには入っておらず、支払いという画面からしか取得出来ません。そこで、注文メニューに関してはスクレイプして取得することにしました。

まず、支払い画面の通信先を見ると、注文履歴のUUIDを使用してデータを取って来ているのが、分かりました。なので、Seleniumでログインした状態で、以下のURLをGETしに行くことでデータの取り出しに成功しました。

https://restaurant.uber.com/portal/payments/order-details?orderUUID=[ここに注文履歴のUUIDが入る]

これは、URLにアクセスするだけみたいなもんなので、本当に簡単でした。

フィードバックレビューの取得

フィードバックはレポートからも取ることが出来るのですが、誰がそのフィードバックしたかというのは、分からず、これを取ることにしました。が、これが意外と面倒でした。

フィードバックレビューの画面は、詳細を見るボタンが付いていて、フィードバックの量を増やしていくことが出来るのですが、Seleniumでデータが取り難かったのです。

そこで、ここでも直接APIを叩くようにしました。注文メニューの取得ではGETすることだけだったので簡単だったのですが、フィードバックレビューではPOSTする必要があり、更にGraphQLということで、ちょっと厄介でした。

実装方法としては、以下の通り、Seleniumで取得したcookieをrequestsに受け渡し、json形式でGraphQLのAPIを叩くというような方法です。また、headerもちゃんとセットしないと通りませんでした。

    headers = {
        'content-type': 'application/json',
        'dnt': '1',
        'sec-fetch-dest': 'empty',
        'sec-fetch-mode': 'cors',
        'sec-fetch-site': 'same-origin',
        'x-csrf-token': 'x',
        'origin': 'https://restaurant.uber.com',
        'referer': 'https://restaurant.uber.com/v2/home/[店舗ID]/feedback/reviews'
    }
    payload = {'operationName': 'EaterReviews', 'variables': {
        'restaurantUUIDs': store_ids,
        'lastTimestamp': ['%Y-%m-%dT%H:%M:%S%z'],
        'filters': {'starRating': [1, 2, 3, 4, 5, -1]}, 'limit': 50
    },
    'query': 'query EaterReviews($restaurantUUIDs: [ID!]!, $limit: Int, $lastTimestamp: String, $filters: EaterReviewFilterInput) {eaterReviews(restaurantUUIDs: $restaurantUUIDs, limit: $limit, lastTimestamp: $lastTimestamp, filters: $filters) {uuid timestamp rating comment tags menuItemReviews {id rating comment tags __typename} eater {uuid name profileURL __typename} eaterTotalOrders order {workflowUUID deliveredAt orderTotal currencyCode restaurant {uuid name __typename} __typename} reply {uuid promotion {uuid flatValue __typename} __typename} __typename}}'
   }
   session = requests.session()
   for cookie in driver.get_cookies():
       session.cookies.set(cookie['name'], cookie['value'])
   res = session.post('https://restaurant.uber.com/v2/graphql', headers=headers, json=payload)

これでユーザーIDまで取れるので、ユーザーを一意にすることが出来ました。それにより、フィードバックをくれたユーザーに関しては、他店舗も合わせてリピートが分かるようにもなりました。

最後に

レポートと合わせて、結構良いデータを蓄積出来るようになりました。

もし、UberEatsを利用している店舗で、データの分析を行いたいなどの要望がありましたら、是非お問い合わせください。

コメントを残す