Project Icon

search-tweets-python

Python工具简化Twitter搜索数据访问和分析

该项目是Twitter高级和企业搜索API的Python封装,提供命令行工具和库。支持30天及全档案搜索,具备自动分页、流式传输、多种认证等功能。兼容Tweet解析器,支持搜索计数,可减少API调用并快速获取推文数量。整体简化了Twitter搜索数据的访问和分析流程,适用于需要处理大量Twitter数据的开发者。

寻找Twitter API v2版本?请查看新的'v2'分支。


Twitter v2搜索端点现在包含一个'counts'端点,可返回匹配推文的时间序列总数。

Python Twitter 搜索 API

该项目作为Twitter高级和企业搜索API的包装器,提供了一个命令行工具和Python库。精美的文档可以在这里查看。

功能

  • 支持30天搜索和完整存档搜索(目前不支持标准搜索API)。
  • 命令行工具可以与其他工具(如jq)进行管道操作。
  • 自动处理搜索结果的分页,可指定限制
  • 向用户传递数据流,内存需求低
  • 处理企业和高级认证方法
  • 在Python程序中灵活使用
  • 与我们团队的Tweet Parser兼容,可快速从每条推文负载中提取相关数据字段
  • 支持搜索计数端点,如果您只需要推文数量而不需要推文负载,可以减少API调用并快速获得洞察

安装

searchtweets库可在Pypi上获得:

pip install searchtweets

或者您可以通过以下方式在本地安装开发版本:

git clone https://github.com/twitterdev/search-tweets-python cd search-tweets-python pip install -e .


凭证处理

高级和企业搜索API使用不同的认证方法,我们试图为所有客户提供一种无缝的认证处理方式。我们知道凭证可能很棘手或令人烦恼 - 请完整阅读这部分内容。

高级客户需要bearer_token和endpoint字段;企业客户需要username、password和endpoint。如果未指定account_type,我们会尝试识别账户类型并声明此行为的警告。

对于高级搜索产品,我们使用仅应用程序认证,bearer token不会设置过期时间。您可以提供:

  • 您的应用程序密钥和密码(库将处理bearer token认证)
  • 您自己获取的bearer token

许多开发人员可能会发现提供应用程序密钥和密码并让这个库管理bearer token生成更加直接。请查看这里了解高级认证方法的概述。

我们支持基于YAML文件的方法和环境变量来存储凭证,并提供灵活的处理方式和合理的默认值。

YAML方法

对于高级客户,最简单的凭证文件应如下所示:

search_tweets_api: account_type: premium endpoint: <端点的完整URL> consumer_key: <消费者密钥> consumer_secret: <消费者密钥>

对于企业客户,最简单的凭证文件应如下所示:

search_tweets_api: account_type: enterprise endpoint: <端点的完整URL> username: <用户名> password: <密码>

默认情况下,该库预期此文件位于"~/.twitter_keys.yaml",但您可以根据需要传递相关位置,可以使用命令行应用程序的--credential-file标志或在Python程序中演示。

上述两个示例都不需要特殊的命令行参数或程序内参数。除非另有指定,凭证解析方法将查找名为search_tweets_api的YAML键。

对于具有多个端点和/或搜索产品的开发人员,您可以将所有凭证保存在同一个文件中并指定要使用的特定键。--credential-file-key在命令行应用程序中指定此行为。示例:

search_tweets_30_day_dev: account_type: premium endpoint: <端点的完整URL> consumer_key: <密钥> consumer_secret: <密钥> (可选) bearer_token: <令牌>

search_tweets_30_day_prod: account_type: premium endpoint: <端点的完整URL> bearer_token: <令牌>

search_tweets_fullarchive_dev: account_type: premium endpoint: <端点的完整URL> bearer_token: <令牌>

search_tweets_fullarchive_prod: account_type: premium endpoint: <端点的完整URL> bearer_token: <令牌>

环境变量

如果您想或需要通过环境变量传递凭证,可以为您的产品设置以下适当的变量:

