跳转到主要内容
此 endpoint 已更新,现包含 Post 编辑的 metadata。请参阅 “Edit Posts” 基础知识页面 以了解这些 metadata 的详细信息。

Decahose stream

Enterprise 这是一项仅在我们的托管访问级别中提供的 Enterprise API。要使用此 API,您必须先与我们的企业销售团队开通账户。 了解更多 Decahose 通过流式连接从实时 X Firehose 提供 10% 的随机样本。这通过实时采样算法实现,算法随机选取 data,同时在 X 通过 firehose 发送时仍能实现预期的低延迟 data 传递。 以下是 Decahose 提供的一些功能:
  • 扩展与增强的 URL: - 完整展开短链接并提供额外的 metadata(页面 title 和描述)
  • Stream 分区 - 2 个分区,每个分区包含 Decahose stream 流量的 50%
  • 增强的可靠性 - 后端系统具备地域多样性
注意:此 data 以批量方式交付,不支持额外过滤(例如按关键词)。 ENTERPRISE

likes 流式传输

这是仅在我们托管访问级别内提供的 Enterprise API。要使用此 API,您必须先与我们的企业销售团队开设账户。了解更多 like 可用于洞察谁对 Post 执行了 like,并提供精确的 like 计数。Gnip 的 Firehose 和 Decahose 可传递与通过 Gnip 分发的 Post 相关的公共 likes,从而获得与某个 Post 相关的实时公共互动与受众度量。   开始使用 likes 在准备消费 likes 数据时,您需要了解:
  • likes 通过独立的 stream 传递
  • likes 历史上称为“Favorites”。增强的原生格式载荷保留了这一命名
  • streams 仅包含公共 likes
    • “公共”意味着点赞用户、Post 创建者和 Post 在平台上均为公开
  • likes 与 转发 非常相似,代表一种公开的互动信号
  • 载荷元素包括:
    • 原始 Post 对象
    • 创建原始 Post 的参与者对象
    • 执行 like 操作的参与者对象
  • 只有原创内容可以被 like
    • 转发 不能被 like。对转发 的 like 将应用于原始 Post
    • 引用的 Tweet 可以 被 like
  • like 活动包含适用的 Gnip Enrichments(如已购买/应用)
  • 支持的产品/功能
    • likes streams 支持 Backfill(如已购买/应用)
    • likes streams 不支持 Replay
    • likes 不支持 Search 或 Historical
    • 目前暂无将 likes 支持添加到 PowerTrack 的计划
