Twitter v2 搜索端点现在包含一个“计数”端点,该端点返回匹配推文的时间序列总数。
该项目充当 Twitter 高级和企业搜索 API 的包装器,提供命令行实用程序和 Python 库。漂亮的文档可以在这里看到。
jq
)。searchtweets
库位于 Pypi 上:
pip install searchtweets
或者您可以通过以下方式在本地安装开发版本
git clone https://github.com/twitterdev/search-tweets-python
cd search-tweets-python
pip install -e .
高级搜索 API 和企业搜索 API 使用不同的身份验证方法,我们尝试提供一种无缝的方式来处理所有客户的身份验证。我们知道凭据可能很棘手或烦人 - 请完整阅读本文。
高级客户端将需要bearer_token
和endpoint
字段;企业客户端需要username
、 password
和endpoint
。如果您不指定account_type
,我们会尝试识别帐户类型并声明有关此行为的警告。
对于高级搜索产品,我们使用仅应用程序身份验证,并且不记名令牌不会在过期时间内传递。您可以提供: - 您的应用程序密钥和秘密(库将处理不记名令牌身份验证) - 您自己获得的不记名令牌
许多开发人员可能会发现提供应用程序密钥和秘密更简单,并让该库为您管理不记名令牌的生成。请参阅此处了解高级身份验证方法的概述。
我们支持基于 YAML 文件的方法和环境变量来存储凭据,并通过合理的默认值提供灵活的处理。
对于高级客户,最简单的凭证文件应如下所示:
search_tweets_api :
account_type : premium
endpoint : <FULL_URL_OF_ENDPOINT>
consumer_key : <CONSUMER_KEY>
consumer_secret : <CONSUMER_SECRET>
对于企业客户来说,最简单的凭证文件应该是这样的:
search_tweets_api :
account_type : enterprise
endpoint : <FULL_URL_OF_ENDPOINT>
username : <USERNAME>
password : <PW>
默认情况下,该库需要此文件位于"~/.twitter_keys.yaml"
,但您可以根据需要传递相关位置,可以使用命令行应用程序的--credential-file
标志,也可以像下面在 Python 中演示的那样程序。
上述两个示例都不需要特殊的命令行参数或程序内参数。除非另有指定,凭证解析方法将查找名为search_tweets_api
的 YAML 键。
对于拥有多个端点和/或搜索产品的开发人员,您可以将所有凭据保存在同一文件中并指定要使用的特定密钥。 --credential-file-key
在命令行应用程序中指定此行为。一个例子:
search_tweets_30_day_dev :
account_type : premium
endpoint : <FULL_URL_OF_ENDPOINT>
consumer_key : <KEY>
consumer_secret : <SECRET>
(optional) bearer_token : <TOKEN>
search_tweets_30_day_prod :
account_type : premium
endpoint : <FULL_URL_OF_ENDPOINT>
bearer_token : <TOKEN>
search_tweets_fullarchive_dev :
account_type : premium
endpoint : <FULL_URL_OF_ENDPOINT>
bearer_token : <TOKEN>
search_tweets_fullarchive_prod :
account_type : premium
endpoint : <FULL_URL_OF_ENDPOINT>
bearer_token : <TOKEN>
如果您想要或需要通过环境变量传递凭据,您可以为您的产品设置以下适当的变量:
导出 SEARCHTWEETS_ENDPOINT= 导出 SEARCHTWEETS_USERNAME= 导出 SEARCHTWEETS_PASSWORD= 导出 SEARCHTWEETS_BEARER_TOKEN= 导出 SEARCHTWEETS_ACCOUNT_TYPE= 导出 SEARCHTWEETS_CONSUMER_KEY= 导出 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 )
{'用户名': '<MY_USERNAME>', '密码': '<我的密码>', '端点':'<MY_ENDPOINT>'}
load_credentials ( filename = "./search_tweets_creds_example.yaml" ,
yaml_key = "search_tweets_premium_example" ,
env_overwrite = False )
{'bearer_token': '<A_VERY_LONG_MAGIC_STRING>', '端点':'https://api.twitter.com/1.1/tweets/search/30day/dev.json', 'extra_headers_dict':无}
如果我们设置环境变量,无论 YAML 文件是否有效或是否存在,程序都会查找它们。
import os
os . environ [ "SEARCHTWEETS_USERNAME" ] = "<ENV_USERNAME>"
os . environ [ "SEARCHTWEETS_PASSWORD" ] = "<ENV_PW>"
os . environ [ "SEARCHTWEETS_ENDPOINT" ] = "<https://endpoint>"
load_credentials ( filename = "nothing_here.yaml" , yaml_key = "no_key_here" )
无法读取文件nothing_here.yaml 解析 YAML 文件时出错;搜索有效的环境变量
{'用户名': '<ENV_USERNAME>', '密码': '<ENV_PW>', '端点':'<https://端点>'}
标志:
--credential-file <FILENAME>
--credential-file-key <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 结果流式传输到 stdout 并保存到文件
search_tweets.py
--max-results 1000
--results-per-call 100
--filter-rule " beyonce has:hashtags "
--filename-prefix beyonce_geo
--print-stream
保存到文件而不输出
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 格式字符串从命令行指定一个或多个自定义标头:
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
文件中找到,可能如下所示:
[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
或者这个:
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
可以在配置文件中的特定凭据密钥下指定自定义标头:
search_tweets_api :
account_type : premium
endpoint : <FULL_URL_OF_ENDPOINT>
username : <USERNAME>
password : <PW>
extra_headers :
<MY_HEADER_KEY> : <MY_HEADER_VALUE>
将配置文件与命令行实用程序结合使用时,您需要通过--config-file
参数指定配置文件。附加的命令行参数将被添加到配置文件 args 中,或者覆盖配置文件 args(如果指定并存在)。
例子:
search_tweets.py --config-文件 myapiconfig.config --无打印流
完整选项如下:
$ search_tweets.py -h 用法:search_tweets.py [-h] [--credential-file CREDENTIAL_FILE] [--凭证文件密钥 CREDENTIAL_YAML_KEY] [--env-overwrite ENV_OVERWRITE] [--配置文件 CONFIG_FILENAME] [--账户类型{高级版,企业}] [--计数桶 COUNT_BUCKET] [--开始日期时间 FROM_DATE] [--结束日期时间 TO_DATE] [--过滤规则 PT_RULE] [--每次调用结果 RESULTS_PER_CALL] [--最大结果 MAX_RESULTS] [--最大页数 MAX_PAGES] [--每个文件结果RESULTS_PER_FILE] [--文件名前缀 FILENAME_PREFIX] [--无打印流] [--打印流] [--额外标头 EXTRA_HEADERS] [--调试] 可选参数: -h, --help 显示此帮助消息并退出 --凭证文件 CREDENTIAL_FILE 用于保存您的 yaml 文件的位置 证书。 --凭证文件密钥 CREDENTIAL_YAML_KEY 用于此会话的凭证文件中的密钥 证书。默认为 search_tweets_api --env-overwrite ENV_OVERWRITE 使用任何设置覆盖 YAML 解析的凭据 环境变量。请参阅 API 文档或自述文件 细节。 --config 文件 CONFIG_FILENAME 包含所有参数的配置文件。远一点,更容易 使用比命令行参数版本。,如果有效 找到文件后,将从那里填充所有参数。 剩余的命令行参数将否决找到的参数 在配置文件中。 --帐户类型 {高级、企业} 您使用的账户类型 --count-bucket COUNT_BUCKET 设置此项以发出“计数”请求。计数端点的存储桶大小。选项:、天、小时、 分钟。 --开始日期时间 FROM_DATE 日期时间窗口的开始,格式“YYYY-mm-DDTHH:MM” (默认值:-30 天) --结束日期时间 TO_DATE 日期时间窗口结束,格式“YYYY-mm-DDTHH:MM” (默认:最近日期) --过滤规则 PT_RULE PowerTrack 过滤规则(参见:http://support.gnip.com/c 客户/门户/文章/901152-powertrack-operators) --每次调用结果 RESULTS_PER_CALL 每次调用返回的结果数(默认 100;最大 500) - 对应于 API 中的“maxResults”。如果使用“--count-bucket”发出“counts”请求,则忽略此参数。 --最大结果 MAX_RESULTS 为此返回的推文或计数的最大数量 会话(默认为 500) --最大页数 MAX_PAGES 为此使用的最大页面数/API 调用数 会议。 --每个文件结果RESULTS_PER_FILE 每个文件保存的最大推文数。 --文件名前缀 FILENAME_PREFIX tweet json 数据所在文件名的前缀 存储。 --no-print-stream 禁用打印流 --print-stream 将推文流打印到标准输出 --extra-headers EXTRA_HEADERS JSON 格式的 str 表示附加的字典 请求标头 --debug 打印所有信息和警告消息
对于高级版和企业版客户端来说,在 Python 程序中使用 API 都很简单。
我们假设凭证位于默认位置~/.twitter_keys.yaml
。
from searchtweets import ResultStream , gen_rule_payload , load_credentials
enterprise_search_args = load_credentials ( "~/.twitter_keys.yaml" ,
yaml_key = "search_tweets_enterprise" ,
env_overwrite = False )
premium_search_args = load_credentials ( "~/.twitter_keys.yaml" ,
yaml_key = "search_tweets_premium" ,
env_overwrite = False )
有一个函数可以将搜索 API 规则格式化为有效的 json 查询,称为gen_rule_payload
。它具有合理的默认值,例如每次调用拉取的推文数量多于默认的 100 条(但请注意,沙盒环境此处最多只能有 100 条,因此如果出现错误,请检查此项),不包括日期。讨论生成搜索规则的细节超出了这些示例的范围;我鼓励您查看文档以了解其中的细微差别,但现在让我们看看规则是什么样的。
rule = gen_rule_payload ( "beyonce" , results_per_call = 100 ) # testing with a sandbox account
print ( rule )
{“查询”:“碧昂丝”,“maxResults”:100}
此规则将匹配其中包含文本beyonce
的推文。
从这一点来看,与API交互的方式有两种。有一种快速方法可以将少量推文收集到内存中,该方法需要较少的思考和知识,以及与ResultStream
对象的交互(稍后将介绍)。
我们将使用search_args
变量来支持 API 的配置点。该对象还采用有效的 PowerTrack 规则,并具有在推文和 API 调用数量达到限制时切断搜索的选项。
我们将使用collect_results
函数,它有三个参数。
对于其余示例,请根据您的使用情况将参数更改为 premium 或 enterprise。
让我们看看情况如何:
from searchtweets import collect_results
tweets = collect_results ( rule ,
max_results = 100 ,
result_stream_args = enterprise_search_args ) # change this if you need to
默认情况下,Tweet 有效负载被延迟解析为Tweet
对象。大量推文属性可直接使用,如下所示:
[ print ( tweet . all_text , end = ' n n ' ) for tweet in tweets [ 0 : 10 ]];
Jay-Z&今晚晚餐时,碧昂斯坐在我们对面,有一次,我与碧昂斯进行了眼神交流。我的四肢变成了果冻,我无法再说出一个连贯的句子。我已经看到了主的眼睛。 碧昂丝和它并不接近。 https://t.co/UdOU9oUtuW 你可能猜到了……碧昂丝的标志永远是我的狗屎。 碧昂丝何时收养了一只狗? https://t.co/U571HyLG4F 等等,你不能只对碧昂丝这样做 https://t.co/3p14DocGqA 为什么你们还要继续用蕾哈娜和碧昂丝的 gif 来宣传节目,而你们却让贝 3 次失去了她应得的同一个奖项,并让蕾哈娜除了背上的衣服什么也没有离开? https://t.co/w38QpH0wma 30) 有人告诉你你看起来像碧昂斯 https://t.co/Vo4Z7bfSCi 我最爱的碧昂丝 https://t.co/f9Jp600l2B 碧昂丝是必要的。 Que diosa @TiniStoessel https://t.co/gadVJbehQZ Joanne Pearce 现在正在播放 IF I WAS A BOY - BEYONCE.mp3 by ! 我想在死之前看看碧昂丝的最后一部
[ 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 ]];
iPhone 版推特 iPhone 版推特 iPhone 版推特 iPhone 版推特 iPhone 版推特 iPhone 版推特 安卓版推特 iPhone 版推特 通话时间专业版 iPhone 版推特
瞧,我们有一些推文。对于交互式环境以及您不关心在单次加载中收集数据或不需要直接对推文流或计数进行操作的其他情况,我建议使用此便利功能。
ResultStream 对象将由search_args
提供支持,并采用规则和其他配置参数,包括页面数量的硬停止以限制 API 调用的使用。
rs = ResultStream ( rule_payload = rule ,
max_results = 500 ,
max_pages = 1 ,
** premium_search_args )
print ( rs )
结果流: { “用户名”:空, “端点”:“https://api.twitter.com/1.1/tweets/search/30day/dev.json”, “规则有效负载”:{ "query":"碧昂斯", “最大结果”:100 }, “推文”:正确, “最大结果”:500 }
有一个函数.stream
可以无缝处理给定查询的请求和分页。它返回一个生成器,为了获取 500 条提到beyonce
推文,我们可以这样做:
tweets = list ( rs . stream ())
使用我们的推文解析器延迟解析推文,因此推文数据很容易提取。
# using unidecode to prevent emoji/accents printing
[ print ( tweet . all_text ) for tweet in tweets [ 0 : 10 ]];
温柔的索科罗 kkkkkkkkkk 碧昂丝 https://t.co/kJ9zubvKuf Jay-Z&今晚晚餐时,碧昂斯坐在我们对面,有一次,我与碧昂斯进行了眼神交流。我的四肢变成了果冻,我无法再说出一个连贯的句子。我已经看到了主的眼睛。 碧昂丝和它并不接近。 https://t.co/UdOU9oUtuW 你可能猜到了……碧昂丝的标志永远是我的狗屎。 碧昂斯何时收养了一只狗? https://t.co/U571HyLG4F 等等,你不能只对碧昂丝这样做 https://t.co/3p14DocGqA 为什么你们还要继续用蕾哈娜和碧昂丝的 gif 来宣传节目,而你们却让贝 3 次失去了她应得的同一个奖项,并让蕾哈娜除了背上的衣服什么也没有离开? https://t.co/w38QpH0wma 30) 有人告诉你你看起来像碧昂斯 https://t.co/Vo4Z7bfSCi 我最爱的碧昂丝 https://t.co/f9Jp600l2B 碧昂丝是必要的。 Que diosa @TiniStoessel https://t.co/gadVJbehQZ Joanne Pearce 现在正在播放 IF I WAS A BOY - BEYONCE.mp3 by !
我们还可以使用搜索 API 计数端点来获取与我们的规则匹配的推文计数。每个请求将返回最多30 天的结果,每个计数请求可以按分钟、每小时或每天进行。底层ResultStream
对象将处理将端点转换为计数端点,并且在制定使用它的规则时必须指定count_bucket
参数。
该过程与抓取推文非常相似,但有一些细微的差别。
警告 - 高级沙箱环境无法访问搜索 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 )
{“查询”:“来自:杰克”,“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 莉兹生日快乐! 从今日俄罗斯 (RT) 和 Sputnik 拥有的所有帐户中删除广告。 我们将捐赠所有预计收入(1.9 毫米)来支持对 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”:“天”}
counts = collect_results ( rule , max_results = 500 , result_stream_args = enterprise_search_args )
[ print ( c ) for c in counts ];
{'timePeriod': '201710290000', '计数': 0} {'timePeriod': '201710280000', '计数': 0} {'timePeriod': '201710270000', '计数': 3} {'timePeriod': '201710260000', '计数': 6} {'timePeriod': '201710250000', '计数': 4} {'timePeriod': '201710240000', '计数': 4} {'timePeriod': '201710230000', '计数': 0} {'timePeriod': '201710220000', '计数': 0} {'timePeriod': '201710210000', '计数': 3} {'timePeriod': '201710200000', '计数': 2} {'timePeriod': '201710190000', '计数': 1} {'timePeriod': '201710180000', '计数': 6} {'timePeriod': '201710170000', '计数': 2} {'timePeriod': '201710160000', '计数': 2} {'timePeriod': '201710150000', '计数': 1} {'timePeriod': '201710140000', '计数': 64} {'timePeriod': '201710130000', '计数': 3} {'timePeriod': '201710120000', '计数': 4} {'timePeriod': '201710110000', '计数': 8} {'timePeriod': '201710100000', '计数': 4} {'timePeriod': '201710090000', '计数': 1} {'timePeriod': '201710080000', '计数': 0} {'timePeriod': '201710070000', '计数': 0} {'timePeriod': '201710060000', '计数': 1} {'timePeriod': '201710050000', '计数': 3} {'timePeriod': '201710040000', '计数': 5} {'timePeriod': '201710030000', '计数': 8} {'timePeriod': '201710020000', '计数': 5} {'timePeriod': '201710010000', '计数': 0} {'timePeriod': '201709300000', '计数': 0} {'timePeriod': '201709290000', '计数': 0} {'timePeriod': '201709280000', '计数': 9} {'timePeriod': '201709270000', '计数': 41} {'timePeriod': '201709260000', '计数': 13} {'timePeriod': '201709250000', '计数': 6} {'timePeriod': '201709240000', '计数': 7} {'timePeriod': '201709230000', '计数': 3} {'timePeriod': '201709220000', '计数': 0} {'timePeriod': '201709210000', '计数': 1} {'timePeriod': '201709200000', '计数': 7}
任何贡献都应遵循以下模式:
git checkout -b my_new_feature
searchtweets/_version.py
中更改版本号以反映您的更改。我们使用语义版本控制,因此不间断的增强功能应增加次要版本,例如1.5.0 -> 1.6.0
,而错误修复将增加最后一个版本, 1.6.0 -> 1.6.1
。拉取请求过程被接受后,包维护者将处理构建文档并分发到 Pypi。
作为参考,分发到 Pypi 是通过以下命令完成的,从存储库的根目录运行:
python setup.py bdist_wheel
python setup.py sdist
twine upload dist/ *
如何构建文档:
构建文档需要一些 Sphinx 包来构建网页:
pip install sphinx
pip install sphinx_bootstrap_theme
pip install sphinxcontrib-napoleon
然后(一旦您的更改提交给 master)您应该能够运行文档生成 bash 脚本并按照说明进行操作:
bash build_sphinx_docs.sh master searchtweets
请注意,此自述文件也会生成,因此在任何自述文件更改后,您需要重新构建自述文件(为此需要 pandoc 版本 2.1+)并提交结果:
bash make_readme.sh