export SEARCHTWEETS_ENDPOINT= export SEARCHTWEETS_USERNAME= export SEARCHTWEETS_PASSWORD= export SEARCHTWEETS_BEARER_TOKEN= export SEARCHTWEETS_ACCOUNT_TYPE= export SEARCHTWEETS_CONSUMER_KEY= export SEARCHTWEETS_CONSUMER_SECRET=

如果load_credentials函数无法从YAML文件加载字段,它将尝试查找这些变量,并且如果已解析,它将覆盖YAML文件中存在的任何作为环境变量的凭证。可以通过将load_credentials参数env_overwrite设置为False来更改此行为。

以下单元演示了Python库中的凭证处理。

from searchtweets import load_credentials

load_credentials(filename="./search_tweets_creds_example.yaml", yaml_key="search_tweets_ent_example", env_overwrite=False)

{'username': '<我的用户名>', 'password': '<我的密码>', 'endpoint': '<我的端点>'}

load_credentials(filename="./search_tweets_creds_example.yaml", yaml_key="search_tweets_premium_example", env_overwrite=False)

{'bearer_token': '<一个很长的神奇字符串>', 'endpoint': 'https://api.twitter.com/1.1/tweets/search/30day/dev.json', 'extra_headers_dict': None}

环境变量覆盖

如果我们设置了环境变量,程序将查找它们,而不管YAML文件是否有效或存在。

import os os.environ["SEARCHTWEETS_USERNAME"] = "<环境用户名>" os.environ["SEARCHTWEETS_PASSWORD"] = "<环境密码>" os.environ["SEARCHTWEETS_ENDPOINT"] = "https://端点"

load_credentials(filename="nothing_here.yaml", yaml_key="no_key_here")

无法读取文件nothing_here.yaml 解析YAML文件时出错;正在搜索有效的环境变量

{'username': '<环境用户名>', 'password': '<环境密码>', 'endpoint': 'https://端点'}

命令行应用程序

以下标志用于控制命令行应用程序中的凭证行为:

  • --credential-file <文件名>
  • --credential-file-key <密钥>
  • --env-overwrite

使用命令行应用程序

该库包含一个名为search_tweets.py的应用程序,可快速访问推文。当您使用pip安装此软件包时,search_tweets.py会全局安装。对于想要在本地运行它的人来说,该文件位于tools/目录中。

请注意,--results-per-call标志指定了API的参数(maxResults,每次调用返回的结果),而不是此程序返回的结果的硬性最大值。参数--max-results定义了从给定调用返回的最大结果数。所有示例都假设您的凭证已在默认位置(.twitter_keys.yaml)或环境变量中正确设置。

将json结果流式传输到stdout而不保存

search_tweets.py
--max-results 1000
--results-per-call 100
--filter-rule "beyonce has:hashtags"
--print-stream 将 JSON 结果流式输出到标准输出并保存到文件

.. code:: bash

search_tweets.py
--max-results 1000
--results-per-call 100
--filter-rule "beyonce has:hashtags"
--filename-prefix beyonce_geo
--print-stream

保存到文件但不输出

.. code:: bash

search_tweets.py
--max-results 100
--results-per-call 100
--filter-rule "beyonce has:hashtags"
--filename-prefix beyonce_geo
--no-print-stream

可以使用 --extra-headers 参数和一个表示额外头部字典的 JSON 格式字符串来从命令行指定一个或多个自定义头部:

.. code:: bash

search_tweets.py
--filter-rule "beyonce has:hashtags"
--extra-headers '{"<MY_HEADER_KEY>":"<MY_HEADER_VALUE>"}'

可以通过配置文件(ini 或 YAML 格式)传递选项。示例文件可以在 tools/api_config_example.config./tools/api_yaml_example.yaml 文件中找到,可能看起来像这样:

.. code:: bash

[search_rules] from_date = 2017-06-01 to_date = 2017-09-01 pt_rule = beyonce has:geo

[search_params] results_per_call = 500 max_results = 500

[output_params] save_file = True filename_prefix = beyonce results_per_file = 10000000

或者像这样:

.. code:: yaml

