10

我被要求画一张像这样的图表

在此处输入图像描述

使用乳胶(更准确地说,tikz 和/或 pgf)。如果我有数据,这将不是问题,但我没有。我所拥有的只是可以显示图表的网站,但我不知道如何从那里获取数据。

我今天花了一天的时间试图获取这些数据,包括写信给谷歌并使用一种跟踪线并推断图形点的软件,例如 Datathief 和 DigitizeIt,但我没有成功。我认为后者不起作用,因为图中的线条太细并且有多个蓝色阴影。当然,我尝试使用 Paint 和 Gimp 来提高图像质量,但仍然无法实现。

我还尝试使用 eps2pgf,这是一个将 eps 数字转换为 pgf 代码的 Java 脚本,但即使这样也不适用于我使用 Image Capture (mac) 和 Print Screen (Windows) 保存的图形,老实说,这将是我的最后一次选项,因为它是一种“蛮力方法”,会吐出你无法真正改进的丑陋代码。

毕竟我决定开始学习 Python,因为我的主管,让我用 tikz 画这张图的人说,有一个 Python 代码可以从这样的网站获取数据。现在我什至不确定 Python 是否能胜任这项工作(尽管我很高兴有学习它的借口),当然学习一门新语言并做类似的事情需要时间,所以我想知道是否真的有从该网站获取数据的方法,最好使用 Python,如果不是,则使用任何其他方法。

4

1 回答 1

25

好吧,如果 Google 为这些数据提供 API,那就太好了!也就是说,您仍然可以从网站上抓取一些数据。以下是如何去做...

安装萤火虫

我更喜欢Firefox 的Firebug,但 Chrome 的开发人员工具也应该可以工作。

调查 首先,让我们访问有问题的url并使用 Firebug 尝试看看发生了什么。使用 F12 激活 Firebug 或转到 Tools->Firebug->Open Firebug。首先单击“网络”选项卡并重新加载页面。这显示了所有提出的请求,并将让您深入了解该站点的工作方式。通常 flash 插件从外部加载数据,而不是将其嵌入到实际插件中,如果您查看请求,您会看到标记为 的请求POST service。如果您将鼠标悬停在它上面,firebug 会显示完整的 url,您会看到该页面向http://www.google.com/transparencyreport/traffic/service. 您可以单击请求并查看发送的标头、发布数据、响应和用于执行请求的 cookie。

请求详细信息

如果您查看响应,您会看到似乎是格式错误的 JSON。据我所知,这似乎包含标准化交通数据点的列表。您实际上可以从 firebug 中剪切和粘贴响应,但由于这是一个 python 问题,让我们更加努力。

将数据导入 Python

为了成功发出 post 请求,我们需要(几乎)完成浏览器所做的所有事情。我们可以稍微作弊,只复制请求标头并从 firebug 中发布数据,以欺骗真实的请求。

标题和帖子数据

使用三引号将多行字符串粘贴到 shell 中。复制请求标头并将其粘贴。 请求标头

>>> headers = """ <paste headers> """

接下来将其转换为 httplib2 的字典。我将使用列表理解(它根据换行符拆分字符串,然后在第一个 : 上拆分行并去除尾随空格,这给了我一个dict可以转换为字典的双元素列表的列表),但是你可以随心所欲地做到这一点。你也可以手动创建字典,我只是发现这个更快。

>>> headers = dict([[s.strip() for s in line.split(':', 1)]
                               for line in headers.strip().split('\n')])

并复制帖子数据。 复制用于我们感兴趣的图表的帖子数据

>>> body = """ <paste post data> """

提出请求 ,我将使用httplib2,但还有一些其他的 http 客户端和一些不错的工具用于抓取网络,例如mechanizescrapy。我们将使用 API 的 url、我们复制的标头和我们从 firebug 复制的发布数据发出 POST 请求。该请求返回一个响应头和内容的元组。

>>> import httplib2 
>>> h = httplib2.Http()
>>> url = 'http://www.google.com/transparencyreport/traffic/service'
>>> resp, content = h.request(url, 'POST', body=body, headers=headers)

按摩数据

原始格式真的很奇怪,只有最高位似乎包含数据点,所以我会放弃其余的。

>>> cleaned = content.split("'")[0][4:-1] + ']' 

现在它是有效的 JSON,所以我们可以将它反序列化为原生 python 数据类型。

>>> import json
>>> data = json.loads(cleaned)

我感兴趣的所有点都是浮点数,所以我将根据它进行过滤。

>>> data = [x for x in data if type(x) == float]

处理/保存数据

现在我们有了我们的数据,检查它,做额外的处理,等等......

>>> data[:5] 
<<< 
[44.73874282836914,
 45.4061279296875,
 47.5350456237793,
 44.56114196777344,
 46.08817672729492]

...或者只是保存它。

>>> with open('data.json', 'w') as f:
...:     f.write(json.dumps(data))

我们还可以使用matplotlib(或其他一些绘图/绘图库)中的pyplot将其绘制出来。

>>> import matplotlib.pyplot as plt
>>> plt.plot(data)

pyplot

结论

如果您只对一些事情感兴趣,您可以调整图表以显示您想要的内容,然后使用正确请求使用的请求标头/发布数据到http://www.google.com/transparencyreport/traffic/service. 您可能希望比我更仔细地检查实际响应,我只是丢弃了对我没有意义的部分。希望他们会为这些数据公开一个公共 API。

于 2011-05-07T11:45:03.033 回答