如何为Twitter API v2最近的搜索循环python代码?

如何为Twitter API v2最近的搜索循环python代码?,python,twitter,Python,Twitter,我对python非常陌生,因此我正在寻求有关此问题的帮助。我的目标是收集大约10000条包含图像的推文,并将其保存到csv文件中。由于Twitter的速率限制是每15分钟450个请求,理想情况下我想自动化这个过程。我看到的指南只使用了tweepy模块,但由于我不太了解它,所以我使用了Twitter上给出的python示例代码: import requests import pandas as pd import os import json # To set your enviornment

我对python非常陌生,因此我正在寻求有关此问题的帮助。我的目标是收集大约10000条包含图像的推文,并将其保存到csv文件中。由于Twitter的速率限制是每15分钟450个请求,理想情况下我想自动化这个过程。我看到的指南只使用了tweepy模块,但由于我不太了解它,所以我使用了Twitter上给出的python示例代码:

import requests
import pandas as pd
import os
import json

# To set your enviornment variables in your terminal run the following line:
os.environ['BEARER_TOKEN']=''


def auth():
    return os.environ.get("BEARER_TOKEN")


def create_url():
    query = "has:images lang:en -is:retweet"
    tweet_fields = "tweet.fields=attachments,created_at,author_id"
    expansions = "expansions=attachments.media_keys"
    media_fields = "media.fields=media_key,preview_image_url,type,url"
    max_results = "max_results=100"
    url = "https://api.twitter.com/2/tweets/search/recent?query={}&{}&{}&{}&{}".format(
        query, tweet_fields, expansions, media_fields, max_results
    )
    return url


def create_headers(bearer_token):
    headers = {"Authorization": "Bearer {}".format(bearer_token)}
    return headers


def connect_to_endpoint(url, headers):
    response = requests.request("GET", url, headers=headers)
    print(response.status_code)
    if response.status_code != 200:
        raise Exception(response.status_code, response.text)
    return response.json()

def save_json(file_name, file_content):
    with open(file_name, 'w', encoding='utf-8') as write_file:
        json.dump(file_content, write_file, sort_keys=True, ensure_ascii=False, indent=4)

def main():
    bearer_token = auth()
    url = create_url()
    headers = create_headers(bearer_token)
    json_response = connect_to_endpoint(url, headers)
    
    #Save the data as a json file
    #save_json('collected_tweets.json', json_response)
    
    #save tweets as csv
    #df = pd.json_normalize(data=json_response)
    df1 = pd.DataFrame(json_response['data'])
    df1.to_csv('tweets_data.csv', mode="a")
    df2 = pd.DataFrame(json_response['includes'])
    df2.to_csv('tweets_includes_media.csv', mode="a")
    print(json.dumps(json_response['meta'], sort_keys=True, indent=4))

if __name__ == "__main__":
    main()
我应该如何修改这段代码,使其在Twitter的v2速率限制内循环,还是改用tweepy更好

顺便说一句,我确实意识到我的“另存为csv”代码有问题,但这是我现在能做的最好的事情。

尝试使用调度程序:

import sched
import time

scheduler = sched.scheduler(time.time, time.sleep)
scheduler.enter(delay=16 * 60, priority=1, action=connect_to_endpoint)
耽搁

是两个事件之间的时间量

行动

是每16分钟执行一次的方法(在本例中)


考虑重复的确切时间和确切方法。

这里有几件事需要记住

  • Tweepy尚未更新为使用新版本的Twitter API(V2),因此您在Twitter文档中大部分时间会发现的内容可能与Tweepy提供的内容不一致。Tweepy仍然可以很好地与V1配合使用,但是,一些tweet匹配功能可能会有所不同,您只需要小心
  • 鉴于您提到的目标,不清楚您是否希望使用最近的搜索端点。例如,可以更容易地使用启动1%的流。这是针对该端点的。这样做的主要好处是,您可以在“后台”(参见下面的注释)中运行它,并使用一个条件,一旦您收集了10k条tweet,它就会终止该进程。这样,您就不必担心达到tweet限制-Twitter默认情况下将您限制在查询量的约1%(在您的情况下,
    “has:images lang:en-is:retweet”
    )并实时收集这些tweet。如果您试图在两个时段之间获得非转发英语推文的完整记录,则需要将这些时间点添加到查询中,然后按照上述要求管理限制。查看中的
    start\u time
    end\u time
注意:要在后台运行脚本,请编写程序,然后从终端使用
nohup nameofstreamingcode.py>logfile.log 2>&1&
执行它。任何正常的终端输出(即打印行和/或错误)都会写入一个名为
logfile.log
的新文件,命令末尾的
&
会使进程在后台运行(因此您可以关闭终端,稍后再返回)

  • 要使用最近的搜索端点,您需要在
    connect\u-To\u端点(url,headers)
    函数中添加大量内容。此外,您还可以使用另一个函数
    pause_until
    ,该函数是为我正在开发的Twitter V2 API包编写的()
def connect_-to_端点(url、标题):
response=requests.request(“GET”,url,headers=headers)
#Twitter(在请求对象的头部)返回多少
#你留下的请求。让我们利用这个优势
剩余的请求=int(response.headers[“x-rate-limit-remaining”])
#如果这个数字是1,我们得到重置时间
#然后再等15秒(欢迎你的Twitter)。
#下面还捕获了常规429异常,
#然而,我们希望在可能的情况下进行防御计划。
如果剩余的_请求==1:
缓冲区等待时间=15
resume\u time=datetime.fromtimestamp(int(response.headers[“x-rate-limit-reset”])+缓冲区等待时间)
打印(f“正在Twitter上等待。\n\t使用时间:{resume\u Time}”)
暂停_直到(恢复时间)##在上述答案中链接到此代码
#我们仍然可能会从Twitter上收到一些奇怪的错误。
#我们只关心与时间相关的错误(即错误
#推特希望我们等待的消息)。
#大多数错误都可以通过等待来解决
#过了一会儿,我们又在推特上发ping——我们就是这么做的。
if response.status_代码!=200:
#错误请求太多
如果response.status_code==429:
缓冲区等待时间=15
resume\u time=datetime.fromtimestamp(int(response.headers[“x-rate-limit-reset”])+缓冲区等待时间)
打印(f“正在Twitter上等待。\n\t使用时间:{resume\u Time}”)
暂停_直到(恢复时间)##在上述答案中链接到此代码
#Twitter内部服务器错误
elif response.status_code==500:
#推特需要休息,所以我们等30秒
resume_time=datetime.now().timestamp()+30
打印(f“正在Twitter上等待。\n\t使用时间:{resume\u Time}”)
暂停_直到(恢复时间)##在上述答案中链接到此代码
#Twitter服务不可用错误
elif response.status_code==503:
#推特需要休息,所以我们等30秒
resume_time=datetime.now().timestamp()+30
打印(f“正在Twitter上等待。\n\t使用时间:{resume\u Time}”)
暂停_直到(恢复时间)##在上述答案中链接到此代码
#如果我们走到这一步,我们做错了什么,应该退出
引发异常(
请求返回错误:{}{}(
response.status_代码,response.text
)
)
#每次我们得到一个200响应,让我们退出函数并返回response.json
如果response.ok:
返回response.json()
由于完整的查询结果将远远大于您在每个查询中请求的100条tweet,因此您需要在更大的查询中跟踪您的位置。这是通过一个网络来完成的

要获得
下一个\u令牌
,实际上相当容易。只需从响应中的元字段中获取它。为了清楚起见,您可以像这样使用上述函数