search_rules: from-date: 2017-06-01 to-date: 2017-09-01 01:01 pt-rule: kanye

search_params: results-per-call: 500 max-results: 500

output_params: save_file: True filename_prefix: kanye results_per_file: 10000000

可以在配置文件中的特定凭证键下指定自定义头部:

.. code:: yaml

search_tweets_api: account_type: premium endpoint: <FULL_URL_OF_ENDPOINT> username: password: extra_headers: <MY_HEADER_KEY>: <MY_HEADER_VALUE>

当与命令行工具一起使用配置文件时,需要通过 --config-file 参数指定配置文件。额外的命令行参数将被添加到配置文件参数中,或者在两者都指定且存在的情况下覆盖配置文件参数。

示例:

::

search_tweets.py
--config-file myapiconfig.config
--no-print-stream


完整选项列表如下:

::

$ search_tweets.py -h usage: search_tweets.py [-h] [--credential-file CREDENTIAL_FILE] [--credential-file-key CREDENTIAL_YAML_KEY] [--env-overwrite ENV_OVERWRITE] [--config-file CONFIG_FILENAME] [--account-type {premium,enterprise}] [--count-bucket COUNT_BUCKET] [--start-datetime FROM_DATE] [--end-datetime TO_DATE] [--filter-rule PT_RULE] [--results-per-call RESULTS_PER_CALL] [--max-results MAX_RESULTS] [--max-pages MAX_PAGES] [--results-per-file RESULTS_PER_FILE] [--filename-prefix FILENAME_PREFIX] [--no-print-stream] [--print-stream] [--extra-headers EXTRA_HEADERS] [--debug]