Decahose 原生增强格式载荷
{
   "id":"43560406e0ad9f68374445f5f30c33fc",
   "created_at":"Thu Dec 01 22:27:39 +0000 2016",
   "timestamp_ms":1480631259353,
   "favorited_status":{
      "created_at":"Thu Dec 01 22:27:16 +0000 2016",
      "id":804451830033948672,
      "id_str":"804451830033948672",
      "text":"@kafammheppduman",
      "source":"\u003ca href=\"http:\/\/x.com\/download\/android\" rel=\"nofollow\"\u003eX for Android\u003c\/a\u003e",
      "truncated":false,
      "in_reply_to_status_id":803694205163814912,
      "in_reply_to_status_id_str":"803694205163814912",
      "in_reply_to_user_id":2855759795,
      "in_reply_to_user_id_str":"2855759795",
      "in_reply_to_screen_name":"kafammheppduman",
      "user":{
         "id":2855759795,
         "id_str":"2855759795",
         "name":"delirdim kanka",
         "screen_name":"kafammheppduman",
         "location":"sanane",
         "url":"http:\/\/instagram.com\/kafammheppduman",
         "description":"Manit @GalatasaraySk \ud83d\udc9e",
         "translator_type":"none",
         "protected":false,
         "verified":false,
         "followers_count":3702,
         "friends_count":607,
         "listed_count":1,
         "favourites_count":113338,
         "statuses_count":389,
         "created_at":"Sat Nov 01 22:38:25 +0000 2014",
         "utc_offset":null,
         "time_zone":null,
         "geo_enabled":true,
         "lang":"tr",
         "contributors_enabled":false,
         "is_translator":false,
         "profile_background_color":"C0DEED",
         "profile_background_image_url":"",
         "profile_background_image_url_https":"",
         "profile_background_tile":false,
         "profile_link_color":"1DA1F2",
         "profile_sidebar_border_color":"C0DEED",
         "profile_sidebar_fill_color":"DDEEF6",
         "profile_text_color":"333333",
         "profile_use_background_image":true,
       "Profile_image_url": "http:\/\/pbs.twimg.com\/profile_images\/804421763945861121\/v3bp9pnq_normal.jpg",
         "Profile_image_url_https": "https:\/\/pbs.twimg.com\/profile_images\/804421763945861121\/v3bp9pnq_normal.jpg",
         "profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/2855759795\/1480630085",
         "default_profile":true,
         "default_profile_image":false,
         "following":null,
         "follow_request_sent":null,
         "notifications":null
      },
      "geo":null,
      "coordinates":null,
      "place":null,
      "contributors":null,
      "is_quote_status":false,
      "retweet_count":0,
      "favorite_count":0,
      "entities":{
         "hashtags":[],
         "urls":[],
         "user_mentions":[
            {
               "screen_name":"kafammheppduman",
               "name":"delirdim kanka",
               "id":2855759795,
               "id_str":"2855759795",
               "indices":[
                  0,
                  16
               ]
            }
         ],
         "symbols":[]
      },
      "favorited":false,
      "retweeted":false,
      "filter_level":"low",
      "lang":"und"
   },
   "user":{
      "id":774146932365070336,
      "id_str":"774146932365070336",
      "name":"Uyuyan Adam",
      "screen_name":"saykoMenn",
      "location":"Tarsus, T\u00fcrkiye",
      "url":"http:\/\/connected2.me\/pmc1i",
      "description":null,
      "translator_type":"none",
      "protected":false,
      "verified":false,
      "followers_count":414,
      "friends_count":393,
      "listed_count":0,
      "favourites_count":9868,
      "statuses_count":370,
      "created_at":"Fri Sep 09 07:26:26 +0000 2016",
      "utc_offset":null,
      "time_zone":null,
      "geo_enabled":false,
      "lang":"tr",
      "contributors_enabled":false,
      "is_translator":false,
      "profile_background_color":"F5F8FA",
      "profile_background_image_url":"",
      "profile_background_image_url_https":"",
      "profile_background_tile":false,
      "profile_link_color":"1DA1F2",
      "profile_sidebar_border_color":"C0DEED",
      "profile_sidebar_fill_color":"DDEEF6",
      "profile_text_color":"333333",
      "profile_use_background_image":true,
      "Profile_image_url": "http:\/\/pbs.twimg.com\/profile_images\/802992813424201728\/VMzcTL3x_normal.jpg",
      "Profile_image_url_https": "https:\/\/pbs.twimg.com\/profile_images\/802992813424201728\/VMzcTL3x_normal.jpg",
      "profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/774146932365070336\/1480283382",
      "default_profile":true,
      "default_profile_image":false,
      "following":null,
      "follow_request_sent":null,
      "notifications":null
   }
}
like DELETE/“取消 like” 载荷
{
   "delete":{
      "favorite":{
         "tweet_id":696615514970279937,
         "tweet_id_str":"696615514970279937",
         "user_id":2510287578,
         "user_id_str":"2510287578"
      },
      "timestamp_ms":"1480437031205"
   }
}

使用指南

恢复与冗余

