第 13 章 应用编程接口

应用编程接口(application programming interface,API)听起来是一个很酷炫的概念,但事实上并不是。API 是在 Web 上共享数据的一种标准方式。许多网站通过 API 端点来共享数据。本书列出了很多可用的 API,但是下面是一些很有用或有趣的 API。

这些都是返回数据的 API 示例。你向 API 发出请求,随后 API 返回数据。API 同样可以作为和其他应用交互的一种方式。例如,我们可以使用 Twitter API 来获得 Twitter 的数据,构建另外一个和 Twitter 交互的应用(例如,一个使用 API 发布推文的应用)。Google API 列表(https://developers.google.com/apis-explorer/#p/)是另外一个示例,大多数 API 允许你同公司服务进行交互。使用 LinkedIn API,你可以获取数据,发布更新到 LinkedIn,而不需要通过访问 Web 界面。因为 API 可以做很多不同的事情,所以它应该被认为是一种服务。就我们的目的而言,这个服务提供数据。

在这一章中,你会请求 API 数据并且保存到电脑。API 通常会返回 JSON、XML 或 CSV 文件,这意味着在数据保存到本地计算机之后,你需要应用在本书前几章学到的知识解析这些数据。本章使用的 API 是 Twitter API。

我们出于下面几个原因选择 Twitter API 作为样例。首先,Twiiter 是一个众所周知的平台。其次,Twitter 拥有大量的数据(推文),人们对分析这些数据有很大的兴趣。最后, Twitter API 允许我们探索许多 API 的概念,这正是本章讨论的话题。

Twitter 数据不仅是非正式的信息收集工具,类似于 One Million Tweet Map(http:// onemilliontweetmap.com/),同时也是更正式的学术研究工具,例如用于预测流感趋势(http://ieeexplore.ieee.org/document/5928903/?reload=true&tp=&arnumber=5928903&url=http:%2F%2Fieeexplore.ieee.org%2Fxpls%2Fabs_all.jsp%3Farnumber%3D5928903),以及捕获实时事件的发生,例如地震(http://dl.acm.org/citation.cfm?id=1772777)。

13.1 API特性

API 可以像数据响应请求一样简单,但是很难找到只有这个功能的 API 了。大多数的 API 还有其他有用的特性。这些特性包括多种不同的 API 请求方法(REST 或流式请求)、数据时间戳、频率限制、数据分级,以及 API 访问对象(key 和 token)。让我们通过 Twitter API 的上下文看一下这些特性。

13.1.1 REST API与流式API

Twitter API 有两种形式:REST API 和流式 API。大多数的 API 是 REST 形式的,但是一些实时服务通常会提供流式 API。REST 的全称为 Representational State Transfer(表述性状态转移),被设计用来构建稳定的 API 架构。可以使用 requests 库(见第 11 章)来获取 REST API 的数据。通过 requests 库,你可以发出 GETPOST Web 请求——这是 REST API 用来返回对应数据所使用的方法。在 Twitter 这个实例中,REST API 允许你查询推文,发布推文,做 Twitter 允许通过网站做的绝大多数事情。

第 13 章 应用编程接口 - 图1 通过 REST API,你经常可以(但并不总是可以)在浏览器中通过请求 API 链接预览查询。如果在浏览器中加载了 URL,结果看起来像是文本块,你可以在浏览器中安装一个格式化预览插件。例如,Chrome 有 JSON 文件的预览插件,通过一种更好阅读的方式预览 JSON 内容。

流式 API 作为一种实时服务运行,监听对相关数据的请求。碰到流式 API 时,你会想要使用一个构建好的库帮助管理数据的拉取。想详细了解多 Twitter 流式 API 是如何工作的,可以查看 Twitter 网站上的概述(https://dev.twitter.com/streaming/overview)。

13.1.2 频率限制

API 通常都有频率限制,限制用户在一段时间内能够请求的数据数量。频率限制由 API 提供者出于多种不同的原因使用。除了频率控制,你可能还会碰到对数据访问有限制的 API,特别是数据与商业利益相关时。出于基础设施和客户服务的考虑,API 提供者会想要控制请求的数量,这样服务器和架构可以控制数据传输数量。如果允许每个人在 100% 的时间使用 100% 的数据,这可能会导致 API 服务的崩溃。

如果遇到需要支付额外费用来取得特殊访问权限的 API,你需要确定是否有能力支付,以及数据对研究有多大的价值。如果碰到有频率限制的 API,你需要确定是否数据的一个子集就足够了。如果 API 有频率限制,可能会花费相当长的时间来收集一个有代表性的样例,所以一定要评估你想要投入在这之上的努力程度。

API 通常会对所有的用户有频率控制,因为这样更易于管理。Twitter 的 API 曾经也使用这种方式;然而,随着流式 API 的出现,用法发生了改变。Twitter 的流式 API 提供了数据的常量流,而 REST API 限制了每 15 分钟你可以发出请求的数量。为了帮助开发者理解频率限制,Twitter 发布了一张图表(https://dev.twitter.com/rest/public/rate-limits)。

在练习中,我们会使用名叫获取搜索 推文(GET searchtweets)的 API。这个接口返回包含特定搜索语素的推文。如果你查看文档(https://dev.twitter.com/rest/reference/get/search/tweets),会发现 API 返回 JSON 格式的数据,频率限制在每 15 分钟 180 次或 450 次,取决于你是以用户还是应用的身份请求 API。

第 13 章 应用编程接口 - 图2 保存来自 API 资源的数据文件时,你可以保存很多文件,或者将数据写入一个文件。正如在第 6 章学到的,你也可以保存推文数据到数据库。无论你用什么方式来保存数据,确保定期保存数据,不丢失任何已经请求的数据。

在第 3 章,我们处理了一个 JSON 文件。如果在每 15 分钟之间最大化 API 使用频率,可以收集 180 个 JSON 文件。如果你碰到了频率限制问题,需要优化对 Twitter 或者其他 API 的请求,请阅读 Twitter 的“API 频率限制”(https://dev.twitter.com/rest/public/rate-limiting)这篇文章中的“避免碰到频率限制的一些建议”这一节。

13.1.3 分级数据卷

迄今为止,我们已经讨论了通过其 API 可免费获取的 Twitter 数据。但是或许你想要知道怎样能够得到所有的数据?在 Twitter 这个实例中,你可能听说过三种数据访问级别: firehose、gardenhose 和 Spritzer。Spritzer 是免费的 API。表 13-1 描述了这些级别之间的不同。

表13-1:Twitter feed类型

feed 类型 覆盖 可用性 花费
firehose 所有推文 通过合作伙伴可用——DataSift(http://datasift.com/)或 Gnip(https://gnip.com/ $$$
gardenhose 10% 的推文 新的访问不再可用 不可用
Spritzer 1% 或不到 1% 的推文 通过公共 API 可用 免费

看到这些选项你可能会想:“我需要 Firehose,因为我想要所有的数据!”但是在你尝试取得访问权限之前,需要知道下面这些事情。

  • firehose 是一个很大的数据。当处理海量数据时,你需要规模化数据处理。仅仅开始查询 firehose 提供的数据集,也会需要很多的工程师和服务器。

  • firehose 需要付费——一年几十万美元。这不包括你需要消耗的基础设施的花费(即服务器空间和数据库耗费)。使用 firehose 通常不是一个人可以独自做的事情——通常,由一个大型的公司或者机构支撑这些花销。

  • 大部分你真正需要的,可以从 Spritzer 得到。

我们会使用 Spritzer,这是 Twitter 的免费公开 API,通过它可以在频率限制下取得推文。为了访问这个 API,我们会使用 API key 和 token。

13.1.4 API key和token

API key 和 token 是用来鉴别应用和用户的方式。Twitter API key 和 token 可能会让你迷惑。这里有四个你需要了解的概念。

  • API key

标识应用。

  • API secret

类似于应用的密码。

  • token

标识用户。

  • token secret

类似于用户的密码。

这几部分的组合给予我们访问 Twitter API 数据的权限。然而并不是所有的 API 都拥有这两层标识和密钥。Twitter 是一个很好的“最佳案例”(即更加安全的)示例。在一些情况下,API 会没有 key 或者只有一个 key。

创建一个Twitter API key和访问token

继续童工雇用的研究,收集 Twitter 上关于童工雇用的讨论。创建一个 Twitter API 的 key 很简单,但是需要以下几步。

(1) 如果你没有 Twitter 账户,先注册(https://twitter.com/signup)。

(2) 登录 apps.twitter.com。

(3) 点击“创建新应用”(Create New App)按钮。

(4) 给你的应用一个名称和描述。例如,名称设置为“童工讨论”,描述设置为“拉取 Twitter 上关于童工的讨论”。

(5) 给你的应用添加一个网站——这个网站托管着应用。指引这样写道:“如果你还没有一个 URL,可以先在此放置一个占位符,但是记得之后修改它。”我们并没有这样一个网站,所以把 Twitter 的 URL 放在这一栏中。确保你的 URL 中包含了 https,例如:https://twitter.com

(6) 同意开发者协议,点击“创建 Twitter 应用”(Create Twitter Application)。

在创建了应用之后,你会被带到应用管理页。如果你找不到这个页面,可以通过回到应用起始页(https://apps.twitter.com/)找到它。

现在,你需要创建一个 token。

(1) 点击“Keys 和访问 Tokens”(Keys and Access Tokens)键。(这里你可以重置 key,同样可以创建一个访问 token。)

(2) 滚动到页面底部,点击“创建我的访问 token”(Create my access token)按钮。一旦你完成了这些,这个页面会通过在顶部更新来刷新。如果再一次滚动到页面底部,你会看到访问 token。

现在你应该有了一个消费者(API)key 和一个 token。下面是我们的 key 和 token。

  • 消费者 key:5Hqg6JTZ0cC89hUThySd5yZcL

  • 消费者 secret:Ncp1oi5tUPbZF19Vdp8Jp8pNHBBfPdXGFtXqoKd6Cqn87xRj0c

  • 访问 token:3272304896-ZTGUZZ6QsYKtZqXAVMLaJzR8qjrPW22iiu9ko4w

  • 访问 token secret:nsNY13aPGWdm2QcgOl0qwqs5bwLBZ1iUVS2OE34QsuR4C

第 13 章 应用编程接口 - 图3

不要跟任何人分享你的 key 或 token !如果你和朋友分享了 key,他们可以在电子层面上代表你。如果他们滥用这个系统,你可能会失去访问权限,并为他们的行为负责。

为什么发布自己的应用?其中一个原因是我们可以生成更多个。在生成新的 key 和 token 的过程中,已经禁用了本书包含的 key 和 token——如果意外地暴露了 key 或者 token,这也是你应该做的事情。如果你需要创建一个新的 key,去“Keys 和访问 Tokens”(Keys and Access Tokens)栏目,点击“重新生成”(Regenerate)按钮。这会为你重新生成一个新的 API key 和 token。

现在有了一个 key,让我们访问 API !

13.2 一次简单的Twitter REST API数据拉取

有了一系列的 key 值,现在可以开始访问 Twitter 的 API 数据了。在这一节中,我们会编写一个简单的脚本,使用一个搜索查询,从 API 拉取数据。这一节中的脚本基于一个由 Twitter 提供的、作为示例的 Python 代码片段(https://dev.twitter.com/oauth/overview/single-user#python)。这份代码使用了 Python OAuth2,OAuth2 是在使用 API 时为了安全地识别和连接而使用的协议。

第 13 章 应用编程接口 - 图4 当下最好的认证方式是使用 OAuth2。一些 API 可能仍旧在使用 OAuth1。OAuth1 与 OAuth2 在功能上有所不同,并且是一个已经废弃的协议。如果需要使用 OAuth1,你可以使用 Requests-OAuthlib(https://requests-oauthlib.readthedocs.org/en/latest/),同 requests 一起拉取数据。当通过 API 认证时,确保识别哪一个协议正在被使用。如果使用了错误的协议,在尝试连接时,你会收到错误信息。

首先,需要安装 Python OAuth2:

  1. pip install oauth2

打开一个新文件,导入 oauth2,并且为你的 key 变量赋值:

  1. import oauth2
  2. API_KEY = '5Hqg6JTZ0cC89hUThySd5yZcL'
  3. API_SECRET = 'Ncp1oi5tUPbZF19Vdp8Jp8pNHBBfPdXGFtXqoKd6Cqn87xRj0c'
  4. TOKEN_KEY = '3272304896-ZTGUZZ6QsYKtZqXAVMLaJzR8qjrPW22iiu9ko4w'
  5. TOKEN_SECRET = 'nsNY13aPGWdm2QcgOl0qwqs5bwLBZ1iUVS2OE34QsuR4C'

然后添加函数来创建 OAuth 连接:

  1. def oauth_req(url, key, secret, http_method="GET", post_body="",
  2. http_headers=None):
  3. consumer = oauth2.Consumer(key=API_KEY, secret=API_SECRET)
  4. token = oauth2.Token(key=key, secret=secret)
  5. client = oauth2.Client(consumer, token)
  6. resp, content = client.request(url, method=http_method,
  7. body=post_body, headers=http_headers)
  8. return content

❶ 创建一个 oauth2 对象的消费者。消费者是 key 的所有者。这行代码给消费者提供 key,这样消费者可以顺利地通过 API 识别。

❷ 将 token 赋值给 oauth2 对象。

❸ 创建客户端,包含消费者和 token。

❹ 使用函数参数 url,通过 OAuth2 客户端执行请求。

❺ 返回从连接接收到的内容。

现在有了一个函数,允许我们连接到 Twitter API。然而,我们需要定义 URL,并且调用函数。搜索 API 文档(https://dev.twitter.com/rest/public/search)告诉我们更多有关想要使用的请求的信息。使用 Web 接口,可以看到,如果搜索#childlabor,最终得到的 URL 是:https://twitter.com/search?q=%23childlabor。文档建议重新格式化 URL,所以最终的 URL 如下:https://api.twitter.com/1.1/search/tweets.json?q=%23childlabor

之后,可以把这个 URL 作为一个变量,并使用之前定义的变量调用函数:

  1. url = 'https://api.twitter.com/1.1/search/tweets.json?q=%23childlabor'
  2. data = oauth_req(url, TOKEN_KEY, TOKEN_SECRET)
  3. print(data)

❶ 在最后添加打印语句,这样可以看见输出。

运行脚本时,你应该看到数据打印成一个很长的 JSON 对象。你可能记得 JSON 对象看起来和 Python 字典类似,但是如果使用 print(type(data)) 重新运行脚本,你会发现内容是一个字符串。现在我们可以做以下两件事情中的一件:转化数据为一个字典并开始解析它,或者保存字符串到一个文件,之后再解析。为了继续在脚本中解析数据,在脚本顶部添加 import json。之后,在尾部,使用 json 加载字符串,并且输出它。

  1. data = json.loads(data)
  2. print(type(data))

变量 data 现在会返回一个 Python 字典。如果你想要将数据写入一个文件并且在之后解析它,替换为下面的代码:

  1. with open('tweet_data.json', 'wb') as data_file:
  2. data_file.write(data)

最后的脚本应该看起来像下面这样:

  1. import oauth2
  2. API_KEY = '5Hqg6JTZ0cC89hUThySd5yZcL'
  3. API_SECRET = 'Ncp1oi5tUPbZF19Vdp8Jp8pNHBBfPdXGFtXqoKd6Cqn87xRj0c'
  4. TOKEN_KEY = '3272304896-ZTGUZZ6QsYKtZqXAVMLaJzR8qjrPW22iiu9ko4w'
  5. TOKEN_SECRET = 'nsNY13aPGWdm2QcgOl0qwqs5bwLBZ1iUVS2OE34QsuR4C'
  6. def oauth_req(url, key, secret, http_method="GET", post_body="",
  7. http_headers=None):
  8. consumer = oauth2.Consumer(key=API_KEY, secret=API_SECRET)
  9. token = oauth2.Token(key=key, secret=secret)
  10. client = oauth2.Client(consumer, token)
  11. resp, content = client.request(url, method=http_method,
  12. body=post_body, headers=http_headers)
  13. return content
  14. url = 'https://api.twitter.com/1.1/search/tweets.json?q=%23popeindc'
  15. data = oauth_req(url, TOKEN_KEY, TOKEN_SECRET)
  16. with open("data/hashchildlabor.json", "w") as data_file:
  17. data_file.write(data)

从这里开始,你可以查看 3.2 节,来解析数据。

13.3 使用Twitter REST API进行高级数据收集

从 Twitter 拉取单个数据文件并不是非常有用,因为这只返回大约 15 条推文。我们希望执行一连串的查询,这样可以收集尽可能多的关于这一话题的推文。我们会使用另外一个库来做这项工作——Tweepy。Tweepy 可以管理一系列的请求,包括 Twitter 的 OAuth。首先安装 tweepy

  1. pip install tweepy

在脚本的最开始,导入 tweepy,并且再一次设置你的 key:

  1. import tweepy
  2. API_KEY = '5Hqg6JTZ0cC89hUThySd5yZcL'
  3. API_SECRET = 'Ncp1oi5tUPbZF19Vdp8Jp8pNHBBfPdXGFtXqoKd6Cqn87xRj0c'
  4. TOKEN_KEY = '3272304896-ZTGUZZ6QsYKtZqXAVMLaJzR8qjrPW22iiu9ko4w'
  5. TOKEN_SECRET = 'nsNY13aPGWdm2QcgOl0qwqs5bwLBZ1iUVS2OE34QsuR4C'

之后将你的 API key 和 API secret 传入 tweepyOAuthHandler 对象,这个对象会管理上一个实际提到的 OAuth 协议。之后设置你的访问 token。

  1. auth = tweepy.OAuthHandler(API_KEY, API_SECRET)
  2. auth.set_access_token(TOKEN_KEY, TOKEN_SECRET)

❶ 创建一个对象,通过 tweepy 来管理 API 认证。

❷ 设置访问 token。

之后,将刚刚创建的认证对象传递给 tweepy.API

  1. api = tweepy.API(auth)

tweepy.API 对象可以接受不同的参数,这给了你请求数据时控制 tweepy 行为的能力。你可以通过传递参数(像 retry_count=3, retry_delay=5)直接添加重试和延迟。另一个有用的选项是 wait_on_rate_limit,这个选项会直到频率限制解除后再去做下一次请求。 tweepy 文档(http://docs.tweepy.org/en/latest/api.html)中有这些选项的细节和更多信息。

我们想要使用 tweepy.Cursor 创建一个和 Twitter API 的连接。然后将 API 方法(这里是 api.searchhttp://docs.tweepy.org/en/latest/api.html#API.search)和与其相关的参数传递给指针(cursor)。

  1. query = '#childlabor'
  2. cursor = tweepy.Cursor(api.search, q=query, lang="en")

❶ 创建 query 变量。

❷ 使用 query 创建 cursor,并且限制其只检索英语。

第 13 章 应用编程接口 - 图5 尽管 Cursor 并不是很直观,但是这是一个在数据库连接中很常用的编程名词。虽然 API 不是数据库,但类名称 Cursor 可能受 API 类似数据库使用方式的影响而命名。你可以在维基百科(https://en.wikipedia.org/wiki/Cursor_(databases))上阅读更多关于指针的内容。

根据 tweepy 的文档(http://tweepy.readthedocs.org/en/latest/api.html),cursor 可以返回一个在单个对象级别或单页对象级别上的迭代器。你同样可以定义限制(http://tweepy.readthedocs.io/en/latest/cursor_tutorial.html#limits),来确定 cursor 抓取的页面数或对象数。如果查看 print(dir(cursor)),你会看到这里有 3 个方法:['items', 'iterator', 'pages']。一页返回一串对象,即在你的查询下独立的推文。根据需要,我们会使用页面。

让我们遍历这些页面,并且保存数据。在此之前,需要做以下两件事。

(1) 添加 import json 到脚本的顶端。

(2) 在脚本的相同目录下,创建一个名叫 data 的文件夹。为此,在命令行中运行 mkdir data

一旦你完成了这两件事情,运行下面的代码来遍历和保存推文:

  1. for page in cursor.pages():
  2. tweets = []
  3. for item in page:
  4. tweets.append(item._json)
  5. with open('data/hashchildlabor.json', 'wb') as outfile:

❶ 对于每一个 cursor.pages() 返回的页面……

❷ 创建一个空列表来保存推文。

❸ 对于页面中的每一个对象(或推文)……

❹ 抽取 JSON 推文数据,保存到推文列表中。

❺ 打开一个名为 hashchildlabor.json 的文件,保存这些推文。

你会注意到,没有保存太多的推文到文件。每个页面只有 15 个推文,所以我们需要找出一个方法来得到更多的数据。有以下一些选项。

  • 打开一个文件,并且永远不关闭它,或者打开一个文件,在末尾追加信息。这会创建一个非常大的文件。

  • 将每一页保存到自己的文件中(你可以使用时间戳来保证每个文件有不同的文件名)。

  • 在你的数据库中创建一个新的表来保存数据。

创建一个文件是危险的,因为进程在任何时候都可能失败,破坏数据。除非你只是在进行很小规模的数据拉取(例如,1000 条推文),或进行开发测试,否则你应该使用其他选择。

每次都有很多种方法可以将数据保存到新文件中,最普遍的一种方式是使用日期和时间戳(https://docs.python.org/2/library/datetime.html)创建一个文件,或者只是递增一个数字,将其添加到文件名的末尾。

我们会继续添加推文到简单的数据库。为此,使用下面的函数。

  1. def store_tweet(item):
  2. db = dataset.connect('sqlite:///data_wrangling.db')
  3. table = db['tweets']
  4. item_json = item._json.copy()
  5. for k, v in item_json.items():
  6. if isinstance(v, dict):
  7. item_json[k] = str(v)
  8. table.insert(item_json)

❶ 创建或访问一个新表,名为 tweets

❷ 检查推文中是否含有字典对象。由于 SQLite 并不支持保存 Python 字典,我们需要将其转换为字符串。

❸ 插入合法的 JSON 对象。

我们还需要添加 datasetimport 部分的代码中。在之前保存页面的地方,需要添加这个函数的使用。确保遍历每一条推文。最后的脚本应该看起来像下面一样。

  1. import json
  2. import tweepy
  3. import dataset
  4. API_KEY = '5Hqg6JTZ0cC89hUThySd5yZcL'
  5. API_SECRET = 'Ncp1oi5tUPbZF19Vdp8Jp8pNHBBfPdXGFtXqoKd6Cqn87xRj0c'
  6. TOKEN_KEY = '3272304896-ZTGUZZ6QsYKtZqXAVMLaJzR8qjrPW22iiu9ko4w'
  7. TOKEN_SECRET = 'nsNY13aPGWdm2QcgOl0qwqs5bwLBZ1iUVS2OE34QsuR4C'
  8. def store_tweet(item):
  9. db = dataset.connect('sqlite:///data_wrangling.db')
  10. table = db['tweets']
  11. item_json = item._json.copy()
  12. for k, v in item_json.items():
  13. if isinstance(v, dict):
  14. item_json[k] = str(v)
  15. table.insert(item_json)
  16. auth = tweepy.OAuthHandler(API_KEY, API_SECRET)
  17. auth.set_access_token(TOKEN_KEY, TOKEN_SECRET)
  18. api = tweepy.API(auth)
  19. query = '#childlabor'
  20. cursor = tweepy.Cursor(api.search, q=query, lang="en")
  21. for page in cursor.pages():
  22. for item in page:
  23. store_tweet(item)

13.4 使用Twitter流式API进行高级数据收集

本章前文中提到过,有两种类型的 Twitter API 可以使用:REST API 和流式 API。

流式 API 同 REST API 相比有什么差别呢?下面进行了简单的概括。

  • 数据是实时的,而 REST API 只返回已经发布一段时间的推文。

  • 流式 API 缺乏普遍性,但是在未来,随着更多实时数据的生成和曝光,其可用性会变得越来越高。

  • 因为最新的数据很有趣,所以很多人对这部分数据很感兴趣,这意味着你可以在网络上找到很多资源和帮助。

让我们创建一个脚本来收集来自流式 API 的数据。这个脚本会使用在这一章覆盖到的所有知识。首先编写最基础的部分——输入值和 key 值。

  1. from tweepy.streaming import StreamListener
  2. from tweepy import OAuthHandler, Stream
  3. API_KEY = '5Hqg6JTZ0cC89hUThySd5yZcL'
  4. API_SECRET = 'Ncp1oi5tUPbZF19Vdp8Jp8pNHBBfPdXGFtXqoKd6Cqn87xRj0c'
  5. TOKEN_KEY = '3272304896-ZTGUZZ6QsYKtZqXAVMLaJzR8qjrPW22iiu9ko4w'
  6. TOKEN_SECRET = 'nsNY13aPGWdm2QcgOl0qwqs5bwLBZ1iUVS2OE34QsuR4C'

❶ 导入 StreamListener,这会创建一个流式会话,并且监听信息。

❷ 导入之前使用过的 OAuthHandler,以及 Stream,后者是真正处理 Twitter 的流信息的类。

这个脚本中的 import 语句和上一个脚本中的有少许不同。这两种方式都是合法的,只是个人偏好问题。下面是这两种方式的一个快速比较。

方式 1

  1. import tweepy
  2. ...
  3. auth = tweepy.OAuthHandler(API_KEY, API_SECRET)

方式 2

  1. from tweepy import OAuthHandler
  2. ...
  3. auth = OAuthHandler(API_KEY, API_SECRET)

通常情况下,脚本中没有频繁使用库时使用第一种方式。在你有一长串代码,想要更清晰一些的时候,也适合使用第一种方式。然而,当库使用得非常多时,要将其都打印出来会变得令人厌烦;同样,如果这个库是脚本的基础,从这个库导入的模块或类对人们来说应该很明显。

现在,要创建导入的 StreamListener 类的子类(在第 12 章学习的概念),以覆写其中的 on_data 方法。为此,在新的类 Listener 中重新定义了这个函数。当有数据时,我们想要在终端中看到它们,所以添加 print 语句到函数中。

  1. class Listener(StreamListener):
  2. def on_data(self, data):
  3. print data
  4. return True

❶ 创建 StreamListener 的子类。

❷ 定义 on_data 方法。

❸ 输出推文。

❹ 返回 TrueStreamListeneron_data 方法,同样返回 True。因为我们创建了子类并重新定义了这个函数,所以必须在子类方法中重复返回这个值。

接下来,添加你的认证处理逻辑:

  1. auth = OAuthHandler(API_KEY, API_SECRET)
  2. auth.set_access_token(TOKEN_KEY, TOKEN_SECRET)

最后,将 Listenerauth 传入到 Stream 中,开始使用搜索词过滤。在这个案例中,我们查看 child labor(童工),因为它相对于 #childlabor 更加普遍。

  1. stream = Stream(auth, Listener())
  2. stream.filter(track=['child labor'])

❶ 将 authListener 作为参数传递,创建一个流。

❷ 过滤流,只返回有 child 和 labor 存在的条目。

最后的脚本如下:

  1. from tweepy.streaming import StreamListener
  2. from tweepy import OAuthHandler, Stream
  3. API_KEY = '5Hqg6JTZ0cC89hUThySd5yZcL'
  4. API_SECRET = 'Ncp1oi5tUPbZF19Vdp8Jp8pNHBBfPdXGFtXqoKd6Cqn87xRj0c'
  5. TOKEN_KEY = '3272304896-ZTGUZZ6QsYKtZqXAVMLaJzR8qjrPW22iiu9ko4w'
  6. TOKEN_SECRET = 'nsNY13aPGWdm2QcgOl0qwqs5bwLBZ1iUVS2OE34QsuR4C'
  7. class Listener(StreamListener):
  8. def on_data(self, data):
  9. print data
  10. return True
  11. auth = OAuthHandler(API_KEY, API_SECRET)
  12. auth.set_access_token(TOKEN_KEY, TOKEN_SECRET)
  13. stream = Stream(auth, Listener())
  14. stream.filter(track=['child labor'])

下面,你需要添加代码,通过 on_data 方法,像本章之前那样将推文保存到数据库、文件或其他的存储工具。

13.5 小结

能够同应用编程接口进行交互是数据处理中很重要的一部分。在这一章中,我们学习了一些 API 基础知识(见表 13-2 中的总结),并且处理了来自 Twitter API 的数据。

表13-2:API概念

概念 功能
REST API(与流式 API 相比) 返回数据,并且暴露静态的节点
流式 API(与 REST API 相比) 返回查询相关的实时数据
OAuth 和 OAuth2 给定一系列 key 值和 token 的认证
分级数据卷 数据频率限制 / 可用性的不同级别;一些需要付费
key 和 token 标识用户和应用的唯一 ID 和密钥

我们已经复用了许多已经知道的 Python 概念,并且在这一章中学习了一些新的 Python 概念。首先是 tweepy 的使用,一个处理同 Twitter API 交互的库。你还学习了有关认证和 OAuth 协议的知识。

作为同 API 交互的拓展,第 14 章会介绍你不在场时运行 API 脚本的知识。