可选参数: -h, --help 显示此帮助消息并退出 --credential-file CREDENTIAL_FILE 用于保存凭证的 yaml 文件的位置。 --credential-file-key CREDENTIAL_YAML_KEY 凭证文件中用于此会话凭证的键。默认为 search_tweets_api --env-overwrite ENV_OVERWRITE 用任何设置的环境变量覆盖 YAML 解析的凭证。详见 API 文档或 readme。 --config-file CONFIG_FILENAME 包含所有参数的配置文件。比命令行参数版本更容易使用。 如果找到有效文件,所有参数都将从那里填充。 剩余的命令行参数将覆盖配置文件中找到的参数。 --account-type {premium,enterprise} 您正在使用的账户类型 --count-bucket COUNT_BUCKET 设置此项以发出"计数"请求。计数端点的桶大小。选项:day、hour、minute。 --start-datetime FROM_DATE 日期时间窗口的开始,格式为 'YYYY-mm-DDTHH:MM' (默认:-30 天) --end-datetime TO_DATE 日期时间窗口的结束,格式为 'YYYY-mm-DDTHH:MM' (默认:最近日期) --filter-rule PT_RULE PowerTrack 过滤规则 (参见:http://support.gnip.com/c ustomer/portal/articles/901152-powertrack-operators) --results-per-call RESULTS_PER_CALL 每次调用返回的结果数 (默认 100;最大 500) - 对应 API 中的 'maxResults'。 如果使用 '--count-bucket' 发出"计数"请求,此参数将被忽略。 --max-results MAX_RESULTS 本次会话返回的推文或计数的最大数量 (默认为 500) --max-pages MAX_PAGES 本次会话使用的最大页数/API 调用次数。 --results-per-file RESULTS_PER_FILE 每个文件保存的最大推文数。 --filename-prefix FILENAME_PREFIX 存储推文 json 数据的文件名前缀。 --no-print-stream 禁用打印流 --print-stream 将推文流打印到标准输出 --extra-headers EXTRA_HEADERS 表示额外请求头字典的 JSON 格式字符串 --debug 打印所有信息和警告消息


使用 Twitter 搜索 API 的 Python 包装器

在 Python 程序中使用 API 对于高级和企业客户来说都很简单。

我们假设凭证位于默认位置 ~/.twitter_keys.yaml

.. code:: python

from searchtweets import ResultStream, gen_rule_payload, load_credentials

企业版设置

.. code:: python

enterprise_search_args = load_credentials("~/.twitter_keys.yaml", yaml_key="search_tweets_enterprise", env_overwrite=False)

高级版设置

.. code:: python

premium_search_args = load_credentials("~/.twitter_keys.yaml", yaml_key="search_tweets_premium", env_overwrite=False)

有一个名为 gen_rule_payload 的函数,它将搜索 API 规则格式化为有效的 json 查询。它有合理的默认值,比如每次调用获取的推文数量比默认的 100 多(但请注意,沙盒环境此处最多只能设置为 100,如果遇到错误,请检查这一点),不包括日期。讨论生成搜索规则的细节超出了这些示例的范围;我建议你查看文档以了解其中的细微差别,但现在让我们看看规则是什么样的。

.. code:: python

rule = gen_rule_payload("beyonce", results_per_call=100) # 使用沙盒账户进行测试 print(rule)

::

{"query":"beyonce","maxResults":100}

这条规则将匹配包含文本 beyonce 的推文。

从这一点开始,有两种与 API 交互的方式。有一种快速方法可以将少量推文收集到内存中,这种方法需要较少的思考和知识,另一种是与 ResultStream 对象交互,稍后将介绍。

快速方法

我们将使用 search_args 变量来为 API 提供配置点。该对象还接受有效的 PowerTrack 规则,并有选项在达到推文数量和 API 调用次数限制时切断搜索。

我们将使用 collect_results 函数,它有三个参数。

  • rule: 之前引用的有效 PowerTrack 规则
  • max_results: 由于 API 处理分页,它会在达到这个数量时停止收集
  • result_stream_args: 我们已经指定的配置参数

对于剩余的示例,请根据您的使用情况将参数更改为 premium 或 enterprise。

让我们看看效果如何:

from searchtweets import collect_results
tweets = collect_results(rule,
                         max_results=100,
                         result_stream_args=enterprise_search_args) # 如果需要请更改此项

默认情况下,Tweet 数据会被懒加载解析为 Tweet 对象。大量的 Tweet 属性可以直接使用,例如:

[print(tweet.all_text, end='\n\n') for tweet in tweets[0:10]];
Jay-Z & Beyoncé 今晚坐在我们对面吃饭,有一刻我和 Beyoncé 对视了。我的四肢变成了果冻,再也无法组织一个连贯的句子。我看到了上帝的眼睛。

Beyoncé,没有人能比得上她。https://t.co/UdOU9oUtuW

正如你所猜测的..Beyoncé 的 Signs 永远是我的最爱。

当 Beyoncé 领养了一只狗 🙌🏾 https://t.co/U571HyLG4F

等等,你不能这样对待 Beyoncé
https://t.co/3p14DocGqA

为什么你们还在用 Rihanna 和 Beyoncé 的 gif 来宣传这个节目,明明你们让 Bey 失去了她应得的三个奖项,还让 Rihanna 空手而归? https://t.co/w38QpH0wma

30) 有人说过你长得像 Beyoncé 吗 https://t.co/Vo4Z7bfSCi

我最喜欢的 Beyoncé https://t.co/f9Jp600l2B
Beyoncé 需要看到这个。@TiniStoessel 简直是女神 🔥🔥🔥 https://t.co/gadVJbehQZ

Joanne Pearce 现在正在播放 IF I WAS A BOY - BEYONCE.mp3!

我想在死前看到 beyoncé 的 finsta
[print(tweet.created_at_datetime) for tweet in tweets[0:10]];
2018-01-17 00:08:50
2018-01-17 00:08:49
2018-01-17 00:08:44
2018-01-17 00:08:42
2018-01-17 00:08:42
2018-01-17 00:08:42
2018-01-17 00:08:40
2018-01-17 00:08:38
2018-01-17 00:08:37
2018-01-17 00:08:37
[print(tweet.generator.get("name")) for tweet in tweets[0:10]];
Twitter for iPhone
Twitter for iPhone
Twitter for iPhone
Twitter for iPhone
Twitter for iPhone
Twitter for iPhone
Twitter for Android
Twitter for iPhone
Airtime Pro
Twitter for iPhone