简介  在以 stream 方式传输大量实时 Post 时,有一套可同时提升数据可靠性与数据完备保真度的最佳实践。在消费实时 data 时,最大化连接持续时间是基本目标。发生断开时,应自动检测并重连。重连后,需要评估是否存在需要回填 data 的时间段。负责处理这些细节并消费实时 Post 的组件只是系统的一部分,系统还涉及网络、数据存储、服务器和存储等方面。鉴于系统的复杂性,另一项最佳实践是划分不同的 streaming 环境,至少将开发/测试与生产的 stream 分离。 Decahose 提供了一系列功能来支持这些工作。
  1. 为支持多个环境,我们可以为你的账户部署Additional Streams。这些 streams 互相独立,并带有不同的 stream_label 以便区分。
  2. 为帮助维持连接,每个 Decahose stream 都支持Redundant Connections。最常见的架构是一个 stream 建立两个连接,客户端侧有两个彼此独立的消费者——最好位于不同网络。通过这种设计,可在客户端侧的网络、服务器和数据存储路径上实现冗余。请注意,每个连接都会传输一份完整的数据副本,客户端必须能够容忍并处理重复数据。
  3. 每 10 秒会发送一次“heartbeat”;然而,在 Decahose stream 中,data 量足够大,即便是短时间(例如几秒)没有 Post 也可能表示连接问题。因此,既可通过“数据静默”也可通过缺少 heartbeat 来检测断连。
鉴于断连在所难免,Decahose stream 提供了专门的RecoveryBackfill功能,帮助恢复因断连及其他运维问题而遗漏的 data。

额外的 Streams

增加额外的 Decahose streams 是提升方案可靠性的一种方式。所有额外的 streams 彼此完全独立,并拥有各自唯一的 endpoint。每个 stream 都会分配一个专属的 stream_label,该标签与您的账户名称一起构成该 stream 的 URL 的一部分。示例如下: https://gnip-stream.x.com/stream/sample10/accounts/:account_name/publishers/twitter/:stream_label.json 最常见的做法是:为您的生产系统配置一个专用的实时 stream,并另设一个 stream 供开发与测试使用。拥有测试/开发 stream 能使 Decahose 客户用于验证客户端消费者的更新。虽然可以为 stream 分配任何(唯一的)标签,但常见约定是生产环境使用“prod”,开发环境使用“dev”或“sandbox”。 streams 的数量及其唯一标签可由您的客户代表进行配置。 冗余连接 冗余连接是指允许您对同一 data stream 建立多个并发连接。这样可通过两个独立的消费者连接到同一个 stream,并在两条连接上接收相同数据,从而提供冗余。因此,您的应用在多种情况下具备热切换能力,例如某条 stream 断开,或应用的主服务器发生故障时。 对于任意给定的 stream,可允许的连接数由您的客户代表进行配置。要使用冗余 stream,只需连接与主连接相同的 URL。该 stream 的数据会通过两条连接同时发送,且两条 stream 连接都会显示在 stream 控制台上。 请注意,出于计费目的,我们会对您通过多个连接接收的活动计数进行去重,确保每个唯一活动仅计费一次。鉴于 Decahose 有两个分区,以下是连接计数的示例: Connect to decahose partition=1 Connect to decahose partition=1 Connect to decahose partition=2 上述情况共计三条连接——两条连接到 partition=1,一条连接到 partition=2。通常,您会希望各分区的连接数相同;该示例表明 partition=2 的冗余连接已掉线,需进一步排查。 恢复

概述 

Recovery 是一款数据恢复工具(不用于主要数据采集),可提供对最近 X 历史数据的滚动 5 天窗口的流式访问。它应在以下情况下用于数据恢复:当您的消费端应用因短时断连,或因其他原因在一段时间内未能摄取实时数据而错过实时 stream 数据时。

使用 Recovery 

通过 Recovery stream,您的应用可以以与实时 stream 相同的方式向其发起请求。但您的应用必须在 URL 中指定参数以表明所请求的时间窗口。换言之,Recovery 请求会向 API 请求“从时间 A 到时间 B 的 Posts”。随后,这些 Posts 将通过您的流式连接以模拟实时 stream 的方式交付,但速率会略低于实时。请参见下方示例: https://stream-data-api.x.com/stream/powertrack/accounts/someAccountName/publishers/twitter/powertrack.json?startTime=2023-07-05T17:09:12.070Z Posts 会从指定时间段的第一个(最早)分钟开始交付,按时间顺序持续到最后一分钟。届时,会通过连接发送一条 Recovery Request Completed 消息,随后服务器将关闭该连接。如果您的请求起始于匹配结果很少或没有结果的时间点,那么在首次结果交付前可能会有一段等待——当 Recovery 在当时正在处理的归档部分遇到匹配项时才会交付 data。当没有可交付的结果时,stream 将继续通过连接发送回车符(“心跳”)以防止连接超时。 Recovery 旨在作为一种便捷工具,用于恢复因短暂断连而遗漏的 data,而非用于覆盖很长的时间段(例如整整一天)。如果需要在较长时间段内恢复 data,建议将较长请求拆分为较短的时间窗口(例如两小时),以降低因网络波动或其他原因导致请求中途断开的可能性,并提升对长请求进度的可见性。

