Uber, statistics, and a chrome extension
好的,我现在需要帮用户总结一篇文章,控制在100字以内。用户已经提供了文章内容,看起来是关于如何通过Chrome扩展程序抓取Uber的出行数据。 首先,我要理解文章的主要内容。作者想统计自己在Uber上的消费情况,发现没有现成的工具,于是自己开发了一个Chrome扩展程序。他通过分析Uber的网页数据,找到了API接口,并处理了CSRF令牌的问题,最终抓取了行程数据,并生成了统计图表。 接下来,我需要将这些信息浓缩到100字以内。重点包括:Chrome扩展程序、抓取 Uber 数据、分析消费、生成图表。同时,要确保语言简洁明了。 可能会遇到的问题是如何在有限的字数内涵盖所有关键点。比如,是否需要提到API和CSRF处理?考虑到用户可能更关注结果而非过程,所以可以简化这部分。 最后,检查字数是否符合要求,并确保描述准确无误。 </think> 作者开发了一个Chrome扩展程序,用于抓取并分析个人在Uber上的出行数据。通过解析Uber网站的API接口和处理CSRF令牌,该工具能够提取行程信息并生成统计图表,帮助用户了解消费情况和出行模式。 2018-12-22 15:39:48 Author: blog.jonlu.ca(查看原文) 阅读量:0 收藏

TL;DR You can get the chrome extension on the Chrome WebStore.

Earlier this week I wanted to see how much I've spent on uber across my roughly 4 years on the platform. I realized there was no easy way to do this. One option would be to go through my bank statements, but I have used a ton of different cards over the years. I could connect all my accounts to a service like Mint and search for it there, but that was time consuming and cumbersome. The goal would be to have a first party solution provided by uber, but no such service exists.

I started poking around Uber's rides website. It was surprisingly rich in data - it provided cost, start and end times, distance, and more. I wanted to see how they were getting the data. If they were server side rendering it then it would be significantly harder to scrape it and it would remove the possibility of interesting data that was returned but not used in the front end. Fortunately for us they just had a getTrips endpoint. The endpoint was a POST request to:

https://riders.uber.com/api/getTripsForClient

Uber network request

Uber network request

The response from the API

From there I could just start make the XMLHTTPRequest from any JavaScript file injected into the page. The best way to do that (and have it be easily deployed and installable) was a chrome extension.

I tried it at first and kept getting Unauthorized errors. I realized that the request was missing the CSRF token. However, since this was a Chrome Extension running code in the same context as the page, and since it had full access to the DOM, I could just retrieve it and pass it along. Fortunately it was stored in a <script> tag at the very beginning of the HTML, with id=__CSRF_TOKEN__. I took this token, added it as a header, and the API began replying back succesfully.

if (!csrf) {
  let text = $("#__CSRF_TOKEN__").text();
  csrf = text.replace(/\\u0022/g, ''); //Strip unicode quotes
}

$.ajax({
  method: 'POST',
  url: TRIP_ENDPOINT,
  data: {
    "tripUUID": tripUUID
  },
  headers: {
    "x-csrf-token": csrf
  },
  ...
}

Their API returns a maximum of 50 results per query, so I simply make the first one and then call it NUM_TOTAL / 50 times more.

if (trips.pagingResult && trips.pagingResult.hasMore && isFirstRun) {
  // Request all results in increments of MAX_LIMIT until we've reached the total amount of trips
  let next = MAX_LIMIT;
  while (next < trips.count) {
    requestDataFromUber(csrf, MAX_LIMIT, next, false);
    next += MAX_LIMIT;
  }
}

A trip data element looks like:

{
  "uuid": "redacted",
  "status": "COMPLETED",
  "clientUUID": "redacted",
  "driverUUID": "redacted",
  "paymentProfileUUID": "redacted",
  "cityID": 38,
  "countryID": 65,
  "vehicleViewName": "UberX",
  "vehicleViewID": 3298,
  "clientFare": 28.44,
  "currencyCode": "EUR",
  "isSurgeTrip": false,
  "begintripFormattedAddress": "Sonnenallee 168, 12059 Berlin, Germany",
  "dropoffFormattedAddress": "12529 Schönefeld, Germany",
  "requestTime": "2018-12-17T11:27:02.000Z",
  "dropoffTime": "2018-12-17T11:49:35.000Z"
}

However the trip data returned didn't include some information, such as the full receipt, car information, or the map.

Further investigation lead to an endpoint where you can query information about a specific trip.

https://riders.uber.com/api/getTrip

This endpoing took a POST request with a body containing the uuid from the request above. It contained the following extra fields.

{
  "tripMap": {
    "url": "<maps.google.com link from start to finish>",
    "mapType": "UBER",
    "mapTypeCompatible": true
  },
  "receipt": {
    "car_label": "Switching Option",
    "distance": "14.23",
    "distance_label_short": "km",
    "trip_time_label": "Trip time",
    "distance_label": "kilometers",
    "car_make": "Toyota",
    "duration": "19 min",
    "vehicle_type": "UberX",
    "car_make_label": "Make"
  }
}

Unfortunately the "Split Payment" wasn't returned as JSON, it was a server side rendered HTML blob. I could scrape it but did not think it would be worth the effort - plus, it would be an additional API call that slowed down the initial data collection.

This was now enough data to start running some queries. I wanted to visualize this on a page, so I built out a page that would receive the data and iterate over it to create a few graphs and populate some stats, such as how much you've spent in every currency.

// $ spent stats
$("#total-payment").text("$" + totalAcrossAllCurrencies.toFixed(2));
let totalSpentText = "";
let currencyKeys = getSortedKeysFromObject(totalSpent, true);
for (const key of currencyKeys) {
  let currencySymbol = getSymbolFromCode(key);
  totalSpentText += `<span className={"subheading"}>${key}</span><span className={"stat"}> ${
    currencySymbol + totalSpent[key].toFixed(2)
  }</span><br />`;
}
$("#total-spent").html(totalSpentText);

Using that data I made UberStats (source code here), which is live on the Chrome Web Store here.

Uber stats

Uber stats

Stats (personal info redacted) on my uber history

Uber stats graph

Uber stats graph

Graphs of months I've taken Ubers

You can get it here.


文章来源: https://blog.jonlu.ca/posts/uber-stats
如有侵权请联系:admin#unsafe.sh