瞧,我们获取到了一些推文。对于交互式环境和其他不需要一次性收集所有数据或不需要直接操作推文流或计数的情况,我建议使用这个便捷函数。

使用 ResultStream

ResultStream 对象由 search_args 驱动,接受规则和其他配置参数,包括对 API 调用次数的硬性限制。

rs = ResultStream(rule_payload=rule,
                  max_results=500,
                  max_pages=1,
                  **premium_search_args)

print(rs)
ResultStream: 
	{
    "username":null,
    "endpoint":"https://api.twitter.com/1.1/tweets/search/30day/dev.json",
    "rule_payload":{
        "query":"beyonce",
        "maxResults":100
    },
    "tweetify":true,
    "max_results":500
}

有一个名为 .stream 的函数可以无缝处理给定查询的请求和分页。它返回一个生成器,要获取 500 条提到 beyonce 的推文,我们可以这样做:

tweets = list(rs.stream())

使用我们的 Tweet Parser 懒加载解析推文,因此可以很容易地提取推文数据。

# 使用 unidecode 防止打印表情符号/重音
[print(tweet.all_text) for tweet in tweets[0:10]];
天哪救命 kkkkkkkkkk BEYONCE https://t.co/kJ9zubvKuf
Jay-Z & Beyoncé 今晚坐在我们对面吃饭,有一刻我和 Beyoncé 对视了。我的四肢变成了果冻,再也无法组织一个连贯的句子。我看到了上帝的眼睛。
Beyoncé,没有人能比得上她。https://t.co/UdOU9oUtuW
正如你所猜测的..Beyoncé 的 Signs 永远是我的最爱。
当 Beyoncé 领养了一只狗 🙌🏾 https://t.co/U571HyLG4F
等等,你不能这样对待 Beyoncé
https://t.co/3p14DocGqA
为什么你们还在用 Rihanna 和 Beyoncé 的 gif 来宣传这个节目,明明你们让 Bey 失去了她应得的三个奖项,还让 Rihanna 空手而归? https://t.co/w38QpH0wma
30) 有人说过你长得像 Beyoncé 吗 https://t.co/Vo4Z7bfSCi
我最喜欢的 Beyoncé https://t.co/f9Jp600l2B
Beyoncé 需要看到这个。@TiniStoessel 简直是女神 🔥🔥🔥 https://t.co/gadVJbehQZ
Joanne Pearce 现在正在播放 IF I WAS A BOY - BEYONCE.mp3!

计数端点

我们还可以使用搜索 API 的计数端点来获取符合我们规则的推文数量。每个请求最多可返回 30 天的结果,每个计数请求可以按分钟、小时或天进行。底层的 ResultStream 对象会处理将您的端点转换为计数端点,您需要在创建规则时指定 count_bucket 参数才能使用它。

这个过程与获取推文非常相似,但有一些细微的差别。

注意 - premium 沙盒环境无法访问搜索 API 的计数端点。

count_rule = gen_rule_payload("beyonce", count_bucket="day")

counts = collect_results(count_rule, result_stream_args=enterprise_search_args)

我们的结果很直观,可以快速使用。

counts