数据可用性

如果您无法在 5 分钟回填窗口内重新连接,您可以使用 Recovery 功能在过去 24 小时内恢复遗漏的 data。 stream 恢复功能可将回填窗口扩展至 24 小时。Recovery 使您能够“恢复”遗漏的 data 所对应的时间段。当您在连接请求中使用 ‘start_time’ 和 ‘end_time’ 请求参数时,将启动恢复 stream。连接后,Recovery 会重新 stream 指定的时间段,然后断开连接。   您可以同时对 Recovery 发起 2 个并发请求,即“两项恢复作业”。Recovery 的技术工作方式与回填相同,不同之处在于需要定义开始时间和结束时间。一次恢复周期仅对应一个时间范围。

回填

要请求回填,您需要在连接请求中添加参数 backfillMinutes=N,其中 N 为在建立连接时要回填的分钟数(1–5,且为整数)。例如,如果您断开连接 90 秒,应在连接请求中添加 backfillMinutes=2。由于该请求将提供 2 分钟的回填(包含断开前的 30 秒),因此您的_consumer app 必须能够容忍重复的 data_。 一个 Decahose 连接请求 URL 示例,请求对分区 1 回填 5 分钟,如下所示: https://gnip-stream.x.com/stream/sample10/accounts/:account_name/publishers/twitter/:stream_label.json?partition=1&backfillMinutes=5 注意:
  • 您可以在每次连接时始终使用“backfillMinutes=5”,然后处理可能出现的重复 data。
  • 如果断开连接超过五分钟,您可以使用 Recovery 来恢复 data。
从断开连接中恢复 重新启动并从断开连接中恢复包括以下步骤:
  • 确定断开时长。
    • 5 分钟及以下?
      • 如果为 stream 启用了 Backfill,请使用合适的 backfillMinutes 参数准备连接请求。
    • 超过 5 分钟?
      • 如果您有 Recovery stream,请针对断开时间段发起 Recovery 请求(理想情况下使用您当前的实时规则集,必要时使用 Rules API)。
  • 请求新的连接。
当您遇到断开或停机时,可采用以下策略进行缓解与恢复:
  1. 实施回填 回填允许您从断开 stream 连接之前的某一时间点重新连接,覆盖最长 5 分钟的断开。通过在连接请求中包含相应参数实现。
  2. 从其他位置消费冗余 stream 如果冗余 stream 能够接入相同的线上环境并对 data 进行去重,则除非主 stream 和冗余 stream 同时出现停机或断开,通常无需进行恢复。如果冗余 stream 无法实时接入生产环境,可将其写入单独的“应急”数据存储。这样,在主 stream 连接发生断开或停机时,系统可用其填补主数据库在相应时段的缺失 data。
  3. 实施 Recovery 当断开或停机同时影响主 stream 与冗余 stream 时,使用 Decahose Recovery 恢复遗漏的 data。该 API 提供覆盖 5 天存档的滚动窗口,最佳做法是每次请求不超过 1 小时的窗口并以流式方式导入,与实时 stream 并行进行。请注意,我们无法提供超出 Recovery 所提供 5 天窗口之外的 Decahose data 的恢复方案,因此务必使用冗余 stream,确保在您侧出现较长停机时,您仍拥有完整的 data 副本。
