[PYTHON] J'ai refactoré "J'ai essayé de faire un script qui enregistre les images postées à la fois en retournant sur les tweets d'un utilisateur spécifique sur Twitter".

Voir @ tyokuyoku's "J'ai créé un script qui renvoie aux tweets d'un utilisateur spécifique sur Twitter et enregistre les images publiées à la fois" Ce n'est pas fonctionnalisé et l'emboîtement est assez profond, donc je pense qu'il peut être amélioré. Je pensais que c'était refactorisé. J'ai commenté le résultat du refactoring, mais je vais l'expliquer car il a été revu plus en détail. Je suis moi-même en train de refactoriser par essais et erreurs, donc si vous avez d'autres bonnes idées, je vous serais reconnaissant si vous pouviez commenter.

Tout d'abord, faites de la partie la plus profonde du nid une fonction. Le contenu de traitement "enregistre-t-il les données d'image trouvées dans un fichier à une extrémité"? Puisqu'il s'agit d'un processus d'analyse, le nom de la fonction est crawl.

def crawl():
    for image, filename in images():
        path = os.path.join(SAVE_DIRECTORY, filename)
        with open(path, 'wb') as localfile:
            localfile.write(image)

Je n'ai pas encore de fonction d'images, mais s'il existe une fonction qui récupère (répertorie) les données d'image et les noms de fichiers les uns après les autres, c'est juste un travail pour les enregistrer dans un fichier. Maintenant, créons une fonction d'images qui fait cela. Tout d'abord, implémentez uniquement le processus de récupération des données d'image.

def images():
    for url in image_url():
        image = urllib.urlopen(url)
        yield image.read()
        image.close()

Il n'y a pas encore de fonction image_url, mais s'il existe une fonction qui énumère l'url des données d'image, c'est juste un travail pour lire les données d'image à la destination de l'url et les produire. S'il s'agit d'un retour, le résultat sera renvoyé une fois et le processus se terminera, mais en utilisant une fonction de générateur qui utilise yield, les résultats peuvent être notifiés les uns après les autres. Ajoutez un processus à cette fonction qui notifie également le nom du fichier. Il s'écarte du principe de responsabilité unique du principe SOLID, mais ...

def images():
    for urls, timestamp in image_urls():
        date_time = timestamp.strftime("%Y%m%d_%H%M%S")
        for index, url in enumerate(urls):
            _, ext = os.path.splitext(url)
            filename = '%s_%s_%s%s' % (USER_NAME, date_time, index, ext)
            image = urllib.urlopen(url)
            yield image.read(), filename
            image.close()

Le nom du fichier est créé à partir de l'heure du tweet, mais comme l'image n'inclut pas l'heure du tweet, je vais laisser la fonction image_urls me le dire. Étant donné que plusieurs images peuvent être collées sur un tweet, une seule fois sera liée à plusieurs images. Veuillez me dire l'heure du tweet avec le standard python datetime et le convertir en année / mois / jour_heure / minute / seconde utilisé pour le nom du fichier. À L'extension du nom de fichier a été fixée à "" .jpg "dans le programme d'origine, mais il y a aussi" .png "` etc., donc je vais retirer l'extension incluse dans l'url et l'utiliser. Vient ensuite la fonction image_urls.

def image_urls():
    for media, timestamp in medias():
        urls = [content["media_url_https"]
                for content in media
                if content.get("type") == "photo"]
        yield urls, timestamp

Le tweet contient des informations multimédias telles que des images accompagnées d'une courte phrase (texte), et s'il existe une fonction médias qui énumère les informations multimédias, il est possible d'extraire uniquement l'URL d'image de type «photo» des informations multimédias et de la notifier. Je vais. Puisque les informations médiatiques n'incluent pas l'heure du tweet, nous demanderons à la fonction média de nous indiquer également l'heure du tweet. Vient ensuite la fonction medias.

def medias():
    for tweet in tweets():
        created_at = tweet["created_at"]
        timestamp = dateutil.parser.parse(created_at)
        extended_entities = tweet.get("extended_entities", {})
        media = extended_entities.get("media", ())
        yield media, timestamp

S'il existe une fonction tweets qui énumère les tweets dans l'ordre, vous pouvez récupérer l'heure et les médias du tweet et les notifier. Il est possible qu'il n'y ait pas d'informations sur les entrées_étendues ou sur les médias, mais s'il n'y a pas d'informations, un taple vide est notifié pour vous faire savoir qu'il n'y a pas d'image. Enfin, la fonction tweets.

