Python 将推文存储到csv文件时出现问题

Python 将推文存储到csv文件时出现问题,python,csv,datetime,twitter,twython,Python,Csv,Datetime,Twitter,Twython,我正在使用Python,试图将与特定关键字相关的推文(更准确地说,仅限于推文的日期、用户、简历和文本)存储在csv文件中。 由于我正在开发Twitter的免费使用API,我每15分钟只能发送450条推文。 所以我编写了一个程序,可以在15分钟内准确存储450条推文 但问题是提取tweet时出现了一些问题,因此在某个特定点,同一条tweet会一次又一次地存储。 任何帮助都将不胜感激!! 提前谢谢 import time from twython import Twython, TwythonErr

我正在使用Python,试图将与特定关键字相关的推文(更准确地说,仅限于推文的日期、用户、简历和文本)存储在csv文件中。 由于我正在开发Twitter的免费使用API,我每15分钟只能发送450条推文。 所以我编写了一个程序,可以在15分钟内准确存储450条推文

但问题是提取tweet时出现了一些问题,因此在某个特定点,同一条tweet会一次又一次地存储。

任何帮助都将不胜感激!! 提前谢谢

import time
from twython import Twython, TwythonError, TwythonStreamer
twitter = Twython(CONSUMER_KEY, CONSUMER_SECRET) 

sfile = "tweets_" + keyword + todays_date + ".csv"
id_list = [last_id]  
count = 0
while count < 3*60*60*2: #we set the loop to run for 3hours

    # tweet extract method with the last list item as the max_id
    print("new crawl, max_id:", id_list[-1])
    tweets = twitter.search(q=keyword, count=2, max_id=id_list[-1])["statuses"]
    time.sleep(2) ## 2 seconds rest between api calls (450 allowed within 15min window)

    for status in tweets:
        id_list.append(status["id"]) ## append tweet id's

        if status==tweets[0]:
            continue

        if status==tweets[1]:
            date = status["created_at"].encode('utf-8')
            user = status["user"]["screen_name"].encode('utf-8') 
            bio = status["user"]["description"].encode('utf-8')
            text = status["text"].encode('utf-8')

            with open(sfile,'a') as sf:
                sf.write(str(status["id"])+ "|||" + str(date) + "|||" + str(user) + "|||" + str(bio) + "|||" + str(text)  +  "\n")

        count += 1
        print(count)
        print(date, text)
导入时间
从twython导入twython、TwythonError、TwythonStreamer
twitter=Twython(消费者密钥,消费者密钥)
sfile=“tweets”+关键字+今天\日期+“.csv”
id\u列表=[最后一个\u id]
计数=0
当计数<3*60*60*2时:#我们将循环设置为运行3小时
#最后一个列表项作为max_id的tweet提取方法
打印(“新爬网,最大id:,id列表[-1])
tweets=twitter.search(q=keyword,count=2,max\u id=id\u list[-1])[“status”]
时间。睡眠(2)##api调用之间休息2秒(15分钟窗口内允许450次)
有关tweets中的状态:
id_list.append(状态[“id”])35;#append tweet id
如果状态==推文[0]:
持续
如果状态==推文[1]:
日期=状态[“创建时间”]。编码('utf-8')
用户=状态[“用户”][“屏幕名称”]。编码('utf-8')
bio=状态[“用户”][“说明”]。编码('utf-8')
text=状态[“text”]。编码('utf-8')
打开(sfile,'a')作为sf:
sf.write(str(status[“id”])+“| | | |”+str(date)+“| | |”+“+str(user)+”+“| | |”+“+str(text)+”\n”)
计数+=1
打印(计数)
打印(日期、文本)

您应该使用Python的CSV库来编写CSV文件。它获取一个包含行的所有项的列表,并自动为您添加分隔符。如果值包含逗号,它会自动为您添加引号(CSV文件就是这样工作的)。它甚至可以处理值内的换行符。如果将生成的文件打开到电子表格应用程序中,您将看到它已正确读入

与其尝试使用
time.sleep()
,不如使用绝对时间。所以我们的想法是把你的开始时间加上三个小时。然后,您可以继续循环,直到达到此
完成时间

同样的方法也可以用于API调用分配。保留一个计数器,记录您已拨打的电话数,并对其进行倒计时。如果到达
0
,则停止拨打电话,直到到达下一个15分钟的时段

timedelta()
可用于向现有的
datetime
对象添加分钟或小时。通过这样做,你的时间永远不会失去同步

下面显示了如何使事情正常工作的模拟。您只需重新添加代码即可获得推文:

from datetime import datetime, timedelta
import time
import csv
import random   # just for simulating a random ID

fifteen = timedelta(minutes=15)
finish_time = datetime.now() + timedelta(hours=3)

calls_allowed = 450
calls_remaining = calls_allowed

now = datetime.now()
next_allocation = now + fifteen

todays_date = now.strftime("%d_%m_%Y")
ids_seen = set()

with open(f'tweets_{todays_date}.csv', 'w', newline='') as f_output:
    csv_output = csv.writer(f_output)

    while now < finish_time:
        time.sleep(2)
        now = datetime.now()

        if now >= next_allocation:
            next_allocation += fifteen
            calls_remaining = calls_allowed
            print("New call allocation")

        if calls_remaining:
            calls_remaining -= 1
            print(f"Get tweets - {calls_remaining} calls remaining")

            # Simulate a tweet response
            id = random.choice(["1111", "2222", "3333", "4444"])    # pick a random ID
            date = "01.01.2019"
            user = "Fred"
            bio = "I am Fred"
            text = "Hello, this is a tweet\nusing a comma and a newline."

            if id not in ids_seen:
                csv_output.writerow([id, date, user, bio, text])
                ids_seen.add(id)
从datetime导入datetime,timedelta
导入时间
导入csv
导入随机#仅用于模拟随机ID
15=时间增量(分钟=15)
finish_time=datetime.now()+timedelta(小时=3)
允许呼叫数=450
calls\u剩余=允许呼叫
now=datetime.now()
下一次分配=现在+15
todays\u date=now.strftime(“%d\u%m\u%Y”)
ids_seen=set()
以open(f'tweets_{todays_date}.csv',w',newline=''作为f_输出:
csv_输出=csv.writer(f_输出)
现在<完成时间:
时间。睡眠(2)
now=datetime.now()
如果现在>=下一次分配:
下一次分配+=15
calls\u剩余=允许呼叫
打印(“新呼叫分配”)
如果剩余的电话:
调用_剩余-=1
打印(f“获取tweets-{calls\u remaining}calls remaining”)
#模拟tweet响应
id=random.choice([“1111”、“2222”、“3333”、“4444”])#选择一个随机id
日期=“2019年1月1日”
user=“Fred”
bio=“我是弗雷德”
text=“您好,这是一条使用逗号和换行符的推特。”
如果id不在id中,请参见:
csv_output.writerow([id、日期、用户、简历、文本])
id_seen.add(id)

至于继续写同样的推文的问题。您可以使用
set()
保存您编写的所有ID。然后,您可以在再次写入之前测试是否已经看到新的tweet。

我建议您在CSV文件中使用标准的逗号分隔符。如果您的tweet包含逗号,则该字段通常用引号括起来。它还能够处理新线。Python的CSV库将自动为您处理所有这些。