[{'count': 366, 'timePeriod': '201801170000'}, {'count': 44580, 'timePeriod': '201801160000'}, {'count': 61932, 'timePeriod': '201801150000'}, {'count': 59678, 'timePeriod': '201801140000'}, {'count': 44014, 'timePeriod': '201801130000'}, {'count': 46607, 'timePeriod': '201801120000'}, {'count': 41523, 'timePeriod': '201801110000'}, {'count': 47056, 'timePeriod': '201801100000'}, {'count': 65506, 'timePeriod': '201801090000'}, {'count': 95251, 'timePeriod': '201801080000'}, {'count': 162883, 'timePeriod': '201801070000'}, {'count': 106344, 'timePeriod': '201801060000'}, {'count': 93542, 'timePeriod': '201801050000'}, {'count': 110415, 'timePeriod': '201801040000'}, {'count': 127523, 'timePeriod': '201801030000'}, {'count': 131952, 'timePeriod': '201801020000'}, {'count': 176157, 'timePeriod': '201801010000'}, {'count': 57229, 'timePeriod': '201712310000'}, {'count': 72277, 'timePeriod': '201712300000'}, {'count': 72051, 'timePeriod': '201712290000'}, {'count': 76371, 'timePeriod': '201712280000'}, {'count': 61578, 'timePeriod': '201712270000'}, {'count': 55118, 'timePeriod': '201712260000'}, {'count': 59115, 'timePeriod': '201712250000'}, {'count': 106219, 'timePeriod': '201712240000'}, {'count': 114732, 'timePeriod': '201712230000'}, {'count': 73327, 'timePeriod': '201712220000'}, {'count': 89171, 'timePeriod': '201712210000'}, {'count': 192381, 'timePeriod': '201712200000'}, {'count': 85554, 'timePeriod': '201712190000'}, {'count': 57829, 'timePeriod': '201712180000'}]

日期搜索 / 完整归档搜索

请注意,这只适用于完整归档搜索选项, 该选项仅通过企业版选项对我的帐户可用。完整 归档搜索可能需要不同的端点或访问 方法;详情请查看您的开发者控制台。

让我们创建一个新规则,这次传入日期。

gen_rule_payload 接受以下形式的时间戳:

  • YYYYmmDDHHMM
  • YYYY-mm-DD(将转换为 UTC 午夜时间 00:00)
  • YYYY-mm-DD HH:MM
  • YYYY-mm-DDTHH:MM

注意 - 所有推文都以 UTC 时间存储。

rule = gen_rule_payload("from:jack",
                        from_date="2017-09-01", #UTC 2017-09-01 00:00
                        to_date="2017-10-30",#UTC 2017-10-30 00:00
                        results_per_call=500)
print(rule)
{"query":"from:jack","maxResults":500,"toDate":"201710300000","fromDate":"201709010000"}
tweets = collect_results(rule, max_results=500, result_stream_args=enterprise_search_args)
[print(tweet.all_text) for tweet in tweets[0:10]];
更明确地说明我们的隐私信息政策和执行情况。也努力在产品中直接构建尽可能多的上下文 https://t.co/IrwBexPrBA
为了更清晰地说明我们的隐私信息政策,我们增加了具体的违规和非违规示例,并深入解释了我们需要从服务中删除此类内容的原因。 https://t.co/NGx5hh2tTQ
11月22日推出暴力团体和仇恨图像/符号政策 https://t.co/NaWuBPxyO5
我们现在将于11月22日推出有关暴力团体和仇恨图像及仇恨符号的政策。在制定过程中,我们收到了宝贵的反馈,我们正在在这些政策发布和执行之前加以实施。更多关于我们政策制定过程的信息请看这里 👇 https://t.co/wx3EeH39BI
@WillStick @lizkelley 生日快乐,Liz!
停止所有俄罗斯今日电视台(RT)和卫星通讯社拥有的账户的广告投放。

我们将捐出所有预计收益(190万美元)以支持对Twitter在选举中使用情况的外部研究,包括恶意自动化和错误信息的使用。 https://t.co/zIxfqqXCZr
@TMFJMo @anthonynoto 谢谢
@gasca @stratechery @Lefsetz 信
@gasca @stratechery Bridgewater的每日观察
没错!!!! ❤️❤️❤️❤️ #davechappelle https://t.co/ybSGNrQpYF
@ndimichino 有时候
在 @CampFlogGnaw 设置 https://t.co/nVq8QjkKsf
rule = gen_rule_payload("from:jack",
                        from_date="2017-09-20",
                        to_date="2017-10-30",
                        count_bucket="day",
                        results_per_call=500)