USER_NAME = 'Nom d'utilisateur que vous souhaitez obtenir'
NUM_OF_TWEET_AT_ONCE = 200      # max: 200
NUM_OF_TIMES_TO_CRAWL = 16      # max: 3200 / NUM_OF_TWEET_AT_ONCE
SAVE_DIRECTORY = os.path.join('.', 'images')

def tweets():
    import twitkey
    twitter = OAuth1Session(twitkey.CONSUMER_KEY,
                            twitkey.CONSUMER_SECRET,
                            twitkey.ACCESS_TOKEN,
                            twitkey.ACCESS_TOKEN_SECRET)
    url = ("https://api.twitter.com/1.1/statuses/user_timeline.json"
           "?screen_name=%s&include_rts=false" % USER_NAME)
    params = {"count": NUM_OF_TWEET_AT_ONCE}
    for i in range(NUM_OF_TIMES_TO_CRAWL):
        req = twitter.get(url, params=params)
        if req.status_code != requests.codes.ok:
            return
        timeline = json.loads(req.text)
        for tweet in timeline:
            yield tweet
            params["max_id"] = tweet["id"]

Vous devez utiliser l'API Twitter pour obtenir des tweets, et vous devez vous inscrire en tant qu'utilisateur avec Twitter à l'avance pour obtenir la clé et le jeton pour accéder à l'API Twitter. Écrivez ces informations sous forme de variable dans un fichier appelé twitkey.py. La source du programme et les informations confidentielles sont séparées. Dans le script d'origine, il s'agit d'une variable de dictionnaire, mais vous pouvez également simplement affecter une variable.

twitkey.py


#coding: UTF-8

CONSUMER_KEY = ""
CONSUMER_SECRET = ""
ACCESS_TOKEN = ""
ACCESS_TOKEN_SECRET = ""

Après tout, l'imbrication a été approfondie dans l'instruction for, mais elle a été rendue moins profonde en en faisant une fonction de générateur utilisant le rendement. En séparant les fonctions, le nom de la fonction devient également un commentaire qui indique le contenu du traitement, et je pense qu'il sera plus facile de comprendre le traitement.

Enfin, je publierai l'intégralité du script, y compris le processus principal, l'importation et l'impression d'affichage de la progression.

#!/usr/bin/env python2
# -*- coding:utf-8 -*-

import sys
import os.path
import dateutil.parser
import urllib
import requests
import json
from requests_oauthlib import OAuth1Session


USER_NAME = 'Nom d'utilisateur que vous souhaitez obtenir'
NUM_OF_TWEET_AT_ONCE = 200      # max: 200
NUM_OF_TIMES_TO_CRAWL = 16      # max: 3200 / NUM_OF_TWEET_AT_ONCE
SAVE_DIRECTORY = os.path.join('.', 'images')


def tweets():
    import twitkey
    twitter = OAuth1Session(twitkey.CONSUMER_KEY,
                            twitkey.CONSUMER_SECRET,
                            twitkey.ACCESS_TOKEN,
                            twitkey.ACCESS_TOKEN_SECRET)
    url = ("https://api.twitter.com/1.1/statuses/user_timeline.json"
           "?screen_name=%s&include_rts=false" % USER_NAME)
    params = {"count": NUM_OF_TWEET_AT_ONCE}
    for i in range(NUM_OF_TIMES_TO_CRAWL):
        req = twitter.get(url, params=params)
        if req.status_code != requests.codes.ok:
            print "ERROR:", req.status_code
            return
        timeline = json.loads(req.text)
        for tweet in timeline:
            print "TWEET:", tweet["text"]
            yield tweet
            params["max_id"] = tweet["id"]



def medias():
    for tweet in tweets():
        created_at = tweet["created_at"]
        timestamp = dateutil.parser.parse(created_at)
        extended_entities = tweet.get("extended_entities", {})
        media = extended_entities.get("media", ())
        print "CREATE:", created_at
        yield media, timestamp


def image_urls():
    for media, timestamp in medias():
        urls = [content["media_url_https"]
                for content in media
                if content.get("type") == "photo"]
        print "IMAGE:", len(urls)
        yield urls, timestamp


def images():
    for urls, timestamp in image_urls():
        date_time = timestamp.strftime("%Y%m%d_%H%M%S")
        for index, url in enumerate(urls):
            _, ext = os.path.splitext(url)
            filename = '%s_%s_%s%s' % (USER_NAME, date_time, index, ext)
            image = urllib.urlopen(url)
            print "URL:", url
            yield image.read(), filename
            image.close()


