跳转到主要内容
请注意: 我们已在 X API v2 中发布了新版的 Post 搜索Post 计数。我们建议你查看 X API v2 的最新变化 这些 endpoint 已更新,现包含 Post 编辑 metadata。请在“编辑 Posts” 基础知识页面了解这些 metadata 的详细信息。 

概览

Enterprise Enterprise 级 API 仅在我们的受管访问层级中提供。要使用这些 API,您必须先与我们的 Enterprise 销售团队开立账户。了解更多信息请参见此处 您可以在此处查看所有 X API 搜索 Post 的产品。 共有两种 Enterprise 搜索 API:
  1. 30 天搜索 API 提供过去 30 天的数据。
  2. 全量归档搜索 API 提供对自 2006 年 3 月首条 Post 起至今的完整 X 数据语料库的即时、完整访问。
这些 RESTful API 每个请求支持单条长度最多 2,048 个字符的 query。查询使用 PowerTrack 规则语法编写——更多详情请参见规则与过滤。用户可以指定任意时间范围,精确到分钟。但响应将受限于您指定的 maxResults 或 31 天中较小者,并包含一个 next 令牌以分页获取下一批结果。如未指定时间参数,API 将返回最近 30 天内的匹配 data。 Enterprise 搜索 API 以低延迟、完整保真度、基于 query 的方式提供对 Post 归档的分钟级访问。Post 数据按时间倒序返回,从与您的 query 匹配的最新 Post 开始。Post 在发布后约 30 秒即可通过搜索 API 获取。 这些搜索 endpoint 提供已编辑 Post 的 metadata。自 2022 年 9 月 29 日以来创建的所有 Post 对象均包含 Post 编辑 metadata,即使该 Post 从未被编辑。每次编辑 Post,都会创建一个新的 Post ID。某条 Post 的编辑历史由一个 Post ID 数组记录,数组以原始 ID 开始。 这些 endpoint 将始终返回最新的编辑版本,并包含任何编辑历史。任何在其 30 分钟编辑窗口之后收集的 Post 都将代表其最终版本。要了解有关 Edit Post metadata 的更多信息,请参阅Edit Posts 基础页面。 请求包含一个 maxResults 参数,用于指定每个 API 响应返回的 Post 最大数量。如果与该 query 关联的 Post 数量超过每次响应的最大结果数,响应中将包含一个 next 令牌。后续请求使用这些 next 令牌分页遍历与该 query 关联的整套 Post。 这些 Enterprise 搜索 API 提供一个 counts endpoint,使用户能够请求与其 query 相关的数据量。 

请求类型

Enterprise 搜索 API 支持两种请求类型:

搜索请求(data)

向 Enterprise 搜索 API 发起的搜索请求,允许你在给定的时间范围内每个响应检索最多 500 条结果,并可通过分页获取更多数据。通过 maxResults 参数,你可以为展示类场景指定较小的页面大小(便于用户按需加载更多结果),或为大规模数据提取指定较大的页面大小(最高 500)。data 以时间逆序返回,并在交付时满足合规要求。

计数请求(Post 计数)

计数请求用于检索历史活动计数,反映在所请求的时间范围内与给定 query(查询)匹配的活动发生次数。响应实质上会按天、小时或分钟(默认分桶为_hour_)返回一个计数直方图。需要注意的是,计数结果并不总能反映在 Post 发布较久之后(超过 7 天)才发生的合规事件(例如 Post 的 delete);因此,计数指标可能并不总是与针对相同 query 的 data 请求结果一致,这是预期的。 计费说明: 针对 data 和计数 endpoint 发起的每个请求——包括分页请求——均计为一次计费请求。因此,如果单个 query 有多页结果,遍历 X 页结果在计费上即等同于 X 次请求。

可用运算符

Enterprise 搜索 API 支持长度最多为 2,048 个字符的规则。Enterprise 搜索 API 支持下列运算符。有关详细说明,请参见此处
基于 Post 内容的匹配:基于关注账号的匹配:Post 属性:地理空间运算符:
* 关键词
* “精确短语”
* “keyword1 keyword2”~N
* #
* @
* $
* url:
* lang:
* from:
* to:
* retweets_of:
* is:retweet

* has:mentions
* has:hashtags
* has:media
* has:videos
* has:images
* has:links
* has:symbols
* is:verified