当您检测到存储数据量异常时—— 在未发生断开或停机的情况下,检测缺失 data 的潜在方法包括:
  1. 统计入站 Posts 系统应在摄取 App 的最前端统计接收的原始 Posts 数量,并提供方式将这些数字与最终数据存储中到达的 Posts 数量进行对比。可监控任何差异,并提醒团队注意接收后导致 data 丢失的问题。
  2. 分析异常的存储量 您也可以分析最终数据库中存储的 data 量,查找异常下降。这同样可能表明存在问题,尽管在某些情况下量的下降是正常的(例如 X 平台不可用,用户在一段时间内无法创建 Posts)。

API 参考文档

Decahose stream

跳转到本页 方法 身份验证 GET /{stream-type}/:stream Replay API

方法

方法说明
GET /{stream-type}/:stream连接到数据流

身份验证

对 Volume Stream API 的所有请求都必须使用 HTTP 基本身份验证(HTTP Basic Authentication),其凭据由用于登录你在 console.gnip.com 上账户的有效电子邮件地址与密码组合构成。凭据必须作为每个请求的 Authorization 标头传递。请确认你的客户端为所有 API 请求添加了“Authorization: Basic”HTTP 标头(通过 HTTPS 传输经编码的凭据)。

GET :stream

建立与 Firehose stream 的持久连接,通过该连接传输实时 data。

请求规范

请求方法HTTP GET
连接类型Keep-Alive

应在请求的 header 中指定。
URL可在控制台中该 stream 的 API Help 页面找到,结构如下:

Decahose:

https://gnip-stream.x.com/stream/sample10/accounts/:account_name/publishers/twitter/:stream_label.json?partition=1
分区(必填)partition=\{#} - 现需使用分区才能消费完整的 stream。连接到 stream 时需指定分区参数。以下为每个 stream 的分区数:

* Decahose:2 partitions
压缩Gzip。要以 Gzip 压缩连接到 stream,只需在连接请求中发送 Accept-Encoding header。该 header 应如下所示:

Accept-Encoding: gzip
字符编码UTF-8
响应格式JSON。请求的 header 中应指定响应采用 JSON 格式。
请求速率限制每 60 秒 10 次请求。
Backfill 参数如果你购买了启用 Backfill 的 stream,需要在 GET 请求中添加 “backfillMinutes” 参数以启用。
读取超时在客户端设置读取超时,并确保其值大于 30 秒。
对 Tweet 编辑的支持所有 Tweet 对象都将包含描述其编辑历史的 Tweet 编辑 metadata。更多详情请参见 “Edit Tweets” 基础页面

响应

对于这些请求,API 可能返回以下响应。大多数错误代码会在正文中附带一个包含更多详细信息的字符串。对于非 200 响应,客户端应尝试重新连接。
状态文本说明
200成功连接已成功建立,新的活动会在到达时通过该连接发送。
401未授权由于凭据无效,HTTP 认证失败。请使用你的凭据登录 console.gnip.com,确认在请求中正确使用。
406不可接受通常发生于客户端未正确包含接受来自 stream 的 gzip 编码的请求头,但也可能在其他情况下出现。

将包含一条类似于 “This connection requires compression. To enable compression, send an ‘Accept-Encoding: gzip’ header in your request and be ready to uncompress the stream as it is read on the client end.” 的 JSON 消息。
429触发请求速率限制你的 App 已超出连接请求的限制。
503服务不可用Twitter 服务器问题。请按指数退避模式重新连接。若 X API Status Page 上未发布关于此问题的通知,并且在 10 分钟后仍无法连接,请联系支持或紧急渠道。

示例 cURL 请求

以下示例请求是在命令行中使用 cURL 完成的。请注意,您也可以使用任意编程语言发送这些请求:
curl --compressed -v -uexample@customer.com "https://gnip-stream.x.com/stream/firehose/accounts/:account\_name/publishers/twitter/:stream\_label.json?partition={#}"

Replay API

Replay API 是对实时 Volume stream 的重要补充。Replay 是一款数据恢复工具,可通过流式方式访问 X 近期历史数据的滚动时间窗口。
I