проблема при сохранении твитов в CSV-файл - PullRequest
2 голосов
/ 07 марта 2019

Я работаю с Python, пытаясь сохранить твиты (точнее, только их дату, пользователя, биографию и текст), связанные с определенным ключевым словом, в CSV-файле. Поскольку я работаю над бесплатным API Twitter, я ограничен 450 твитами каждые 15 минут. Итак, я написал что-то, что должно хранить ровно 450 твитов за 15 минут.

НО проблема в том, что что-то идет не так при извлечении твитов , так что в определенной точке один и тот же твит сохраняется снова и снова.

Любая помощь будет высоко ценится! Заранее спасибо

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)

1 Ответ

0 голосов
/ 08 марта 2019

Вы должны использовать библиотеку Python CSV для записи ваших файлов CSV. Он берет список, содержащий все элементы для строки, и автоматически добавляет разделители для вас. Если значение содержит запятую, оно автоматически добавляет кавычки для вас (именно так должны работать файлы CSV). Он может даже обрабатывать переводы строк внутри значения. Если вы откроете полученный файл в приложении для работы с электронными таблицами, вы увидите, что он правильно прочитан.

Вместо того, чтобы пытаться использовать time.sleep(), лучше использовать абсолютное время. Таким образом, идея состоит в том, чтобы взять ваше время начала и добавить три часа к нему. Затем вы можете продолжать цикл до тех пор, пока не будет достигнут finish_time.

Тот же подход может быть применен к распределению вызовов API. Держите счетчик, показывающий, сколько звонков у вас осталось, и уменьшите его. Если он достигает 0, прекратите звонить, пока не будет достигнут следующий пятнадцатиминутный интервал.

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)

Что касается проблемы продолжения написания одних и тех же твитов. Вы можете использовать set() для хранения всех идентификаторов, которые вы написали. Затем вы можете проверить, был ли новый твит уже просмотрен, прежде чем писать снова.

...