def crawl():
    for image, filename in images():
        path = os.path.join(SAVE_DIRECTORY, filename)
        print "SAVE:", path
        with open(path, 'wb') as localfile:
            localfile.write(image)


if __name__ == '__main__':
    if len(sys.argv) > 1:
        USER_NAME = sys.argv[1]
    crawl()

Recommended Posts

J'ai refactoré "J'ai essayé de faire un script qui enregistre les images postées à la fois en retournant sur les tweets d'un utilisateur spécifique sur Twitter".
J'ai essayé de créer un script qui retrace les tweets d'un utilisateur spécifique sur Twitter et enregistre l'image publiée à la fois
J'ai créé une application Twitter qui identifie et enregistre l'image d'un personnage spécifique sur la chronologie de Twitter par pytorch transfer learning
Comment faire un Raspberry Pi qui parle les tweets d'un utilisateur spécifié
J'ai essayé de créer un système qui ne récupère que les tweets supprimés
J'ai essayé de créer un site qui permet de voir facilement les informations mises à jour d'Azure
[Python] J'ai essayé de créer un programme simple qui fonctionne sur la ligne de commande en utilisant argparse
[Twitter] Je veux faire des tweets téléchargés (de mon compte) dans un beau CSV
[Aux messieurs sur Twitter] J'ai écrit un script pour convertir immédiatement .jpg-large en .jpg.
J'ai essayé de vérifier le résultat du test A / B avec le test du chi carré
L'histoire de l'adresse IPv6 que je souhaite conserver au minimum
J'ai essayé de créer un BOT de traduction qui fonctionne avec Discord en utilisant googletrans
J'ai essayé de récupérer les données de l'ordinateur portable en le démarrant sur Ubuntu
Recevez de nombreux tweets Twitter à la fois
J'ai essayé de l'activer / de le désactiver en définissant "Créer un plug-in qui met en évidence les espaces pleine largeur avec Sublime Text 2".
J'ai essayé de faire sonner le téléphone lorsqu'il a été publié sur le poste IoT
Un script qui transfère les tweets contenant des mots-clés spécifiques sur Twitter vers Slack en temps réel.
J'ai essayé de faciliter la modification du paramètre du proxy authentifié sur Jupyter
J'ai créé un outil pour obtenir les liens de réponse d'OpenAI Gym en même temps
Script Python qui va de la recherche Google à l'enregistrement de la page de résultats de recherche à la fois
J'ai essayé de résumer les langues que les débutants devraient désormais apprendre par but
J'ai analysé les tweets sur le nouveau virus corona publiés sur Twitter
[Python] J'ai essayé de visualiser la relation de suivi de Twitter
J'ai essayé de changer le script python de 2.7.11 à 3.6.0 sur Windows10
Publiez le script shell créé pour réduire les problèmes de création de LiveUSB sous Linux
J'ai essayé de classer le nom d'utilisateur et le mot de passe de phpMyAdmin ciblés par l'attaque du serveur
J'ai essayé de créer une configuration RAID logicielle SATA qui démarre le système d'exploitation sur Ubuntu Server
J'ai essayé de créer une expression régulière de "montant" en utilisant Python
J'ai essayé de créer une expression régulière de "temps" en utilisant Python
J'ai essayé de créer une expression régulière de "date" en utilisant Python
J'ai analysé les tweets sur le nouveau virus corona publiés sur Twitter, partie 2
J'ai essayé d'enregistrer une station sur la plateforme IoT "Rimotte"
J'ai essayé de créer un mécanisme de contrôle exclusif avec Go
J'ai découvert en créant un script python pour enregistrer radiko tout en lisant le code des prédécesseurs
Django super introduction par les débutants Python! Partie 2 J'ai essayé d'utiliser les fonctions pratiques du modèle
zoom J'ai essayé de quantifier le degré d'excitation de l'histoire lors de la conférence
J'ai essayé de trouver l'itinéraire optimal du pays des rêves par recuit (quantique)
J'ai essayé de vérifier et d'analyser l'accélération de Python par Cython
J'ai essayé d'afficher la valeur d'altitude du DTM dans un graphique
L'histoire de la création de Botonyan qui renvoie le contenu de Google Docs en réponse à un mot-clé spécifique sur Slack
J'ai essayé de confirmer si l'estimation impartiale de l'écart-type était vraiment impartiale en "jetant des pièces 10 000 fois"
J'ai essayé de réveiller le nom de lieu qui apparaît dans les paroles de Masashi Sada sur la carte thermique