print(rule)
{"query":"from:jack","toDate":"201710300000","fromDate":"201709200000","bucket":"day"}
counts = collect_results(rule, max_results=500, result_stream_args=enterprise_search_args)
[print(c) for c in counts];
{'时间段': '201710290000', '数量': 0}
{'时间段': '201710280000', '数量': 0}
{'时间段': '201710270000', '数量': 3}
{'时间段': '201710260000', '数量': 6}
{'时间段': '201710250000', '数量': 4}
{'时间段': '201710240000', '数量': 4}
{'时间段': '201710230000', '数量': 0}
{'时间段': '201710220000', '数量': 0}
{'时间段': '201710210000', '数量': 3}
{'时间段': '201710200000', '数量': 2}
{'时间段': '201710190000', '数量': 1}
{'时间段': '201710180000', '数量': 6}
{'时间段': '201710170000', '数量': 2}
{'时间段': '201710160000', '数量': 2}
{'时间段': '201710150000', '数量': 1}
{'时间段': '201710140000', '数量': 64}
{'时间段': '201710130000', '数量': 3}
{'时间段': '201710120000', '数量': 4}
{'时间段': '201710110000', '数量': 8}
{'时间段': '201710100000', '数量': 4}
{'时间段': '201710090000', '数量': 1}
{'时间段': '201710080000', '数量': 0}
{'时间段': '201710070000', '数量': 0}
{'时间段': '201710060000', '数量': 1}
{'时间段': '201710050000', '数量': 3}
{'时间段': '201710040000', '数量': 5}
{'时间段': '201710030000', '数量': 8}
{'时间段': '201710020000', '数量': 5}
{'时间段': '201710010000', '数量': 0}
{'时间段': '201709300000', '数量': 0}
{'时间段': '201709290000', '数量': 0}
{'时间段': '201709280000', '数量': 9}
{'时间段': '201709270000', '数量': 41}
{'时间段': '201709260000', '数量': 13}
{'时间段': '201709250000', '数量': 6}
{'时间段': '201709240000', '数量': 7}
{'时间段': '201709230000', '数量': 3}
{'时间段': '201709220000', '数量': 0}
{'时间段': '201709210000', '数量': 1}
{'时间段': '201709200000', '数量': 7}

贡献
============

任何贡献都应遵循以下模式:

1. 创建一个功能或修复错误的分支,例如,
   ``git checkout -b my_new_feature``
2. 在该分支中进行修改
3. 确保在 ``searchtweets/_version.py`` 中增加版本号以反映你的更改。我们使用 `语义化版本 <https://semver.org>`__,因此非破坏性的增强应该增加次版本号,例如,``1.5.0 -> 1.6.0``,而错误修复将增加最后一位版本号,``1.6.0 -> 1.6.1``。
4. 创建一个拉取请求

拉取请求被接受后,包维护者将处理文档构建和发布到 Pypi。

作为参考,发布到 Pypi 是通过在仓库根目录运行以下命令完成的:

.. code:: bash

   python setup.py bdist_wheel
   python setup.py sdist
   twine upload dist/*

如何构建文档:

构建文档需要一些 Sphinx 包来构建网页:

.. code:: bash

   pip install sphinx
   pip install sphinx_bootstrap_theme
   pip install sphinxcontrib-napoleon

然后(一旦你的更改提交到 master 分支)你应该能够运行生成文档的 bash 脚本并按照说明进行操作:

.. code:: bash

   bash build_sphinx_docs.sh master searchtweets

请注意,这个 README 也是生成的,因此在进行任何 README 更改后,你需要重新构建 README(你需要 pandoc 2.1+ 版本)并提交结果:

.. code:: bash

   bash make_readme.sh
项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

白日梦AI

白日梦AI提供专注于AI视频生成的多样化功能,包括文生视频、动态画面和形象生成等,帮助用户快速上手,创造专业级内容。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

讯飞绘镜

讯飞绘镜是一个支持从创意到完整视频创作的智能平台,用户可以快速生成视频素材并创作独特的音乐视频和故事。平台提供多样化的主题和精选作品,帮助用户探索创意灵感。

Project Cover

讯飞文书

讯飞文书依托讯飞星火大模型,为文书写作者提供从素材筹备到稿件撰写及审稿的全程支持。通过录音智记和以稿写稿等功能,满足事务性工作的高频需求,帮助撰稿人节省精力,提高效率,优化工作与生活。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号