* -is:nullcast(仅用于取反的运算符)
* bounding_box:[west_long south_lat east_long north_lat]
* point_radius:[lon lat radius]
* has:geo
* place:
* place_country:
* has:profile_geo
* profile_country:
* profile_region:
* profile_locality:
注意:不要嵌入/嵌套运算符(“#cats”)在搜索 API 中将被解析为 cats。‘lang:’ 运算符以及所有 ‘is:’ 和 ‘has:’ 运算符不能单独使用,必须与其他子句组合(例如 @XDevelopers has:links)。 由于分词/匹配机制的限制,搜索 API 仅支持有限的运算符集合。Enterprise 实时和批量历史 API 提供其他运算符。更多详情请参见此处 更多详情,请参阅运算符入门指南。

数据可用性 / 重要日期

在使用 Full-Archive 搜索 API 时,请注意自 2006 年以来 X 平台持续演进。随着新功能加入,底层 JSON 对象也新增了 metadata。因此,了解搜索运算符所匹配的 Post 属性是何时引入的非常重要。下面列出了几类重要 metadata 的关键“诞生”日期。想了解 Post 属性最初引入的时间,请参阅 this guide
  • 第一条 Post:2006/3/21
  • 首次原生转发:2009/11/6
  • 首次带地理标签的 Post:2009/11/19
  • 首次为过滤建立 URL 索引:2011/8/27
  • 增强的 URL 展开 metadata(网站标题与描述):2014/12/1
  • 个人资料地理信息增强 metadata 及过滤:2015/2/17

数据更新与可变性

使用 Enterprise 搜索 API 时,Post 中的某些数据是可变的,即在初始归档后仍可能被更新或更改。 这些可变数据分为两类:
  • 用户对象 metadata:
    • 用户的 @handle(数值型 id 永不更改)
    • 个人简介
    • 计数:statuses、followers、friends、favorites、lists
    • 资料位置
    • 其他信息,如时区和语言
  • Post 统计数据——即可由用户在平台上的操作改变的任何内容(示例如下):
    • Favorites 计数
    • 转发计数
在大多数情况下,搜索 API 会返回在查询执行时存在于平台上的数据,而非 Post 生成时的数据。然而,对于使用特定运算符(例如 from、to、@、is:verified)的查询,可能并非如此。我们的索引会定期更新数据,且对最近时间范围的更新频率更高。因此,在某些情况下,返回的数据可能与 X.com 上当前显示的数据不完全一致,但与其上次被索引时的数据一致。 请注意,这种不一致仅适用于运算符作用于可变数据的查询。例如按用户名进行过滤;对此,最佳的替代方案是使用用户的数值型 ID,而不是 @handle 进行此类查询。

单线程与多线程请求

每位客户在其搜索 endpoint 上都有明确的请求速率限制。Full-Archive 搜索的默认每分钟请求速率限制为每分钟 120 次请求,平均为每秒 2 次 query(QPS)。这个平均 QPS 意味着理论上每秒可以向 API 发起 2 次请求。鉴于产品的分页特性,如果一个为期一年的 query 关联了一百万条 Post,并且全年均匀分布,那么需要发起 2,000 多次请求(假设 maxResults 为 500)才能获取所有 data。假设每个响应耗时 2 秒,则需要约 4,000 秒(或略超一小时)通过单线程(使用上一个响应的 next 令牌、每秒 1 次请求)串行拉取全部 data。不错! 现在考虑使用 12 个并行线程来接收数据的情况。假设这一百万条 Post 在一年的时间内均匀分布,您可以将请求拆分为 12 个并行线程(多线程),从而在单个“作业”上更充分利用每秒的请求速率限制。换句话说,您可以对感兴趣的每个月各运行一个线程,这样数据检索速度可提升 12 倍(约 6 分钟)。 这个多线程示例同样适用于 counts endpoint。比如,如果您希望获取两年期间的 Post 计数,您可以发起单线程请求,并以每次回溯 31 天的方式分页获取计数。假设每个响应耗时 2 秒,那么完成 24 次 API 请求并检索完整的计数集大约需要 48 秒。不过,您也可以选择同时发起多个按月的请求。当以每秒 12 次请求的速率发起时,完整的计数集大约在 2 秒内即可检索完成。

重试逻辑

如果您在使用 Enterprise 搜索 API 时遇到 503 错误,这通常是暂时性问题,稍后重试请求即可解决。 如果请求连续失败 4 次,且每次失败之间至少间隔 10 分钟,请按以下步骤排查:
  • 缩短请求覆盖的时间范围后重试;如仍不成功,继续缩短,直至最小为 6 小时的时间窗口。
  • 如果您将大量术语使用 OR 连接,请将其拆分为多条独立规则,并分别重试。
  • 如果您的规则中包含大量排除条件,请减少否定术语的数量后重试。

快速上手

开始使用 Enterprise Search Posts:30-Day API

Enterprise Search Posts:30-Day API 可提供最近 30 天内发布的 Post。系统会根据你在请求中指定的 query(查询)来匹配 Post 并返回结果。query 是一条规则,用于定义返回的 Post 应包含的内容。在本教程中,我们将搜索由 X 账号 @XDevelopers 用英语发布的 Post。 你在负载中收到的 Posts 可以是 data 格式(提供完整的 Post 负载),也可以是 counts 格式(提供匹配 Post 的数值统计数据)。我们将使用 cURL 向 data 和 counts endpoint 发起请求。 你需要准备以下内容:

访问 data endpoint

data endpoint 将返回匹配到的 Post 的完整负载。我们将使用 from:lang: 运算符查找来自 @XDevelopers 且语言为英语的 Post。更多运算符请点击此处
  • cURL
  • cURL example
cURL 是一种使用 URL 语法获取或发送文件的命令行工具。按如下所示替换占位符后,将以下 cURL 请求复制到命令行中:
  • Username <USERNAME>,例如:email@domain.com
  • Account name <ACCOUNT-NAME>,例如:john-doe
  • Label <LABEL>,例如:prod
  • fromDate 和 toDate,例如:"fromDate":"201811010000", "toDate":"201811122359"
发送请求后,系统会提示输入密码。
curl -X POST -u<USERNAME> "https://gnip-api.x.com/search/30day/accounts/<ACCOUNT-NAME>/<LABEL>.json" -d '{"query":"from:TwitterDev lang:en","maxResults":"500","fromDate":"<yyyymmddhhmm>","toDate":"<yyyymmddhhmm>"}'

Data endpoint 的响应载荷

从 API 请求返回的载荷将以 JSON 格式呈现,如下所示。
{
	"results": [
		{
			"created_at": "Fri Nov 02 17:18:31 +0000 2018",
			"id": 1058408022936977409,
			"id_str": "1058408022936977409",
			"text": "RT @harmophone: \"Tagboard、Twitter 和 TEGNA 合作实现的创新众包正在发掘本地相关对话…",
			"source": "<a href=\"http:\/\/twitter.com\" rel=\"nofollow\">Twitter Web Client<\/a>",
			"truncated": false,
			"in_reply_to_status_id": null,
			"in_reply_to_status_id_str": null,
			"in_reply_to_user_id": null,
			"in_reply_to_user_id_str": null,
			"in_reply_to_screen_name": null,
			"user": {
				"id": 2244994945,
				"id_str": "2244994945",
				"name": "Twitter Dev",
				"screen_name": "TwitterDev",
				"location": "互联网",
				"url": "https:\/\/developer.x.com\/",
				"description": "您获取 Twitter 平台新闻、更新和活动的官方来源。需要技术帮助?请访问 https:\/\/devcommunity.com\/ ⌨️ #TapIntoTwitter",
				"translator_type": "null",
				"protected": false,
				"verified": true,
				"followers_count": 503828,
				"friends_count": 1477,
				"listed_count": 1437,
				"favourites_count": 2199,
				"statuses_count": 3380,
				"created_at": "Sat Dec 14 04:35:55 +0000 2013",
				"utc_offset": null,
				"time_zone": null,
				"geo_enabled": true,
				"lang": "en",
				"contributors_enabled": false,
				"is_translator": false,
				"profile_background_color": "null",
				"profile_background_image_url": "null",
				"profile_background_image_url_https": "null",
				"profile_background_tile": null,
				"profile_link_color": "null",
				"profile_sidebar_border_color": "null",
				"profile_sidebar_fill_color": "null",
				"profile_text_color": "null",
				"profile_use_background_image": null,
				"profile_image_url": "null",
				"profile_image_url_https": "https:\/\/pbs.twimg.com\/profile_images\/880136122604507136\/xHrnqf1T_normal.jpg",
				"profile_banner_url": "https:\/\/pbs.twimg.com\/profile_banners\/2244994945\/1498675817",
				"default_profile": false,
				"default_profile_image": false,
				"following": null,
				"follow_request_sent": null,
				"notifications": null
			},
			"geo": null,
			"coordinates": null,
			"place": null,
			"contributors": null,
			"retweeted_status": {
				"created_at": "Tue Oct 30 21:30:25 +0000 2018",
				"id": 1057384253116289025,
				"id_str": "1057384253116289025",
				"text": "\"Tagboard、Twitter 和 TEGNA 合作实现的创新众包正在发掘本地相关… https:\/\/t.co\/w46U5TRTzQ",
				"source": "<a href=\"http:\/\/twitter.com\" rel=\"nofollow\">Twitter Web Client<\/a>",
				"truncated": true,
				"in_reply_to_status_id": null,
				"in_reply_to_status_id_str": null,
				"in_reply_to_user_id": null,
				"in_reply_to_user_id_str": null,
				"in_reply_to_screen_name": null,
				"user": {
					"id": 175187944,
					"id_str": "175187944",
					"name": "Tyler Singletary",
					"screen_name": "harmophone",
					"location": "加利福尼亚州旧金山",
					"url": "http:\/\/medium.com\/@harmophone",
					"description": "@Tagboard 产品高级副总裁。曾在 @Klout 和 @LithiumTech 从事数据、业务和产品工作;@BBI 董事会成员;@Insightpool 顾问。世界上最糟糕的白板使用者。",
					"translator_type": "null",
					"protected": false,
					"verified": false,
					"followers_count": 1982,
					"friends_count": 1877,
					"listed_count": 245,
					"favourites_count": 23743,
					"statuses_count": 12708,
					"created_at": "Thu Aug 05 22:59:29 +0000 2010",
					"utc_offset": null,
					"time_zone": null,
					"geo_enabled": false,
					"lang": "en",
					"contributors_enabled": false,
					"is_translator": false,
					"profile_background_color": "null",
					"profile_background_image_url": "null",
					"profile_background_image_url_https": "null",
					"profile_background_tile": null,
					"profile_link_color": "null",
					"profile_sidebar_border_color": "null",
					"profile_sidebar_fill_color": "null",
					"profile_text_color": "null",
					"profile_use_background_image": null,
					"profile_image_url": "null",
					"profile_image_url_https": "https:\/\/pbs.twimg.com\/profile_images\/719985428632240128\/WYFHcK-m_normal.jpg",
					"profile_banner_url": "https:\/\/pbs.twimg.com\/profile_banners\/175187944\/1398653841",
					"default_profile": false,
					"default_profile_image": false,
					"following": null,
					"follow_request_sent": null,
					"notifications": null
				},
				"geo": null,
				"coordinates": null,
				"place": null,
				"contributors": null,
				"is_quote_status": false,
				"extended_tweet": {
					"full_text": "\"Tagboard、Twitter 和 TEGNA 合作实现的创新众包正在实时发掘本地相关对话,并使选民能够在辩论期间提问,\" -- @adamostrow,@TEGNA\n了解更多:https:\/\/t.co\/ivAFtanfje",
					"display_text_range": [
						0,
						259
					],
					"entities": {
						"hashtags": [],
						"urls": [
							{
								"url": "https:\/\/t.co\/ivAFtanfje",
								"expanded_url": "https:\/\/blog.tagboard.com\/twitter-and-tagboard-collaborate-to-bring-best-election-content-to-news-outlets-with-tagboard-e85fc864bcf4",
								"display_url": "blog.tagboard.com\/twitter-and-ta…",
								"unwound": {
									"url": "https:\/\/blog.tagboard.com\/twitter-and-tagboard-collaborate-to-bring-best-election-content-to-news-outlets-with-tagboard-e85fc864bcf4",
									"status": 200,
									"title": "Twitter 和 Tagboard 合作通过 Tagboard 为新闻媒体带来最佳选举内容…",
									"description": "作者:Tyler Singletary,Tagboard 产品负责人"
								},
								"indices": [
									236,
									259
								]
							}
						],
						"user_mentions": [
							{
								"screen_name": "adamostrow",
								"name": "Adam Ostrow",
								"id": 5695942,
								"id_str": "5695942",
								"indices": [
									204,
									215
								]
							},
							{
								"screen_name": "TEGNA",
								"name": "TEGNA",
								"id": 34123003,
								"id_str": "34123003",
								"indices": [
									217,
									223
								]
							}
						],
						"symbols": []
					}
				},
				"quote_count": 0,
				"reply_count": 1,
				"retweet_count": 6,
				"favorite_count": 19,
				"entities": {
					"hashtags": [],
					"urls": [
						{
							"url": "https:\/\/t.co\/w46U5TRTzQ",
							"expanded_url": "https:\/\/twitter.com\/i\/web\/status\/1057384253116289025",
							"display_url": "twitter.com\/i\/web\/status\/1…",
							"indices": [
								117,
								140
							]
						}
					],
					"user_mentions": [],
					"symbols": []
				},
				"favorited": false,
				"retweeted": false,
				"possibly_sensitive": false,
				"filter_level": "low",
				"lang": "en"
			},
			"is_quote_status": false,
			"quote_count": 0,
			"reply_count": 0,
			"retweet_count": 0,
			"favorite_count": 0,
			"entities": {
				"hashtags": [],
				"urls": [],
				"user_mentions": [
					{
						"screen_name": "harmophone",
						"name": "Tyler Singletary",
						"id": 175187944,
						"id_str": "175187944",
						"indices": [
							3,
							14
						]
					}
				],
				"symbols": []
			},
			"favorited": false,
			"retweeted": false,
			"filter_level": "low",
			"lang": "en",
			"matching_rules": [
				{
					"tag": null
				}
			]
		}
	],
	"requestParameters": {
		"maxResults": 100,
		"fromDate": "201811010000",
		"toDate": "201811060000"
	}
}

访问 counts endpoint

使用 counts endpoint,我们将按 day 分组检索来自 @XDevelopers 账户且为英文的 Post 数量。
  • cURL
  • cURL example
cURL 是一款使用 URL 语法来获取或发送文件的命令行工具。完成以下替换后,将下面的 cURL 请求复制到命令行中:
  • Username <USERNAME>,例如 email@domain.com
  • Account name <ACCOUNT-NAME>,例如 john-doe
  • Label <LABEL>,例如 prod
  • fromDate 和 toDate,例如 "fromDate":"201811010000", "toDate":"201811122359"
发送请求后,系统将提示你输入密码。
curl -X POST -u<USERNAME> "https://gnip-api.x.com/search/30day/accounts/<ACCOUNT-NAME>/<LABEL>/counts.json" -d '{"query":"from:TwitterDev lang:en","fromDate":"<yyyymmddhhmm>","toDate":"<yyyymmddhhmm>","bucket":"day"}'

Counts endpoint 响应负载

通过 API 请求返回的负载将以 JSON 格式呈现,如下所示。
{
	"results": [
		{
			"timePeriod": "201811010000",
			"count": 0
		},
		{
			"timePeriod": "201811020000",
			"count": 1
		},
		{
			"timePeriod": "201811030000",
			"count": 0
		},
		{
			"timePeriod": "201811040000",
			"count": 0
		},
		{
			"timePeriod": "201811050000",
			"count": 0
		}
	],
	"totalCount": 1,
	"requestParameters": {
		"bucket": "day",
		"fromDate": "201811010000",
		"toDate": "201811060000"
	}
}
做得好!你已成功访问 Enterprise Search Posts: 30-Day API。
参考文章

开始使用 Enterprise Search Posts:Full-Archive API

Enterprise Search Posts:Full-Archive API 可提供自 2006 年首条发布以来的所有 Posts。系统会根据你在请求中指定的 query(查询)匹配 Posts 并返回结果。query 是一条规则,用于定义返回的 Post 应包含的内容。在本教程中,我们将搜索来自 X 账号 @XDevelopers、语言为英语的 Posts。 响应负载中的 Posts 可以是 data 格式(提供完整的 Post 负载),也可以是 counts 格式(提供匹配 Posts 的数值统计数据)。我们将使用 cURL 向 data 和 counts 的 endpoints 发起请求。 你需要准备以下内容:

访问 data endpoint

data endpoint 将向我们返回匹配到的 Posts 的完整 Post 载荷。我们将使用 from:lang: 运算符来查找来自 @XDevelopers 且语言为英文的 Posts。更多运算符请点击此处
  • cURL
  • cURL example
cURL 是一款使用 URL 语法来获取或发送文件的命令行工具。根据以下说明进行替换后,将下面的 cURL 请求复制到命令行中:
  • Username <USERNAME>,例如 email@domain.com
  • Account name <ACCOUNT-NAME>,例如 john-doe
  • Label <LABEL>,例如 prod
  • fromDate 和 toDate,例如 "fromDate":"201802010000", "toDate":"201802282359"
发送请求后,系统会提示你输入密码。
curl -X POST -u<USERNAME> "https://gnip-api.x.com/search/fullarchive/accounts/<ACCOUNT-NAME>/<LABEL>.json" -d '{"query":"from:TwitterDev lang:en","maxResults":"500","fromDate":"<yyyymmddhhmm>","toDate":"<yyyymmddhhmm>"}'
数据 endpoint 的响应载荷
你的 API 请求返回的载荷将以 JSON 格式呈现,如下所示。
{
	"results": [
		{
			"created_at": "Fri Nov 02 17:18:31 +0000 2018",
			"id": 1058408022936977409,
			"id_str": "1058408022936977409",
			"text": "RT @harmophone: \"Tagboard、Twitter 和 TEGNA 合作实现的创新众包正在发掘本地相关对话…",
			"source": "<a href=\"http:\/\/twitter.com\" rel=\"nofollow\">Twitter Web Client<\/a>",
			"truncated": false,
			"in_reply_to_status_id": null,
			"in_reply_to_status_id_str": null,
			"in_reply_to_user_id": null,
			"in_reply_to_user_id_str": null,
			"in_reply_to_screen_name": null,
			"user": {
				"id": 2244994945,
				"id_str": "2244994945",
				"name": "Twitter Dev",
				"screen_name": "TwitterDev",
				"location": "互联网",
				"url": "https:\/\/developer.x.com\/",
				"description": "您获取 Twitter 平台新闻、更新和活动的官方来源。需要技术帮助?请访问 https:\/\/devcommunity.com\/ ⌨️ #TapIntoTwitter",
				"translator_type": "null",
				"protected": false,
				"verified": true,
				"followers_count": 503828,
				"friends_count": 1477,
				"listed_count": 1437,
				"favourites_count": 2199,
				"statuses_count": 3380,
				"created_at": "Sat Dec 14 04:35:55 +0000 2013",
				"utc_offset": null,
				"time_zone": null,
				"geo_enabled": true,
				"lang": "en",
				"contributors_enabled": false,
				"is_translator": false,
				"profile_background_color": "null",
				"profile_background_image_url": "null",
				"profile_background_image_url_https": "null",
				"profile_background_tile": null,
				"profile_link_color": "null",
				"profile_sidebar_border_color": "null",
				"profile_sidebar_fill_color": "null",
				"profile_text_color": "null",
				"profile_use_background_image": null,
				"profile_image_url": "null",
				"profile_image_url_https": "https:\/\/pbs.twimg.com\/profile_images\/880136122604507136\/xHrnqf1T_normal.jpg",
				"profile_banner_url": "https:\/\/pbs.twimg.com\/profile_banners\/2244994945\/1498675817",
				"default_profile": false,
				"default_profile_image": false,
				"following": null,
				"follow_request_sent": null,
				"notifications": null
			},
			"geo": null,
			"coordinates": null,
			"place": null,
			"contributors": null,
			"retweeted_status": {
				"created_at": "Tue Oct 30 21:30:25 +0000 2018",
				"id": 1057384253116289025,
				"id_str": "1057384253116289025",
				"text": "\"Tagboard、Twitter 和 TEGNA 合作实现的创新众包正在发掘本地相关… https:\/\/t.co\/w46U5TRTzQ",
				"source": "<a href=\"http:\/\/twitter.com\" rel=\"nofollow\">Twitter Web Client<\/a>",
				"truncated": true,
				"in_reply_to_status_id": null,
				"in_reply_to_status_id_str": null,
				"in_reply_to_user_id": null,
				"in_reply_to_user_id_str": null,
				"in_reply_to_screen_name": null,
				"user": {
					"id": 175187944,
					"id_str": "175187944",
					"name": "Tyler Singletary",
					"screen_name": "harmophone",
					"location": "加利福尼亚州旧金山",
					"url": "http:\/\/medium.com\/@harmophone",
					"description": "@Tagboard 产品高级副总裁。曾在 @Klout 和 @LithiumTech 从事数据、业务和产品工作;@BBI 董事会成员;@Insightpool 顾问。世界上最糟糕的白板使用者。",
					"translator_type": "null",
					"protected": false,
					"verified": false,
					"followers_count": 1982,
					"friends_count": 1877,
					"listed_count": 245,
					"favourites_count": 23743,
					"statuses_count": 12708,
					"created_at": "Thu Aug 05 22:59:29 +0000 2010",
					"utc_offset": null,
					"time_zone": null,
					"geo_enabled": false,
					"lang": "en",
					"contributors_enabled": false,
					"is_translator": false,
					"profile_background_color": "null",
					"profile_background_image_url": "null",
					"profile_background_image_url_https": "null",
					"profile_background_tile": null,
					"profile_link_color": "null",
					"profile_sidebar_border_color": "null",
					"profile_sidebar_fill_color": "null",
					"profile_text_color": "null",
					"profile_use_background_image": null,
					"profile_image_url": "null",
					"profile_image_url_https": "https:\/\/pbs.twimg.com\/profile_images\/719985428632240128\/WYFHcK-m_normal.jpg",
					"profile_banner_url": "https:\/\/pbs.twimg.com\/profile_banners\/175187944\/1398653841",
					"default_profile": false,
					"default_profile_image": false,
					"following": null,
					"follow_request_sent": null,
					"notifications": null
				},
				"geo": null,
				"coordinates": null,
				"place": null,
				"contributors": null,
				"is_quote_status": false,
				"extended_tweet": {
					"full_text": "\"Tagboard、Twitter 和 TEGNA 合作实现的创新众包正在实时发掘本地相关对话,并使选民能够在辩论期间提问,\" -- @adamostrow,@TEGNA\n了解更多:https:\/\/t.co\/ivAFtanfje",
					"display_text_range": [
						0,
						259
					],
					"entities": {
						"hashtags": [],
						"urls": [
							{
								"url": "https:\/\/t.co\/ivAFtanfje",
								"expanded_url": "https:\/\/blog.tagboard.com\/twitter-and-tagboard-collaborate-to-bring-best-election-content-to-news-outlets-with-tagboard-e85fc864bcf4",
								"display_url": "blog.tagboard.com\/twitter-and-ta…",
								"unwound": {
									"url": "https:\/\/blog.tagboard.com\/twitter-and-tagboard-collaborate-to-bring-best-election-content-to-news-outlets-with-tagboard-e85fc864bcf4",
									"status": 200,
									"title": "Twitter 和 Tagboard 合作通过 Tagboard 为新闻媒体带来最佳选举内容…",
									"description": "作者:Tyler Singletary,Tagboard 产品负责人"
								},
								"indices": [
									236,
									259
								]
							}
						],
						"user_mentions": [
							{
								"screen_name": "adamostrow",
								"name": "Adam Ostrow",
								"id": 5695942,
								"id_str": "5695942",
								"indices": [
									204,
									215
								]
							},
							{
								"screen_name": "TEGNA",
								"name": "TEGNA",
								"id": 34123003,
								"id_str": "34123003",
								"indices": [
									217,
									223
								]
							}
						],
						"symbols": []
					}
				},
				"quote_count": 0,
				"reply_count": 1,
				"retweet_count": 6,
				"favorite_count": 19,
				"entities": {
					"hashtags": [],
					"urls": [
						{
							"url": "https:\/\/t.co\/w46U5TRTzQ",
							"expanded_url": "https:\/\/twitter.com\/i\/web\/status\/1057384253116289025",
							"display_url": "twitter.com\/i\/web\/status\/1…",
							"indices": [
								117,
								140
							]
						}
					],
					"user_mentions": [],
					"symbols": []
				},
				"favorited": false,
				"retweeted": false,
				"possibly_sensitive": false,
				"filter_level": "low",
				"lang": "en"
			},
			"is_quote_status": false,
			"quote_count": 0,
			"reply_count": 0,
			"retweet_count": 0,
			"favorite_count": 0,
			"entities": {
				"hashtags": [],
				"urls": [],
				"user_mentions": [
					{
						"screen_name": "harmophone",
						"name": "Tyler Singletary",
						"id": 175187944,
						"id_str": "175187944",
						"indices": [
							3,
							14
						]
					}
				],
				"symbols": []
			},
			"favorited": false,
			"retweeted": false,
			"filter_level": "low",
			"lang": "en",
			"matching_rules": [
				{
					"tag": null
				}
			]
		}
	],
	"requestParameters": {
		"maxResults": 100,
		"fromDate": "201811010000",
		"toDate": "201811060000"
	}
}

访问 counts endpoint

使用 counts endpoint,我们将按 day 分组检索来自 @XDevelopers 账户、语言为英语的 Post 数量。
  • cURL
  • cURL example
cURL 是一款使用 URL 语法来获取或发送文件的命令行工具。在完成以下替换后,将下述 cURL 请求复制到你的命令行中:
  • Username <USERNAME>,例如 email@domain.com
  • Account name <ACCOUNT-NAME>,例如 john-doe
  • Label <LABEL>,例如 prod
  • fromDate 和 toDate,例如 "fromDate":"201802010000", "toDate":"201802282359"
发送请求后,系统会提示你输入密码。
curl -X POST -u<USERNAME> "https://gnip-api.x.com/search/fullarchive/accounts/<ACCOUNT-NAME>/<LABEL>/counts.json" -d '{"query":"from:TwitterDev lang:en","fromDate":"<yyyymmddhhmm>","toDate":"<yyyymmddhhmm>","bucket":"day"}'

Counts endpoint 响应载荷

从 API 请求返回的载荷将以 JSON 格式呈现,如下所示。
{
	"results": [
		{
			"timePeriod": "201811010000",
			"count": 0
		},
		{
			"timePeriod": "201811020000",
			"count": 1
		},
		{
			"timePeriod": "201811030000",
			"count": 0
		},
		{
			"timePeriod": "201811040000",
			"count": 0
		},
		{
			"timePeriod": "201811050000",
			"count": 0
		}
	],
	"totalCount": 1,
	"requestParameters": {
		"bucket": "day",
		"fromDate": "201811010000",
		"toDate": "201811060000"
	}
}
做得好!你已成功访问 Enterprise Search Posts: Full-Archive API。
参考资料

指南

构建搜索查询

Enterprise 运算符

以下是 X 的 Enterprise 搜索 API 支持的所有运算符:
  • Enterprise 30 天搜索 API
  • Enterprise 全量归档搜索 API
有关各产品可用运算符的并排对比,请参见此处
操作符描述
keyword匹配 Post 正文或 URL 中的分词关键词。这是一种分词匹配,即您的关键词字符串将与 Post 正文的分词文本进行匹配——分词基于标点符号、符号和分隔符 Unicode 基本平面字符。例如,包含文本”I like coca-cola”的 Post 将被分割为以下词元:I、like、coca、cola。然后将这些词元与您规则中使用的关键词字符串进行比较。要匹配包含标点符号(例如 coca-cola)、符号或分隔符字符的字符串,您必须使用下面描述的引号精确匹配。

注意: 在 Search API 中,重音符号和特殊字符会被标准化为标准拉丁字符,这可能会改变外语的含义或返回意外结果:
例如,“músic”将匹配”music”,反之亦然。
例如,西班牙语中的常见短语”Feliz Año Nuevo!”将被索引为”Feliz Ano Nuevo”,这改变了短语的含义。

注意: 此操作符将匹配 Post 中的 URL 和展开的 URL。
emoji匹配 Post 正文中的表情符号。表情符号是分词匹配,即您的表情符号将与 Post 正文的分词文本进行匹配——分词基于标点符号、符号/表情符号和分隔符 Unicode 基本平面字符。例如,包含文本”I like “的 Post 将被分割为以下词元:I、like、。然后将这些词元与您规则中使用的表情符号进行比较。请注意,如果表情符号有变体,您必须使用”引号”将其添加到规则中。
“exact phrase match”匹配 Post 正文或 URL 中的分词和有序短语。这是一种分词匹配,即您的关键词字符串将与 Post 正文的分词文本进行匹配——分词基于标点符号、符号和分隔符 Unicode 基本平面字符。

注意: 标点符号不会被分词,而是被视为空白字符。
例如,引号中的”#hashtag”将匹配”hashtag”但不匹配 #hashtag(使用不带引号的 hashtag # 操作符来匹配实际的话题标签)。
例如,引号中的”cashtag&quot;将匹配&quot;cashtag&quot;但不匹配 cashtag(使用不带引号的 cashtag $ 操作符来匹配实际的股票标签)。
例如,“Love Snow”将匹配”#love #snow”
例如,“#Love #Snow”将匹配”love snow”

注意: 此操作符将匹配 Post 中的 URL 和展开的 URL。
“keyword1 keyword2”~N通常称为邻近操作符,匹配关键词之间不超过 N 个词元的 Post。

如果关键词顺序相反,它们之间不能超过 N-2 个词元。引号中可以包含任意数量的关键词。N 不能大于 6。

请注意,此操作符仅在 enterprise 搜索 API 中可用。
from:匹配来自特定用户的任何 Post。
该值必须是用户的 X 数字账户 ID 或用户名(不包括 @ 字符)。查找数字 X 账户 ID 的方法请参见此处此处
to:匹配回复特定用户的任何 Post。

该值必须是用户的数字账户 ID 或用户名(不包括 @ 字符)。查找数字 X 账户 ID 的方法请参见此处
url:对 Post 的展开 URL 执行分词(关键词/短语)匹配(类似于 url_contains)。包含标点符号或特殊字符的词元和短语应使用双引号。例如,url:“/developer”。虽然通常不建议,但如果您想匹配特定协议,请用双引号括起来:url:“https://developer.x.com&quot;。
注意: 使用 PowerTrack 或 Historical PowerTrack 时,此操作符将匹配引用 Post 原始 Post 中包含的 URL。例如,如果您的规则包含 url:“developer.x.com”,并且某个 Post 包含该 URL,则该 Post 的任何引用 Tweet 都将包含在结果中。使用 Search API 时情况并非如此。
#匹配包含给定话题标签的任何 Post。

此操作符执行精确匹配,而非分词匹配,即规则”2016”将匹配包含确切话题标签”2016”的 Post,但不匹配包含话题标签”2016election”的 Post

注意:话题标签操作符依赖 X 的实体提取来匹配话题标签,而不是从正文本身提取话题标签。有关 X 实体 JSON 属性的更多信息,请参见此处
@匹配提及给定用户名的任何 Post。
to: 操作符返回 @mention 操作符的子集匹配。
$匹配包含指定”股票标签”的任何 Post(其中词元的前导字符是”$“字符)。

请注意,股票标签操作符依赖 X 的”符号”实体提取来匹配股票标签,而不是尝试从正文本身提取股票标签。有关 X 实体 JSON 属性的更多信息,请参见此处

请注意,此操作符仅在 enterprise 搜索 API 中可用。

retweets_of:可用别名:retweets_of_user:
匹配指定用户的转发 Post。接受用户名和数字 X 账户 ID(不是 Post 状态 ID)。查找数字 X 账户 ID 的方法请参见此处
lang:匹配被 X 分类为特定语言的 Post(当且仅当该 Post 已被分类时)。需要注意的是,每个 Post 目前只被分类为一种语言,因此将多种语言进行 AND 操作将不会产生任何结果。

注意: 如果无法进行语言分类,提供的结果是”und”(表示未定义)。

下面的列表表示当前支持的语言及其对应的 BCP 47 语言标识符:
阿姆哈拉语: am德语: de马拉雅拉姆语: ml斯洛伐克语: sk
阿拉伯语: ar希腊语: el迪维希语: dv斯洛文尼亚语: sl
亚美尼亚语: hy古吉拉特语: gu马拉地语: mr索拉尼库尔德语: ckb
巴斯克语: eu海地克里奥尔语: ht尼泊尔语: ne西班牙语: es
孟加拉语: bn希伯来语: iw挪威语: no瑞典语: sv
波斯尼亚语: bs印地语: hi奥里亚语: or他加禄语: tl
保加利亚语: bg拉丁字母印地语: hi-Latn旁遮普语: pa泰米尔语: ta
缅甸语: my匈牙利语: hu普什图语: ps泰卢固语: te
克罗地亚语: hr冰岛语: is波斯语: fa泰语: th
加泰罗尼亚语: ca印度尼西亚语: in波兰语: pl藏语: bo
捷克语: cs意大利语: it葡萄牙语: pt繁体中文: zh-TW
丹麦语: da日语: ja罗马尼亚语: ro土耳其语: tr
荷兰语: nl卡纳达语: kn俄语: ru乌克兰语: uk
英语: en高棉语: km塞尔维亚语: sr乌尔都语: ur
爱沙尼亚语: et韩语: ko简体中文: zh-CN维吾尔语: ug
芬兰语: fi老挝语: lo信德语: sd越南语: vi
法语: fr拉脱维亚语: lv僧伽罗语: si威尔士语: cy
格鲁吉亚语: ka立陶宛语: lt
place:匹配带有指定位置或 X place ID(见示例)标签的 Post。多词地点名称(“New York City”“Palo Alto”)应使用引号括起。

注意:有关如何获取 X place ID,请参阅公共 API endpoint GET geo/search

注意:此运算符不会匹配转发,因为转发的地点附加在原始 Post 上。对于引用推文的原始 Post 所附加的地点也不会匹配。
place_country:匹配其所标记的place关联国家/地区代码与给定 ISO 双字母代码相同的 Post。

有效的 ISO 代码可在此处查看:http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2

注意:此运算符不会匹配转发,因为转发的地点附加在原始 Post 上。对于引用推文的原始 Post 所附加的地点也不会匹配。
point_radius:[lon lat radius]在存在时,匹配 Post 的精确位置(x, y);并且在 X 中,匹配“Place”地理多边形,前提是该 Place 完全包含在定义的区域内。

* 支持的半径单位为英里(mi)和千米(km)。
* 半径必须小于 25 mi。
* 经度范围为 ±180。
* 纬度范围为 ±90。
* 所有坐标均为十进制度。
* 规则参数置于方括号内,并以空格分隔。

注意:此运算符不会匹配转发,因为转发的地点附加在原始 Post 上。对于引用推文的原始 Post 所附加的地点也不会匹配。
bounding_box:[west_long south_lat east_long north_lat]可用别名:geo_bounding_box:

在存在时,匹配 Post 的精确位置(long, lat);并且在 X 中,匹配“Place”地理多边形,前提是该 Place 完全包含在定义的区域内。

* west_long 与 south_lat 表示边界框的西南角,其中 west_long 为该点的经度,south_lat 为该点的纬度。
* east_long 与 north_lat 表示边界框的东北角,其中 east_long 为该点的经度,north_lat 为该点的纬度。
* 边界框的宽度和高度必须小于 25 mi。
* 经度范围为 ±180。
* 纬度范围为 ±90。
* 所有坐标均为十进制度。
* 规则参数置于方括号内,并以空格分隔。
注意:此运算符不会匹配转发,因为转发的地点附加在原始 Post 上。对于引用推文的原始 Post 所附加的地点也不会匹配。
profile_country:对 Profile Geo 增强数据中“address”对象的“countryCode”字段进行精确匹配。
使用基于 ISO-3166-1-alpha-2 规范的标准化两字母国家/地区代码。为简洁起见,提供此运算符以替代针对“address”对象中“country”字段的运算符。
profile_region:匹配 Profile Geo 增强数据中“address”对象的“region”字段。

为精确的完整字符串匹配。无需使用反斜杠进行转义。例如,匹配包含斜杠的内容时,使用“one/two”,而非“one/two”。匹配包含空格或标点的子字符串时,请使用双引号。
profile_locality:匹配 Profile Geo 增强数据中“address”对象的“locality”字段。

为精确的完整字符串匹配。无需使用反斜杠进行转义。例如,匹配包含斜杠的内容时,使用“one/two”,而非“one/two”。匹配包含空格或标点的子字符串时,请使用双引号。
注意: 使用 Search API 时,所有 is: 与 has: 运算符都不能单独使用,必须与其他子句组合。例如:@XDeevelopers has:links
has:geo匹配包含X提供的Post特定地理位置数据的Post。这可以是”geo”经纬度坐标,或者是X “Place”形式的”location”,包含相应的显示名称、地理多边形和其他字段。



注意: 使用Search API时,此操作符必须与其他不包含is:has:的操作符结合使用。
has:profile_geo可用别名: has:derived_user_geo

匹配包含任何Profile Geo metadata的Post,无论实际值如何。


注意: 使用Search API时,此操作符必须与其他不包含is:has:的操作符结合使用。
has:links此操作符匹配消息正文中包含链接的Post。


注意: 使用Search API时,此操作符必须与其他不包含is:has:的操作符结合使用。
is:retweet仅传递匹配规则的显式转发。也可以取反以排除匹配规则的转发,仅传递原创内容。

此操作符仅查找使用X转发功能的真正转发。引用Tweet和不使用X转发功能的修改Post不会被此操作符匹配。



注意: 使用Search API时,此操作符必须与其他不包含is:has:的操作符结合使用。
is:reply用于根据Post是否为Post回复来过滤Post的操作符。仅传递匹配规则的显式回复。也可以取反以排除匹配规则的回复。

请注意,此操作符适用于付费高级版和企业搜索,在沙盒开发环境中不可用。



注意: 使用Search API时,此操作符必须与其他不包含is:has:的操作符结合使用。
is:quote仅传递引用Tweet,或引用另一个Post的Post,通过Post载荷中的”is_quote_status”:true标识。也可以取反以排除引用Tweet。

注意: 使用Search API时,此操作符必须与其他不包含is:has:的操作符结合使用。
is:verified仅传递作者被X”认证”的Post。也可以取反以排除作者已认证的Post。


注意: 使用Search API时,此操作符必须与其他不包含is:has:的操作符结合使用。
has:mentions匹配提及另一个X用户的Post。


注意: 使用Search API时,此操作符必须与其他不包含is:has:的操作符结合使用。
has:hashtags匹配包含话题标签的Post。


注意: 使用Search API时,此操作符必须与其他不包含is:has:的操作符结合使用。
has:media可用别名: has:media_link

匹配包含X分类的媒体url的Post。例如,pic.x.com。


注意: 使用Search API时,此操作符必须与其他不包含is:has:的操作符结合使用。
has:images匹配包含X分类的媒体url的Post。例如,pic.x.com。


注意: 使用Search API时,此操作符必须与其他不包含is:has:的操作符结合使用。
has:videos可用别名: has:video_link

匹配包含直接上传到X的原生X视频的Post。这不会匹配使用Vine、Periscope创建的视频或包含其他视频托管网站链接的Post。


注意: 使用Search API时,此操作符必须与其他不包含is:has:的操作符结合使用。
has:symbols匹配包含现金标签符号(带有前导’&#39;字符,例如tag)的Post。请注意,此操作符仅在enterprise搜索API中可用。


注意: 使用Search API时,此操作符必须与其他不包含is:has:的操作符结合使用。

产品概览

Enterprise 等级的 Full-archive Search 于 2015 年 8 月发布,premium 等级版本于 2018 年 2 月发布。这些搜索产品使客户能够即时访问任何公开可用的 Post。使用 Full-archive Search,您只需提交一个 query(查询),即可按照经典的 RESTful 方式获得响应。Full-archive Search 实现了每次响应最多 500 条 Post 的分页,并支持 premium 每分钟最多 60 次请求(rpm)的速率限制,enterprise 为 120 rpm。基于这些特性,Full-archive Search 可用于快速检索 Post,并可通过并发请求实现大规模获取。 与基于磁盘上一组 Post 扁平文件构建归档的 Historical PowerTrack 不同,Full-archive Search 的 Post 归档更类似在线数据库。与所有数据库一样,它支持对其内容进行查询;同时利用索引以实现高性能的数据检索。对于 Full-archive Search 的 endpoint,其查询语言由 PowerTrack Operators 组成,每个 Operator 都对应一个已建立索引的 Post JSON 属性。 同样地,与 Historical PowerTrack 一样,存在在发出 query(查询)时以当前为准的 Post 属性。举例来说,如果您今天使用 Search API 访问一条发布于 2010 年的 Post,那么该用户的个人资料描述、账户“home”所在地、显示名称,以及 Favorites 和 Retweet 计数等 Post 度量将会更新为今天的数值,而非 2010 年时的数值。 

元数据时间线

下面是 Full-archive search endpoint 中各类运算符开始生效匹配的时间线。在某些情况下,运算符的匹配开始时间远晚于某种在 X 上已成为常态的“沟通约定”。例如,@Replies 作为一种用户约定早在 2006 年就出现了,但直到 2007 年初才在配套 JSON 的支持下成为“一等对象”或“事件”。因此,2006 年要对 @Replies 进行匹配,需要检查 Post 正文,而不能依赖 to:in_reply_to_status_id: 这类 PowerTrack 运算符。 这里提供的细节是使用 Full-Archive Search(来自数百次搜索的结果)生成的。该时间线并非 100% 完整或精确。如果你发现了对你的用例至关重要的其他过滤/元数据“诞生日”,请告知我们。 请注意,底层的搜索索引可能会被重建。因此,这些时间线细节可能会发生变化。

2006

  • 3月26日 - lang:。在生成搜索索引时回填 Post metadata 的示例。
  • 7月13日 - has:mentions 开始匹配。
  • 10月6日 - has:symbols。用于讨论股票代码的 cashtags(或symbols)直到2009年初才变得常见。在此之前,大多数用法可能只是俚语(例如cashtags(或 symbols)直到 2009 年初才变得常见。在此之前,大多数用法可能只是俚语(例如 slang)。
  • 10月26日 - has:links 开始匹配。
  • 11月23日 - has:hashtags 开始匹配。

2007

  • 1月30日 - 首个一等公民级 @reply(in_reply_to_user_id),reply_to_status_id: 开始生效匹配。
  • 8月23日 - Hashtag 作为组织主题和会话的通用约定出现。一周后首次得到实际应用。

2009

  • 5月15日 - is:retweet。请注意,此运算符从官方转发功能的“beta”发布版本及其“Via @”模式开始匹配。在该 beta 期间,Post 的动词为“post”,且原始 Post 不包含在有效负载中。
  • 8月13日 - 官方转发功能的最终版本发布,采用“RT @”模式,动词设为“share”,并引入包含原始 Post 的“retweet_status”属性(因此 JSON 有效负载的大小大约翻倍)。

2010

  • 3月6日 - has:geobounding_box:point_radius: 地理运算符开始生效并可用于匹配。
  • 8月28日 - has:videos(截至2015年2月,该运算符匹配包含指向特定视频托管网站(如 youtube.com、vimeo.com 和 vivo.com)链接的 Post)。

2011

  • 7 月 20 日 - has:mediahas:images 开始支持匹配。原生照片于 2010 年 8 月 9 日正式发布。

2014

  • 12月3日 - (约)部分 增强的 URL 元数据(包含 HTML 标题和描述)开始出现在负载中。增强的元数据在 2016 年 5 月更为完善地推出。

2015

  • 2月10日 - has:videos 可匹配 X 的“原生”视频。
  • 2月17日 - has:profile_geoprofile_country:profile_region:profile_locality: Profile Geo 运算符开始生效。
  • 2月17日 - place_country:place: Post 地理运算符开始生效。

2016

2017

  • 2 月 22 日 - 投票 metadata 以增强的原生格式提供。对此类 metadata 无对应的 Operators。

2022

  • 9月27日 - 自该日期起创建的所有 Post 对象均包含可用的“已编辑 Post”元数据。自该日期起,所有提供 Post 对象的 Enterprise endpoint 均已更新以提供此元数据。所提供的编辑元数据包括 edit_history 和 edit_controls 对象。对于 2022 年 9 月 27 日之前创建的 Posts,将不会返回这些元数据。目前,没有可用的 Enterprise Operator 与这些元数据匹配。要了解有关编辑 Post 元数据的更多信息,请参阅 Edit Posts fundamentals 页面。

2022

  • 9月29日 - 自该日期起创建的所有 Post 对象均提供已编辑 Post 的 metadata。自该日期起,所有返回 Post 对象的 Enterprise endpoint 也已更新以提供此 metadata。提供的编辑 metadata 包含 edit_history 和 edit_controls 对象。对于在 2022 年 9 月 27 日之前创建的 Posts,将不会返回这些 metadata。目前,没有可用的 Enterprise Operators 可与这些 metadata 匹配。要了解有关 Edit Post metadata 的更多信息,请参阅 Edit Posts fundamentals 页面。

过滤技巧

鉴于上述时间线信息,在编写 Search API 的过滤条件时确实需要考虑许多细节。需要重点注意两点:
  • 某些 metadata 带有“生效起始”日期,因此过滤可能会出现_假阴性_。这类搜索依赖的 Operators 使用了在整个或部分检索时段内尚不存在的 metadata。比如,如果你使用 has:images Operator 搜索 Post,在 2011 年 7 月之前将不会有任何匹配结果。原因是该 Operator 仅匹配_原生_照片(通过 X 的用户界面附加到 Post)。若要获得更完整的照片分享类 Post 数据集,2011 年 7 月之前的过滤条件需要包含匹配常见图片托管站点 URL 的规则子句。
  • 有些 metadata 是在 Post 发布到 X_之后_才被回填的。
在创建 PowerTrack 查询时,通常会关注以下几类属性:
  • X 个人资料
  • 原创或转发的 Post
  • Post 的语言分类
  • 带地理参照的 Post
  • 含分享链接的媒体
其中有些具有特定产品行为,另一些则行为一致。详见下文。

X 个人资料

Search API 会在检索时点返回历史 Post,并附带当时的用户个人资料数据集。如果你请求一条 2014 年的 Post,用户的个人资料 metadata 将反映其在 query(查询)时的状态。

原始 Post 和转发

PowerTrack _is:retweet_ 运算符可让用户包含或排除转发。使用该运算符的用户在处理 2009 年 8 月之前的 data 时,需要针对转发匹配(或不匹配)准备两种策略。对于 2009 年 8 月之前的时期,需要通过精确短语匹配检查 Post 消息本身是否符合 “@RT ” 模式(实际上,如果你在筛选 2009 年 5 月至 8 月之间的转发,还应包含 “Via @” 模式)。对于 2009 年 8 月之后的时期,可使用 _is:retweet_ 运算符。

Post 语言分类

在基于 Post 的语言分类进行过滤方面,X 的历史产品存在较大差异。构建 Search 归档时,所有 Post 都已用 X 的语言分类进行了回填。因此,lang: 运算符可用于整个 Post 归档。

对 Post 进行地理定位

对 Post 进行地理定位主要有三种方式:
  • Post 正文中的地理指代。 在 Post 正文中基于地理相关表述进行匹配,虽然通常最具挑战(因为依赖本地知识),但可用于整个 Post 存档。此处 是一个 2006 年的示例,基于“golden gate”筛选对旧金山地区进行地理定位匹配。
  • 用户为 Post 添加的地理标签(geo-tag)。 借助搜索 API,部分 Geo 运算符自 2010 年 3 月起即可用于匹配 Post,另一些则自 2015 年 2 月起可用:
    • 2010 年 3 月 6 日:has:geobounding_box:point_radius:
    • 2015 年 2 月 17 日:place_country:place:
  • 用户在账号资料中设置的“home”位置。 Profile Geo 运算符在 Historical PowerTrack 和 Search API 中均可用。对于 Search API,相关 Profile Geo metadata 自 2015 年 2 月起提供。对于早于 Profile Geo metadata 提供时间发布的 Post,可使用 bio_location: 运算符来匹配未经规范化的用户输入。
2012 年 3 月,推出“扩展 URL 富化”。在此之前,Post 负载仅包含用户提供的 URL。因此,如果用户包含的是短链接,想要匹配到感兴趣的(已展开)URL 会比较困难。对于 Search API,这些 metadata 自 2012 年 3 月起可用。 2016 年 7 月,推出“增强 URL 富化”。该增强版本会在 Post 负载中提供网站的 HTML 标题和描述,并提供用于匹配它们的 Operators。这些 metadata 自 2014 年 12 月开始出现。 2016 年 9 月,X 引入“原生附件”,尾随的共享链接不再计入 140 个 Post 字符限制。这两种 URL 富化仍适用于此类共享链接。 以下为相关 Search Operators 开始生效的时间:
  • 2006 年 10 月 26 日 - has:links
  • 2011 年 7 月 20 日 - has:imageshas:media
  • 2011 年 8 月 - url:,配合扩展 URL 富化。早至 2006 年 9 月,(url:"spotify.com" OR url:gnip OR url:microsoft OR url:google OR url:youtube) 就能匹配 http://x.com/Adam/statuses/16602,尽管在 twitter_entities 和 gnip 对象中没有 urls[] metadata。“youtube.com” 是一个示例,说明在没有任何 urls[] metadata 的情况下,消息内容也会匹配 url:youtube。
  • 2015 年 2 月 10 日 - 面向原生视频的 has:videos。在 2010/08/28 至 2015/02/10 期间,该 Operator 会匹配包含指向部分视频托管站点(如 youtube.com、vimeo.com 和 vivo.com)链接的 Posts。
  • 2016 年 5 月 1 日 - 基于增强 URL 富化url_title:url_description:,全面可用。首批增强 URL metadata 自 2014 年 12 月开始出现。

常见问题(FAQ)

常见的 Search Post API 问题

counts endpoint 与 data endpoint 提供的结果之间存在已知差异。你可能会在结果中看到不一致,这是因为 counts endpoint 属于合规处理之前(即不会计入已删除的 Post、地理信息清理等),而 data endpoint 在交付时已完成合规处理,并会纳入所有合规事件。
这可能发生的原因有几种,包括:
  1. 您预期看到的 Post 来自受保护的账号
  2. data endpoint 会计入所有合规事件(这意味着已删除的 Posts、被清除的地理信息等将不会包含在响应中)。
这很可能是由于你不当使用了我们的高级规则和过滤功能所致。请在此处查阅我们的文档,并确保你了解构建规则时的相关限制。
是的,包括:
  • Tweepy - 适用于使用标准的搜索/Posts 产品(Python)
  • X API - 适用于使用标准的 Search Post API(Python)
  • Search Posts PythonSearch Posts Ruby - 两款适用于 Enterprise(以及 v2!)Search Post API 的优秀工具
我们直接支持的所有库都可以在我们的 xdevplatform GitHub 页面找到:https://github.com/xdevplatform还有其他第三方库可能也很有帮助;不过请注意,其中一些可能无法与我们的高级和 Enterprise 产品配合使用。
是的。我们的 data endpoint 会在达到指定的 maxResults,或经过 30 天后进行分页。例如,如果在某个 30 天周期内你有 800 个 Post,则需要发起两次请求才能获取完整结果,因为每次请求最多返回 500 个 Post(maxResults)。再例如,如果第一个月只有 400 个 Post,第二个月有 100 个 Post,你同样需要发起两次请求才能获取完整结果,因为即使首次请求返回的 Post 少于指定的 maxResults,分页仍会在 30 天后发生。
Post 按时间倒序返回。例如,第一页结果将显示与 query(查询)匹配的最新 Post;分页将持续进行,直到结果中各 Post 的发布时间达到最初请求的 fromDate 为止。
仅原始 Post 会用于计费。任何后续编辑都会被忽略,不会计入您的总体活动量。Enterprise
我们的 Enterprise 解决方案提供可预测的定价,并可按需定制以满足您的业务需求。有关更多信息,请在此处提交申请。
  • 请参阅我们的 Enterprise Search Post API 文档此处
  • 有关规则与过滤的实用信息见此处
  • 有关使用 data endpoint 的实用信息见此处
  • 有关使用 counts endpoint 的实用信息见此处
  • 可用 operators 列表见此处
请联系您在 X 的客户经理,他们可以协助您处理此事。

错误排查指南

代码 404 - 未找到
  1. 请确保为各个 endpoint 使用了正确的参数(例如,buckets 字段只能与 counts endpoint 搭配使用,不能用于 data endpoint)
  2. 请再次确认 :product:account_name:label 字段是否正确。您可以在 GNIP Console 中找到 :label 字段(仅限 Enterprise 客户)。

API 参考

Enterprise 搜索 API

有两种 Enterprise 搜索 API:
  • 30-Day Search API - 提供过去 30 天内发布的 Tweets。
  • Full-Archive Search API - 提供最早可追溯到 2006 年的 Tweets,起始于 2006 年 3 月发布的第一条 Tweet。
这些搜索 API 采用统一的设计,以下文档适用于两者。请注意,对于自 2022 年 9 月 29 日起创建的 Tweets,Tweet 对象将包含描述其编辑历史的 Tweet 编辑 metadata。更多详情请参阅 “Edit Tweets” 基础知识页面。 以下是在集成 Enterprise 搜索 API 时需要了解的重要信息:
  • 请求 Tweet 数据与计数的方法
  • 身份验证
  • 分页
  • API 请求参数与示例请求
  • API 响应 JSON 负载与示例响应
  • HTTP 响应状态代码
Enterprise API 提供低延迟、全保真、基于 query(查询)的 Tweet 存档访问。这两个 API 的唯一区别在于可搜索的时间范围:要么是过去 30 天,要么是最早可追溯到 2006 年。时间范围可精确到分钟。Tweet 数据按时间倒序返回,从与您的 query 匹配的最新 Tweet 开始。Tweets 在发布后约 30 秒即可通过搜索 API 获取。

方法

Enterprise 搜索的基准 URI 为 https://gnip-api.x.com/search/
方法说明
POST /search/:product/accounts/:account_name/:label检索过去 30 天内与指定 PowerTrack 规则匹配的 Tweet。
POST /search/:product/accounts/:account_name/:label/counts检索过去 30 天内与指定 PowerTrack 规则匹配的 Tweet 数量。
说明:
  • :product 表示你要请求的搜索 endpoint,取值为 30dayfullarchive
  • :account_name 是与你账户关联的名称(区分大小写),如在 console.gnip.com 中所示
  • :label 是与你搜索 endpoint 关联的标签(区分大小写),如在 console.gnip.com 中所示
例如,如果 TwitterDev 账户启用了 30 天搜索产品,且标签为“prod”(production 的缩写),则搜索 endpoint 为: 你的完整 Enterprise 搜索 API endpoint 会显示在 https://console.gnip.com 下面提供了一些使用 curl(一个简单的 HTTP 工具)的示例请求。这些示例在 URL 中使用了 :product:account_name:label。要使用这些示例,请务必将 URL 替换为你的具体信息。

身份验证

对 Enterprise 搜索 API 的所有请求都必须使用 HTTP 基本身份验证(Basic Authentication),由用于登录你在 https://console.gnip.com 账户的有效电子邮件地址和密码组合构成。每个请求都必须在 Authorization 标头中传递这些凭据。

请求/响应行为

使用 fromDatetoDate 参数,您可以请求 API 支持的任意时间段。30-Day 搜索 API 提供最近 31 天内的 Tweets(尽管名为“30-Day” API,但为便于用户发起整月请求,实际可用范围为 31 天)。Full-Archive 搜索 API 提供可追溯至第一条 Tweet(2006 年 3 月 21 日)的 Tweets。不过,单个响应的返回将受限于您指定的 maxResults 或 31 天二者中较小的值。如果匹配的 data 或您的时间范围超过您指定的 maxResults 或 31 天,您将收到一个 next 令牌,应使用该令牌对指定时间范围的其余结果进行分页。 例如,假设您使用 Full-Archive 搜索,并希望获取 2017 年 1 月 1 日至 2017 年 6 月 30 日期间与您的 query(查询)匹配的所有 Tweets。您将在请求中使用 fromDatetoDate 参数指定这整整六个月的时间段。搜索 API 将返回第一“页” Tweets,其数量与您的 maxResults 参数相匹配(默认值为 100)。若还有更多 Tweets(通常会有),API 还会提供一个 next 令牌,使您能够请求下一“页”的 data。此过程将重复,直至 API 不再返回 next 令牌。有关更多详细信息,请参见下一节。 在发起数据请求和计数请求时,返回结果往往超过单个响应所能包含的数量。此时,响应会包含一个“next”令牌。该“next”令牌作为根级 JSON 属性提供。只要出现“next”令牌,就表示还有更多数据可获取,您需要继续发起 API 请求。 注意: “next”令牌在数据请求与计数请求中的行为略有差异。下文将分别说明,示例响应见 API 参考部分。
数据分页
数据请求通常会产生超过单次响应可返回的数量。每个数据请求都包含一个参数,用于设置每次请求返回的 Tweets 的最大数量。maxResults 参数的默认值为 100,可设置在 10–500 的范围内。如果你的 query 匹配的 Tweets 数量超过请求中使用的 maxResults 参数,响应将包含一个 next 令牌(作为根级 JSON 属性)。该 next 令牌用于后续请求,以获取该 query 的下一部分匹配的 Tweets(即下一“页”)。在到达该 query 的最后一“页”且不再提供 next 令牌之前,系统会持续返回 next 令牌。 要请求下一“页”数据,必须发起与原始请求完全相同的查询(如使用),包括 querytoDatefromDate 参数,并包含一个 next 请求参数,取值为上一个响应返回的值。这可用于 GET 或 POST 请求。但在 GET 请求中,必须对 next 参数进行 URL 编码。 你可以持续传入上一次 query 返回的 next 元素,直至获取到该 query 所覆盖时间段内的所有 Tweets。当收到的响应不包含 next 元素时,表示你已到达最后一页,指定的 query 和时间范围内不再有其他可用数据。
计数分页
“counts” endpoint 提供与 query(查询)关联的 Tweet 量级统计,可按天、小时或每分钟的粒度返回。“counts” API endpoint 将返回一个带时间戳的计数数组,最多覆盖 31 天的计数数据。如果请求超过 31 天的计数,将会返回一个 “next” 令牌。与 data 的 “next” 令牌相同,您必须使用与原始请求完全一致的 query,并在请求中包含一个名为 “next” 的参数,其值设为上一次响应返回的令牌。 除了请求超过 31 天的计数之外,还有另一种会返回 “next” 令牌的情形。对于高量级查询,生成计数所需时间可能足够长,从而触发响应超时。当发生这种情况时,您会收到少于 31 天的计数,但同时会返回一个 “next” 令牌,以便继续请求直至获取完整的计数数据。重要说明: 发生超时时仅会返回完整的 “bucket”(桶)——例如 2.5 天将返回 2 个完整的按日 “bucket”。
其他说明
  • 在搜索请求中使用 fromDate 或 toDate 时,您只会获得位于指定时间范围内的结果。当到达该时间范围内的最后一组结果时,您将不会收到“next”令牌。
  • “next”元素可与任意 10–500 范围内的 maxResults 值配合使用(默认值为 100)。maxResults 决定每个响应返回的 Tweet 数量,但不会阻止您最终获取全部结果。
  • “next”元素不会过期。使用相同“next” query 的多次请求将获得相同结果,而与请求时间无关。
  • 使用“next”参数对结果进行分页时,您可能会在 query 的边界处遇到重复项。您的应用程序应能够容忍这些重复。

data endpoint

POST /search/:product/:label
endpoint 模式:
此 endpoint 会根据指定的 query(查询)和时间范围返回 data。若未指定时间范围,时间参数将默认为过去 30 天。注意:也可通过使用 GET 请求(而非 POST)来实现此功能,只需将下述参数编码到 URL 中即可。
数据请求参数
参数说明是否必需示例值
query等同于一条 PowerTrack 规则,最多 2,048 个字符(正向和负向子句数量不设上限)。

该参数应包含 PowerTrack 规则的所有部分,包括所有运算符;规则的任何部分都不应拆分到 query 的其他参数中。

注意: 并非所有 PowerTrack 运算符都受支持。受支持的运算符列在此处
(snow OR cold OR blizzard) weather
tag可使用标签将规则及其匹配的 data 划分到不同的逻辑组中。若提供规则标签,该标签将包含在 ‘matching_rules’ 属性中。

建议为规则标签分配特定于规则的 UUID,并在客户端维护所需的映射关系。
8HYG54ZGTU
fromDate提供 Tweets 的最早 UTC 时间戳(使用 Full-Archive 搜索可追溯至 2006/3/21)。时间戳粒度为分钟,且为包含(例如 12:00 包含第 00 分钟)。

已指定: 仅使用 fromDate 而不提供 toDate 参数时,将返回从现在起向后回溯至 fromDate 的 query 结果。

未指定: 如果未指定 fromDate,API 将返回从 now() 起或至 toDate(若已指定)之前 30 天内的所有结果。

如果既未使用 fromDate 也未使用 toDate 参数,API 将返回最近 30 天内的所有结果,从请求时刻开始向后回溯。
201207220000
toDate提供 Tweets 的最新(最近)UTC 时间戳。时间戳粒度为分钟,且为不包含(例如 11:59 不包含该小时的第 59 分钟)。

已指定: 仅使用 toDate 而不提供 fromDate 参数时,将返回 toDate 之前最近 30 天的数据。

未指定: 如果未指定 toDate,API 将返回从 now() 起向后回溯至 fromDate 的 query 的所有结果。

如果既未使用 fromDate 也未使用 toDate 参数,API 将返回整个 30 天索引内的所有结果,从请求时刻开始向后回溯。
201208220000
maxResults单个请求可返回的搜索结果最大数量。取值范围为 10 到系统上限(当前为 500)。默认情况下,响应将返回 100 个结果。500
next用于获取下一“页”结果的参数,详见此处。该参数的取值直接来自 API 返回的响应,不应修改。NTcxODIyMDMyODMwMjU1MTA0
其他详细信息
可用时间范围30-Day:过去 31 天
Full-Archive:2006 年 3 月 21 日至今
Query 格式等同于一条 PowerTrack 规则,最多 2,048 个字符(正负子句数量不受限制)。

**注意:**并非所有 PowerTrack 运算符都受支持。有关受支持运算符的列表,请参见 Available operators
请求速率限制合作伙伴将在分钟级和秒级两个粒度上受到请求速率限制。每分钟的请求速率限制将依据合同在不同合作伙伴之间有所差异。但这些每分钟的限制并非用于一次性突发耗尽。无论您的每分钟请求速率限制是多少,所有合作伙伴每秒最多仅限 20 个请求,该限制在所有 data 和/或计数请求中聚合计算。
合规性通过 Full-Archive Search API 交付的所有数据在交付时均处于合规状态。
实时可用性数据在 X 平台生成后的 30 秒内即可被索引并可用
data 请求与响应示例
示例 POST 请求
  • 如下所示,POST 请求的请求参数通过 JSON 格式的请求体发送。
  • 需要查询的 PowerTrack 规则的所有组成部分(例如关键词、以及 bounding_box: 等其他运算符)都应放在 ‘query’ 参数中。
  • 请勿将规则的各个部分拆分为查询 URL 中的独立参数。
下面是一个用于发起初始数据请求的 POST(使用 cURL)命令示例:
    curl -X POST -u<username> "https://gnip-api.x.com/search/:product/accounts/:account_name/:label.json" -d '{"query":"from:twitterDev","maxResults":500,"fromDate":"yyyymmddhhmm","toDate":"yyyymmddhhmm"}'
如果 API 的数据响应包含“next”令牌,以下展示的是一个后续请求:它基于原始请求,并将“next”参数设置为提供的令牌。
    curl -X POST -u<username> "https://gnip-api.x.com/search/:product/accounts/:account_name/:label.json" -d '{"query":"from:twitterDev","maxResults":500,"fromDate":"yyyymmddhhmm","toDate":"yyyymmddhhmm",
    "next":"NTcxODIyMDMyODMwMjU1MTA0"}'
示例 GET 请求
  • 在 GET 请求中,请求参数会采用标准 URL 编码并附加到 URL 中。
  • 要查询的 PowerTrack 规则的各个部分(例如关键词、以及诸如 bounding_box: 之类的其他运算符)都应放在 query 参数中。
  • 请不要在查询 URL 中将规则的部分拆分为单独的参数。
下面是一个用于发起初始 data 请求的示例 GET(使用 cURL)命令:
    curl -u<username> "http://gnip-api.x.com/search/:product/accounts/:account_name/:label.json?query=from%3Atwitterdev&maxResults=500&fromDate=yyyymmddhhmm&toDate=yyyymmddhhmm"
示例数据响应
请注意,对于自 2022 年 9 月 29 日起创建的 Tweets,Tweet 对象将包含描述其编辑历史的 Tweet 编辑 metadata。有关更多详细信息,请参阅 “Edit Tweets” 基础知识页面。 下面是对 data query 的示例响应。此示例假设可用的 Tweets 多于 ‘maxResults’,因此为后续请求提供了一个 ‘next’ 令牌。如果与您的 query 关联的 Tweets 数量小于或等于 ‘maxResults’,响应中将不包含 ‘next’ 令牌。 ‘next’ 元素的值会随每次 query 变化,应将其视为不透明字符串。响应正文中的 ‘next’ 元素如下所示:
{
    "results":
      [
            {--Tweet 1--},
            {--Tweet 2--},
            ...
            {--Tweet 500--}
      ],
    "next":"NTcxODIyMDMyODMwMjU1MTA0",
    "requestParameters":
      {
        "maxResults":500,
        "fromDate":"201101010000",
        "toDate":"201201010000"
      }
  }
对后续请求的响应可能如下所示(请注意新增的 Tweets 以及不同的“next”值):
{
      "results":
      [
            {--Tweet 501--},
            {--Tweet 502--},
            ...
            {--Tweet 1000--}
      ],
      "next":"R2hCDbpBFR6eLXGwiRF1cQ",
      "requestParameters":
      {
        "maxResults":500,
        "fromDate":"201101010000",
        "toDate":"201201010000"
      }
  }
您可以继续传入先前 query(查询)中的 ‘next’ 元素,直到获取到该 query 所覆盖时间范围内的所有 Tweet。收到不包含 ‘next’ 元素的响应时,表示您已到达最后一页,在所选时间范围内没有更多可用的 data。

计数 endpoint

/search/:stream/counts
endpoint 模式:
/search/fullarchive/accounts/:account_name/:label/counts.json 此 endpoint 返回指定 query(查询)的计数(数据量)data。若未指定时间范围,时间参数默认取过去 30 天。数据量将以带时间戳的数组返回,可按天、按小时(默认)或按分钟聚合。 注意: 也可通过将下文所述参数编码到 URL 中,使用 GET 请求(而非 POST)来实现相同功能。
计数请求参数
Parameters描述是否必需示例值
query等同于一条 PowerTrack 规则,最多 2,048 个字符(正向与负向子句的数量不受限制)。

此参数应包含该 PowerTrack 规则的所有部分,包括全部运算符;规则的任一部分都不应拆分到 query 的其他参数中。

注意: 并非所有 PowerTrack 运算符均受支持。请参阅可用运算符以获取受支持运算符列表。
Yes(snow OR cold OR blizzard) weather
fromDate提供 tweets 的最早 UTC 时间戳(最早可追溯至 2006/3/21)。时间戳粒度为分钟,且为包含(例如 12:00 包含第 00 分钟)。

已指定: 仅指定 fromDate 而未提供 toDate 时,API 将从当前时刻向前回溯至 fromDate,返回该 query(查询)的计数(数据量)。如果 fromDate 早于当前时间超过 31 天,将返回 next 令牌以分页。

未指定: 如果未指定 fromDate,API 将返回从当前时刻或(如已指定)toDate 起向前 30 天的计数(数据量)。

如果既未使用 fromDate 也未使用 toDate,API 将返回最近 30 天的计数(数据量),从请求发起时刻开始向后计算。
No201207220000
toDate提供 tweets 的最新(最近)UTC 时间戳。时间戳粒度为分钟,且为不包含(例如 11:59 不包含该小时的第 59 分钟)。

已指定: 仅指定 toDate 而未提供 fromDate 时,将返回 toDate 之前 30 天内的最新计数(数据量)。

未指定: 如果未指定 toDate,API 将向前回溯至 fromDate,返回该 query(查询)的计数(数据量)。如果 fromDate 早于当前时间超过 31 天,将返回 next 令牌以分页。

如果既未使用 fromDate 也未使用 toDate,API 将返回最近 30 天的计数(数据量),从请求发起时刻开始向后计算。
No201208220000
bucket提供计数数据的时间单位。可在请求的时间范围内按天、小时或分钟返回计数数据。默认按小时返回。可选值:‘day’、‘hour’、‘minute’Nominute
next用于获取下一“页”结果,详见此处。该参数的取值直接来自 API 的响应,且不应修改。NoNTcxODIyMDMyODMwMjU1MTA0
其他详细信息
可用时间范围30-Day:过去 31 天
Full-Archive:2006 年 3 月 21 日至今
查询格式相当于一条 PowerTrack 规则,最多 2,048 个字符。

**注意:**并非所有 PowerTrack 运算符均受支持。请参阅 Available operators 获取受支持的运算符列表。
请求速率限制合作伙伴将同时在分钟级和秒级受到请求速率限制。每分钟的请求速率限制将按合同约定,因合作伙伴而异。但这些每分钟的限制并非用于一次性突发使用。无论您的每分钟请求速率限制如何,所有合作伙伴的每秒请求上限均为 20 次,该上限在所有 data 和/或计数请求间聚合计算。
计数精度通过此 endpoint 提供的计数反映实际发生的 Tweet 数量,不包括任何后续的合规事件(删除、scrub geos)。由于用户合规操作,被计数的某些 Tweet 可能无法通过 data endpoint 获取。
计数请求和响应示例
示例 POST 请求
  • 在 POST 请求中,请求参数通过 JSON 格式的请求体发送,如下所示。
  • 需要查询的 PowerTrack 规则的所有组成部分(例如关键词、以及如 bounding_box: 之类的其他运算符)都应放入 query(查询) 参数中。
  • 不要将规则的各个部分拆分为查询 URL 中的独立参数。
下面是一个用于发起初始计数请求的 POST(使用 cURL)命令示例:
    curl -X POST -u<username> "https://gnip-api.x.com/search/:product/accounts/:account_name/:label/counts.json" -d '{"query":"TwitterDev","fromDate":"yyyymmddhhmm","toDate":"yyyymmddhhmm","bucket":"day"}'
如果 API 的计数响应中包含“next”令牌,下面是一个后续请求:在原始请求的基础上,将“next”参数设置为提供的令牌:
    curl -X POST -u<username> "https://gnip-api.x.com/search/:product/accounts/:account_name/:label/counts.json" -d '{"query":"TwitterDev","fromDate":"yyyymmddhhmm","toDate":"yyyymmddhhmm","bucket":"day",
    "next":"YUcxO87yMDMyODMwMjU1MTA0"}'
示例 GET 请求
  • GET 请求的请求参数会编码进 URL 中,并采用标准的 URL 编码
  • 要查询的 PowerTrack 规则的所有部分(例如关键词、以及像 bounding_box: 这样的其他运算符)都应放在 ‘query’ 参数中
  • 不要在查询 URL 中将规则的各部分拆分为单独的参数
下面是一个用于发起初始计数请求的示例 GET(使用 cURL)命令:
    curl -u<username> "http://gnip-api.x.com/search/fullarchive/accounts/:account_name/:label/counts.json?query=TwitterDev&bucket=day&fromDate=yyyymmddhhmm&toDate=yyyymmddhhmm"

示例计数响应

下面是一个针对 counts(数据量)query(查询)的示例响应。该示例响应包含一个“next”令牌,这意味着计数请求的时间范围超过了 31 天,或者提交的 query(查询)所关联的数据量足够大,从而触发了部分响应。 “next”元素的值会在每次 query(查询)中变化,应将其视为不透明字符串。响应正文中的“next”元素将如下所示:
    {
      "results": [
        { "timePeriod": "201101010000", "count": 32 },
        { "timePeriod": "201101020000", "count": 45 },
        { "timePeriod": "201101030000", "count": 57 },
        { "timePeriod": "201101040000", "count": 123 },
        { "timePeriod": "201101050000", "count": 134 },
        { "timePeriod": "201101060000", "count": 120 },
        { "timePeriod": "201101070000", "count": 43 },
        { "timePeriod": "201101080000", "count": 65 },
        { "timePeriod": "201101090000", "count": 85 },
        { "timePeriod": "201101100000", "count": 32 },
        { "timePeriod": "201101110000", "count": 23 },
        { "timePeriod": "201101120000", "count": 85 },
        { "timePeriod": "201101130000", "count": 32 },
        { "timePeriod": "201101140000", "count": 95 },
        { "timePeriod": "201101150000", "count": 109 },
        { "timePeriod": "201101160000", "count": 34 },
        { "timePeriod": "201101170000", "count": 74 },
        { "timePeriod": "201101180000", "count": 24 },
        { "timePeriod": "201101190000", "count": 90 },
        { "timePeriod": "201101200000", "count": 85 },
        { "timePeriod": "201101210000", "count": 93 },
        { "timePeriod": "201101220000", "count": 48 },
        { "timePeriod": "201101230000", "count": 37 },
        { "timePeriod": "201101240000", "count": 54 },
        { "timePeriod": "201101250000", "count": 52 },
        { "timePeriod": "201101260000", "count": 84 },
        { "timePeriod": "201101270000", "count": 120 },
        { "timePeriod": "201101280000", "count": 34 },
        { "timePeriod": "201101290000", "count": 83 },
        { "timePeriod": "201101300000", "count": 23 },
        { "timePeriod": "201101310000", "count": 12 }
       ],
      "totalCount":2027,
      "next":"NTcxODIyMDMyODMwMjU1MTA0",
      "requestParameters":
        {
          "bucket":"day",
          "fromDate":"201101010000",
          "toDate":"201201010000"
        }
    }
对后续请求的响应可能如下所示(请注意新的计数时间线以及不同的“next”值):
    {
      "results": [
        { "timePeriod": "201102010000", "count": 45 },
        { "timePeriod": "201102020000", "count": 76 },
         ....
        { "timePeriod": "201103030000", "count": 13 }
     ],
     "totalCount":3288,
     "next":"WE79fnakFanyMDMyODMwMjU1MTA0",
     "requestParameters":
        {
          "bucket":"day",
          "fromDate":"201101010000",
          "toDate":"201201010000"
        }
    }
你可以继续传入先前 query(查询)中的“next”元素,直到获取到该 query(查询)时间范围内的所有计数。当你收到的响应不包含“next”元素时,表示你已到达最后一页,且在你的时间范围内没有更多计数可用。

HTTP 响应代码

状态文本说明
200OK请求成功。JSON 响应类似如下:
400Bad Request通常由于请求中包含无效的 JSON,或请求未发送任何 JSON 负载而返回。
401Unauthorized由于凭据无效导致 HTTP 身份验证失败。请使用您的凭据登录 console.gnip.com,确认在请求中正确使用。
404Not Found在请求发送到的 URL 未找到资源,通常是因为使用了不正确的 URL。
422Unprocessable Entity由于 query(查询)中存在无效参数而返回,例如无效的 PowerTrack 规则。
429Unknown Code您的 App 已超出连接请求的限制。相应的 JSON 消息类似如下:
500Internal Server Error服务器端发生错误。请使用指数退避策略重试请求。
502Proxy Error服务器端发生错误。请使用指数退避策略重试请求。
503Service Unavailable服务器端发生错误。请使用指数退避策略重试请求。
I