L'auteur a sélectionnéThe Computer History Museum pour recevoir un don dans le cadre du programmeWrite for DOnations.
introduction
Les bots deTwitter sont un moyen puissant de gérer vos médias sociaux et d'extraire des informations du réseau de microblogging. En exploitant les API polyvalentes de Twitter, un bot peut faire beaucoup de choses: tweet, retweet, «favori-tweet», suivre les gens avec certains intérêts, répondre automatiquement, etc. Même si les gens peuvent abuser du pouvoir de leur bot, ce qui crée une expérience négative pour les autres utilisateurs, des recherches ont montré que les gens considèrent les robots Twitter comme une source d’information crédible. Par exemple, un bot peut garder vos abonnés engagés avec du contenu même lorsque vous n'êtes pas en ligne. Certains bots fournissent même des informations critiques et utiles, comme@EarthquakesSF. Les applications pour les robots sont illimitées. À partir de 2019, on estime que les bots représentent environ24% of all tweets sur Twitter.
Dans ce didacticiel, vous allez créer un bot Twitter à l'aide dethis Twitter API library pour Python. Vous utiliserez les clés API de votre compte Twitter pour autoriser votre bot et créer un outil capable de supprimer le contenu de deux sites Web. De plus, vous allez programmer votre bot pour qu’il twitte à tour de rôle le contenu de ces deux sites Web et à des intervalles de temps définis. Notez que vous utiliserez Python 3 dans ce tutoriel.
Conditions préalables
Vous aurez besoin des éléments suivants pour compléter ce didacticiel:
-
Un environnement de programmation Python 3 local configuré en suivantHow To Install and Set Up a Local Programming Environment For Python 3.
-
Installez un éditeur de texte de votre choix, tel queVisual Studio Code,Atom ouSublime Text.
[.note] #Note: Vous allez configurer un compte de développeur avec Twitter, ce qui implique un examen de l'application par Twitter avant de pouvoir accéder aux clés API dont vous avez besoin pour ce bot. L'étape 1 passe en revue les détails spécifiques pour remplir la demande.
#
[[step-1 -—- setup-your-developer-account-and-access-your-twitter-api-keys]] == Étape 1 - Configuration de votre compte de développeur et accès à vos clés API Twitter
Avant de commencer à coder votre bot, vous aurez besoin des clés d’API pour que Twitter reconnaisse les requêtes de votre bot. Au cours de cette étape, vous allez configurer votre compte de développeur Twitter et accéder à vos clés d’API pour votre bot Twitter.
Pour obtenir vos clés API, rendez-vous surdeveloper.twitter.com et enregistrez votre application de bot sur Twitter en cliquant surApply dans la section supérieure droite de la page.
Cliquez maintenant surApply for a developer account.
Ensuite, cliquez surContinue pour associer votre nom d'utilisateur Twitter à votre application de bot que vous allez créer dans ce didacticiel.
Sur la page suivante, pour les besoins de ce didacticiel, vous choisirez l'optionI am requesting access for my own personal use car vous allez créer un robot pour votre propre usage éducatif.
Après avoir choisi vosAccount Name etCountry, passez à la section suivante. PourWhat use case(s) are you interested in?, choisissez les optionsPublish and curate Tweets etStudent project / Learning to code. Ces catégories sont la meilleure représentation de la raison pour laquelle vous suivez ce didacticiel.
Ensuite, décrivez le bot que vous essayez de construire. Twitter en a besoin pour se protéger contre les abus des bot; en 2018, ils ont introduit un tel vetting. Pour ce didacticiel, vous allez extraire du contenu axé sur la technologie à partir deThe New Stack etThe Coursera Blog.
Lorsque vous décidez quoi entrer dans la casedescription, modélisez votre réponse sur les lignes suivantes pour les besoins de ce didacticiel:
Je suis un didacticiel pour créer un robot Twitter qui récupérera le contenu de sites Web comme thenewstack.io (The New Stack) et blog.coursera.org (le blog de Coursera) et en tweetant des citations. Le contenu récupéré sera agrégé et tweeté de manière circulaire via les fonctions du générateur Python.
Enfin, choisissezno pourWill your product, service, or analysis make Twitter content or derived information available to a government entity?
Ensuite, acceptez les conditions générales de Twitter, cliquez surSubmit application, puis vérifiez votre adresse e-mail. Twitter vous enverra un e-mail de vérification après la soumission de ce formulaire.
Une fois que vous aurez vérifié votre adresse e-mail, vous obtiendrez une pageApplication under review avec un formulaire de commentaires pour le processus de candidature.
Vous recevrez également un autre email de Twitter concernant l'examen:
Le calendrier du processus d’examen des applications de Twitter peut varier considérablement, mais Twitter le confirmera souvent en quelques minutes. Toutefois, si l’examen de votre demande prend plus de temps, cela n’est pas inhabituel et vous devriez le recevoir dans un jour ou deux. Une fois la confirmation reçue, Twitter vous a autorisé à générer vos clés. Vous pouvez y accéder sous l'ongletKeys and tokens après avoir cliqué sur le bouton Détails de votre application surdeveloper.twitter.com/apps.
Enfin, accédez à l'ongletPermissions sur la page de votre application et définissez l'optionAccess Permission surRead and Write puisque vous souhaitez également écrire du contenu de tweet. Habituellement, vous utiliseriez le mode lecture seule à des fins de recherche, telles que l'analyse des tendances, l'exploration de données, etc. La dernière option permet aux utilisateurs d'intégrer les chatbots dans leurs applications existantes, car les chatbots nécessitent un accès aux messages directs.
Vous avez accès à la puissante API de Twitter, qui constituera un élément crucial de votre application bot. Vous allez maintenant configurer votre environnement et commencer à construire votre bot.
[[step-2 -—- building-the-essentials]] == Step 2 - Building the Essentials
Au cours de cette étape, vous écrirez du code pour authentifier votre bot avec Twitter à l’aide des clés de l’API, et ferez le premier tweet programmatique via votre pseudo Twitter. Cela constituera une bonne étape dans votre chemin vers l'objectif de créer un robot Twitter qui récupère le contenu deThe New Stack et desCoursera Blog et les tweete périodiquement.
Tout d’abord, vous allez configurer un dossier de projet et un environnement de programmation spécifique pour votre projet.
Créez votre dossier de projet:
mkdir bird
Déplacez-vous dans votre dossier de projet:
cd bird
Créez ensuite un nouvel environnement virtuel Python pour votre projet:
python3 -m venv bird-env
Activez ensuite votre environnement en utilisant la commande suivante:
source bird-env/bin/activate
Cela attachera un préfixe(bird-env)
à l'invite dans la fenêtre de votre terminal.
Maintenant, passez à votre éditeur de texte et créez un fichier appelécredentials.py
, qui stockera vos clés API Twitter:
nano credentials.py
Ajoutez le contenu suivant en remplaçant le code en surbrillance par vos clés Twitter:
bird/credentials.py
ACCESS_TOKEN='your-access-token'
ACCESS_SECRET='your-access-secret'
CONSUMER_KEY='your-consumer-key'
CONSUMER_SECRET='your-consumer-secret'
Vous allez maintenant installer la bibliothèque principale d’API pour l’envoi de demandes à Twitter. Pour ce projet, vous aurez besoin des bibliothèques suivantes:nltk
,requests
,twitter
,lxml
,random
ettime
. random
ettime
font partie de la bibliothèque standard de Python, vous n'avez donc pas besoin d'installer ces bibliothèques séparément. Pour installer les bibliothèques restantes, vous utiliserezpip, un gestionnaire de packages pour Python.
Ouvrez votre terminal, assurez-vous que vous vous trouvez dans le dossier du projet et exécutez la commande suivante:
pip3 install lxml nltk requests twitter
-
lxml
etrequests
: vous les utiliserez pour le web scraping. -
twitter
: il s'agit de la bibliothèque pour passer des appels API aux serveurs de Twitter. -
nltk
: (boîte à outils en langage naturel) Vous utiliserez pour diviser les paragraphes de blogs en phrases. -
random
: Vous l'utiliserez pour sélectionner au hasard des parties d'un article de blog entièrement récupéré. -
time
: Vous utiliserez pour faire dormir votre bot périodiquement après certaines actions.
Une fois les bibliothèques installées, vous êtes prêt à commencer la programmation. Vous allez maintenant importer vos informations d’identité dans le script principal qui exécutera le bot. Parallèlement àcredentials.py
, à partir de votre éditeur de texte, créez un fichier dans le répertoire du projetbird
et nommez-lebot.py
:
nano bot.py
En pratique, vous répartiriez les fonctionnalités de votre bot sur plusieurs fichiers à mesure qu’il deviendrait de plus en plus sophistiqué. Cependant, dans ce didacticiel, vous mettrez tout votre code dans un seul script,bot.py
, à des fins de démonstration.
Vous allez d’abord tester vos clés d’API en autorisant votre bot. Commencez par ajouter l'extrait de code suivant àbot.py
:
bird/bot.py
import random
import time
from lxml.html import fromstring
import nltk
nltk.download('punkt')
import requests
from twitter import OAuth, Twitter
import credentials
Ici, vous importez les bibliothèques requises; et dans quelques cas, vous importez lesfunctions nécessaires à partir des bibliothèques. Vous utiliserez la fonctionfromstring
plus tard dans le code pour convertir la source de chaîne d'une page Web grattée en une structure arborescente qui facilite l'extraction des informations pertinentes de la page. OAuth
vous aidera à construire un objet d'authentification à partir de vos clés, etTwitter
construira l'objet API principal pour toute communication ultérieure avec les serveurs de Twitter.
Maintenant, étendezbot.py
avec les lignes suivantes:
bird/bot.py
...
tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')
oauth = OAuth(
credentials.ACCESS_TOKEN,
credentials.ACCESS_SECRET,
credentials.CONSUMER_KEY,
credentials.CONSUMER_SECRET
)
t = Twitter(auth=oauth)
nltk.download('punkt')
télécharge un ensemble de données nécessaire pour analyser les paragraphes et les segmenter (diviser) en composants plus petits. tokenizer
est l’objet que vous utiliserez plus tard dans le code pour diviser les paragraphes écrits en anglais.
oauth
est l'objet d'authentification construit en alimentant la classeOAuth
importée avec vos clés API. Vous authentifiez votre bot via la lignet = Twitter(auth=oauth)
. ACCESS_TOKEN
etACCESS_SECRET
aident à reconnaître votre application. Enfin,CONSUMER_KEY
etCONSUMER_SECRET
aident à reconnaître le handle via lequel l'application interagit avec Twitter. Vous utiliserez cet objett
pour communiquer vos demandes à Twitter.
Enregistrez maintenant ce fichier et exécutez-le dans votre terminal à l'aide de la commande suivante:
python3 bot.py
Votre sortie ressemblera à ce qui suit, ce qui signifie que votre autorisation a réussi:
Output[nltk_data] Downloading package punkt to /Users/binaryboy/nltk_data...
[nltk_data] Package punkt is already up-to-date!
Si vous recevez une erreur, vérifiez vos clés API enregistrées avec celles de vosTwitter developer account et réessayez. Assurez-vous également que les bibliothèques requises sont correctement installées. Sinon, utilisez à nouveaupip3
pour les installer.
Maintenant, vous pouvez essayer de tweeter quelque chose par programme. Tapez la même commande sur le terminal avec l'indicateur-i
pour ouvrir l'interpréteur Python après l'exécution de votre script:
python3 -i bot.py
Ensuite, tapez ce qui suit pour envoyer un tweet via votre compte:
t.statuses.update(status="Just setting up my Twttr bot")
Ouvrez maintenant votre timeline Twitter dans un navigateur et vous verrez un tweet en haut de votre timeline contenant le contenu que vous avez posté.
Fermez l'interpréteur en tapantquit()
ouCTRL + D
.
Votre bot a maintenant la capacité fondamentale de tweeter. Pour que votre bot puisse utiliser du contenu utile sur Twitter, vous allez incorporer le scraping Web à l’étape suivante.
[[step-3 -—- scraping-website-for-your-tweet-content]] == Étape 3 - Récupération de sites Web pour le contenu de votre Tweet
Pour introduire du contenu plus intéressant dans votre chronologie, vous allez extraire le contenu dethe New Stack et desCoursera Blog, puis publier ce contenu sur Twitter sous forme de tweets. Généralement, pour extraire les données appropriées de vos sites Web cibles, vous devez expérimenter leur structure HTML. Chaque tweet provenant du bot que vous allez construire dans ce tutoriel aura un lien vers un article de blog des sites Web choisis, avec une citation aléatoire de ce blog. Vous implémenterez cette procédure dans une fonction spécifique à la récupération de contenu de Coursera, vous la nommerez doncscrape_coursera()
.
Première ouverturebot.py
:
nano bot.py
Ajoutez la fonctionscrape_coursera()
à la fin de votre fichier:
bird/bot.py
...
t = Twitter(auth=oauth)
def scrape_coursera():
Pour extraire des informations du blog, vous devez d’abord demander la page Web correspondante aux serveurs de Coursera. Pour cela, vous utiliserez la fonctionget()
de la bibliothèquerequests
. get()
prend une URL et récupère la page Web correspondante. Donc, vous passerezblog.coursera.org
comme argument àget()
. Cependant, vous devez également fournir un en-tête dans votre demande GET, ce qui garantira que les serveurs de Coursera vous reconnaissent comme un véritable client. Ajoutez les lignes en surbrillance suivantes à votre fonctionscrape_coursera()
pour fournir un en-tête:
bird/bot.py
def scrape_coursera():
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5)'
' AppleWebKit/537.36 (KHTML, like Gecko) Cafari/537.36'
}
Cet en-tête contiendra des informations relatives à un navigateur Web défini s'exécutant sur un système d'exploitation spécifique. Tant que ces informations (généralement appeléesUser-Agent
) correspondent à de vrais navigateurs Web et systèmes d'exploitation, peu importe si les informations d'en-tête correspondent au navigateur Web et au système d'exploitation réels de votre ordinateur. Par conséquent, cet en-tête fonctionnera correctement pour tous les systèmes.
Une fois que vous avez défini les en-têtes, ajoutez les lignes suivantes en surbrillance pour envoyer une demande GET à Coursera en spécifiant l'URL de la page Web du blog:
bird/bot.py
...
def scrape_coursera():
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5)'
' AppleWebKit/537.36 (KHTML, like Gecko) Cafari/537.36'
}
r = requests.get('https://blog.coursera.org', headers=HEADERS)
tree = fromstring(r.content)
Cela récupérera la page Web sur votre machine et enregistrera les informations de la page Web entière dans la variabler
. Vous pouvez évaluer le code source HTML de la page Web à l'aide de l'attributcontent
der
. Par conséquent, la valeur der.content
est la même que celle que vous voyez lorsque vous inspectez la page Web dans votre navigateur en faisant un clic droit sur la page et en choisissant l'optionInspect Element.
Ici, vous avez également ajouté la fonctionfromstring
. Vous pouvez transmettre le code source de la page Web à la fonctionfromstring
importée de la bibliothèquelxml
pour construire la structuretree
de la page Web. Cette structure detreevous permettra d'accéder facilement à différentes parties de la page Web. Le code source HTML a une structure arborescente particulière; chaque élément est inclus dans la balise<html>
et imbriqué par la suite.
Maintenant, ouvrezhttps://blog.coursera.org
dans un navigateur et inspectez sa source HTML à l'aide des outils de développement du navigateur. Faites un clic droit sur la page et choisissez l'optionInspect Element. Une fenêtre apparaît au bas du navigateur et affiche une partie du code source HTML de la page.
Ensuite, cliquez avec le bouton droit sur la vignette de tout article de blog visible, puis inspectez-la. La source HTML mettra en évidence les lignes HTML pertinentes où la vignette de ce blog est définie. Vous remarquerez que tous les articles de blog sur cette page sont définis dans une balise<div>
avec unclass de"recent"
:
Ainsi, dans votre code, vous utiliserez tous les éléments de ces articles de blogdiv
via leursXPath, ce qui est un moyen pratique d'adresser les éléments d'une page Web.
Pour ce faire, étendez votre fonction enbot.py
comme suit:
bird/bot.py
...
def scrape_coursera():
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5)'
' AppleWebKit/537.36 (KHTML, like Gecko) Cafari/537.36'
}
r = requests.get('https://blog.coursera.org', headers=HEADERS)
tree = fromstring(r.content)
links = tree.xpath('//div[@class="recent"]//div[@class="title"]/a/@href')
print(links)
scrape_coursera()
Ici, leXPath (la chaîne passée àtree.xpath()
) indique que vous voulez des élémentsdiv
de toute la source de la page Web, declass"recent"
. Le//
correspond à la recherche sur toute la page Web,div
dit à la fonction d'extraire uniquement les élémentsdiv
, et[@class="recent"]
lui demande d'extraire uniquement ces élémentsdiv
qui ont les valeurs de leur attributclass
comme"recent"
.
Cependant, vous n’avez pas besoin de ces éléments eux-mêmes, vous avez seulement besoin des liens qu’ils pointent, pour pouvoir accéder aux articles de blog individuels afin d’en extraire le contenu. Par conséquent, vous extrayez tous les liens en utilisant les valeurs des balises d'ancragehref
qui se trouvent dans les balisesdiv
précédentes des articles de blog.
Pour tester votre programme jusqu'à présent, vous appelez la fonctionscrape_coursera()
à la fin debot.py
.
Enregistrez et quittezbot.py
.
Maintenant, exécutezbot.py
avec la commande suivante:
python3 bot.py
Dans votre sortie, vous verrez unlist d'URL comme suit:
Output['https://blog.coursera.org/career-stories-from-inside-coursera/', 'https://blog.coursera.org/unlock-the-power-of-data-with-python-university-of-michigan-offers-new-programming-specializations-on-coursera/', ...]
Après avoir vérifié la sortie, vous pouvez supprimer les deux dernières lignes en surbrillance du scriptbot.py
:
bird/bot.py
...
def scrape_coursera():
...
tree = fromstring(r.content)
links = tree.xpath('//div[@class="recent"]//div[@class="title"]/a/@href')
~~print(links)~~
~~scrape_coursera()~~
Maintenant, étendez la fonction enbot.py
avec la ligne en surbrillance suivante pour extraire le contenu d'un article de blog:
bird/bot.py
...
def scrape_coursera():
...
links = tree.xpath('//div[@class="recent"]//div[@class="title"]/a/@href')
for link in links:
r = requests.get(link, headers=HEADERS)
blog_tree = fromstring(r.content)
Vous parcourez chaque lien, récupérez le billet de blog correspondant, extrayez une phrase aléatoire du message, puis tweetez cette phrase sous forme de citation, ainsi que l'URL correspondante. Extraire une phrase aléatoire comporte trois parties:
-
Saisir tous les paragraphes de l'article du blog sous forme de liste.
-
Sélectionner un paragraphe au hasard dans la liste des paragraphes.
-
Sélection d'une phrase au hasard dans ce paragraphe.
Vous exécuterez ces étapes pour chaque article de blog. Pour en récupérer un, vous faites une demande GET pour son lien.
Maintenant que vous avez accès au contenu d'un blog, vous allez introduire le code qui exécute ces trois étapes pour en extraire le contenu souhaité. Ajoutez l’extension suivante à votre fonction de grattage qui exécute les trois étapes:
bird/bot.py
...
def scrape_coursera():
...
for link in links:
r = requests.get(link, headers=HEADERS)
blog_tree = fromstring(r.content)
paras = blog_tree.xpath('//div[@class="entry-content"]/p')
paras_text = [para.text_content() for para in paras if para.text_content()]
para = random.choice(paras_text)
para_tokenized = tokenizer.tokenize(para)
for _ in range(10):
text = random.choice(para_tokenized)
if text and 60 < len(text) < 210:
break
Si vous inspectez le billet de blog en ouvrant le premier lien, vous remarquerez que tous les paragraphes appartiennent à la balisediv
ayantentry-content
comme classe. Par conséquent, vous extrayez tous les paragraphes sous forme de liste avecparas = blog_tree.xpath('//div[@class="entry-content"]/p')
.
Les éléments de la liste ne sont pas des paragraphesliteral; ce sontElement
objects. Pour extraire le texte de cesobjects, vous utilisez la méthodetext_content()
. Cette ligne suit le modèle de conception de Pythonlist comprehension, qui définit une collection en utilisant une boucle qui est généralement écrite sur une seule ligne. Dansbot.py
, vous extrayez le texte de chaque élément de paragrapheobject et le stockez dans unlist si le texte n'est pas vide. Pour choisir au hasard un paragraphe dans cette liste de paragraphes, vous incorporez le modulerandom
.
Enfin, vous devez sélectionner une phrase au hasard dans ce paragraphe, qui est stockée dans la variablepara
. Pour cette tâche, vous divisez d’abord le paragraphe en phrases. Une approche pour y parvenir consiste à utiliser la méthodesplit()
de Python. Cependant, cela peut être difficile car une phrase peut être fractionnée à plusieurs points d'arrêt. Par conséquent, pour simplifier vos tâches de fractionnement, vous tirez parti du traitement du langage naturel via la bibliothèquenltk
. L'objettokenizer
que vous avez défini précédemment dans le didacticiel sera utile à cette fin.
Maintenant que vous avez une liste de phrases, vous appelezrandom.choice()
pour extraire une phrase aléatoire. Vous voulez que cette phrase soit une citation pour un tweet, de sorte qu'elle ne puisse pas dépasser 280 caractères. Toutefois, pour des raisons esthétiques, vous sélectionnerez une phrase ni trop grande ni trop petite. Vous indiquez que votre phrase sur Twitter doit comporter entre 60 et 210 caractères. Les sélections de phraserandom.choice()
peuvent ne pas satisfaire ce critère. Pour identifier la phrase correcte, votre script effectuera dix tentatives en vérifiant le critère à chaque fois. Une fois que la phrase choisie au hasard satisfait à votre critère, vous pouvez sortir de la boucle.
Bien que la probabilité soit assez faible, il est possible qu'aucune des phrases ne remplisse cette condition de taille en moins de dix tentatives. Dans ce cas, vous ignorerez la publication de blog correspondante et passerez à la suivante.
Maintenant que vous avez une phrase à citer, vous pouvez la tweeter avec le lien correspondant. Vous pouvez le faire en générant une chaîne contenant la phrase choisie de manière aléatoire ainsi que le lien de blog correspondant. Le code qui appelle cette fonctionscrape_coursera()
publiera ensuite la chaîne produite sur Twitter via l'API de Twitter.
Étendez votre fonction comme suit:
bird/bot.py
...
def scrape_coursera():
...
for link in links:
...
para_tokenized = tokenizer.tokenize(para)
for _ in range(10):
text = random.choice(para)
if text and 60 < len(text) < 210:
break
else:
yield None
yield '"%s" %s' % (text, link)
Le script n'exécute l'instructionelse
que lorsque la bouclefor
précédente ne s'arrête pas. Ainsi, cela ne se produit que lorsque la boucle ne parvient pas à trouver une phrase correspondant à votre taille. Dans ce cas, vous cédez simplementNone
pour que le code qui appelle cette fonction puisse déterminer qu'il n'y a rien à tweeter. Ensuite, il appellera de nouveau la fonction et récupérera le contenu du prochain lien de blog. Mais si la boucle se rompt, cela signifie que la fonction a trouvé une phrase appropriée; le script n'exécutera pas l'instructionelse
, et la fonction produira une chaîne composée de la phrase ainsi que du lien du blog, séparés par un seulwhitespace.
L'implémentation de la fonctionscrape_coursera()
est presque terminée. Si vous souhaitez créer une fonction similaire pour supprimer un autre site Web, vous devrez répéter une partie du code que vous avez écrit pour supprimer le blog de Coursera. Pour éviter de réécrire et de dupliquer des parties du code et pour vous assurer que le script de votre bot suit le principeDRY (Don't Repeat Yourself), vous identifierez et extrayerez des parties du code que vous utiliserez encore et encore pour toute fonction de racleur écrite plus tard.
Quel que soit le site Web que la fonction est en train de supprimer, vous devrez choisir un paragraphe au hasard, puis choisir une phrase aléatoire dans ce paragraphe choisi - vous pouvez extraire ces fonctionnalités dans des fonctions distinctes. Ensuite, vous pouvez simplement appeler ces fonctions à partir des fonctions de votre grattoir et obtenir le résultat souhaité. Vous pouvez également définirHEADERS
en dehors de la fonctionscrape_coursera()
afin que toutes les fonctions de racleur puissent l'utiliser. Par conséquent, dans le code qui suit, la définition deHEADERS
doit précéder celle de la fonction de racleur, afin que vous puissiez éventuellement l'utiliser pour d'autres scrapers:
bird/bot.py
...
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5)'
' AppleWebKit/537.36 (KHTML, like Gecko) Cafari/537.36'
}
def scrape_coursera():
r = requests.get('https://blog.coursera.org', headers=HEADERS)
...
Vous pouvez maintenant définir la fonctionextract_paratext()
pour extraire un paragraphe aléatoire d'une liste d'objets paragraphe. Le paragraphe aléatoire passera à la fonction en tant qu'argumentparas
et renverra la forme symbolique du paragraphe choisi que vous utiliserez plus tard pour l'extraction de phrases:
bird/bot.py
...
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5)'
' AppleWebKit/537.36 (KHTML, like Gecko) Cafari/537.36'
}
def extract_paratext(paras):
"""Extracts text from elements and returns a clean, tokenized random
paragraph."""
paras = [para.text_content() for para in paras if para.text_content()]
para = random.choice(paras)
return tokenizer.tokenize(para)
def scrape_coursera():
r = requests.get('https://blog.coursera.org', headers=HEADERS)
...
Ensuite, vous définirez une fonction qui extraira une phrase aléatoire de longueur appropriée (entre 60 et 210 caractères) du paragraphe tokenisé qu'elle reçoit en argument, que vous pouvez nommer enpara
. Si une telle phrase n'est pas découverte après dix tentatives, la fonction renvoie à la placeNone
. Ajoutez le code en surbrillance suivant pour définir la fonctionextract_text()
:
bird/bot.py
...
def extract_paratext(paras):
...
return tokenizer.tokenize(para)
def extract_text(para):
"""Returns a sufficiently-large random text from a tokenized paragraph,
if such text exists. Otherwise, returns None."""
for _ in range(10):
text = random.choice(para)
if text and 60 < len(text) < 210:
return text
return None
def scrape_coursera():
r = requests.get('https://blog.coursera.org', headers=HEADERS)
...
Une fois que vous avez défini ces nouvelles fonctions d'assistance, vous pouvez redéfinir la fonctionscrape_coursera()
pour qu'elle ressemble à ceci:
bird/bot.py
...
def extract_paratext():
for _ in range(10):<^>
text = random.choice(para)
...
def scrape_coursera():
"""Scrapes content from the Coursera blog."""
url = 'https://blog.coursera.org'
r = requests.get(url, headers=HEADERS)
tree = fromstring(r.content)
links = tree.xpath('//div[@class="recent"]//div[@class="title"]/a/@href')
for link in links:
r = requests.get(link, headers=HEADERS)
blog_tree = fromstring(r.content)
paras = blog_tree.xpath('//div[@class="entry-content"]/p')
para = extract_paratext(paras)
text = extract_text(para)
if not text:
continue
yield '"%s" %s' % (text, link)
Enregistrez et quittezbot.py
.
Ici, vous utilisezyield
au lieu dereturn
car, pour parcourir les liens, la fonction de raclage vous donnera les chaînes de tweet une par une de manière séquentielle. Cela signifie que lorsque vous effectuez un premier appel au scrapersc
défini commesc = scrape_coursera()
, vous obtiendrez la chaîne de tweet correspondant au premier lien parmi la liste de liens que vous avez calculée dans la fonction scraper. Si vous exécutez le code suivant dans l'interpréteur, vous obtiendrezstring_1
etstring_2
comme indiqué ci-dessous, si la variablelinks
dansscrape_coursera()
contient une liste qui ressemble à["https://thenewstack.io/cloud-native-live-twistlocks-virtual-conference/", "https://blog.coursera.org/unlock-the-power-of-data-with-python-university-of-michigan-offers-new-programming-specializations-on-coursera/", ...]
.
python3 -i bot.py
Instanciez le grattoir et appelez-lesc
:
>>> sc = scrape_coursera()
C'est maintenant un générateur; il génère ou gratte un contenu pertinent de Coursera, un à la fois. Vous pouvez accéder au contenu récupéré un par un en appelant de manière séquentiellenext()
sursc
:
>>> string_1 = next(sc)
>>> string_2 = next(sc)
Vous pouvez maintenantprint
les chaînes que vous avez définies pour afficher le contenu récupéré:
>>> print(string_1)
"Other speakers include Priyanka Sharma, director of cloud native alliances at GitLab and Dan Kohn, executive director of the Cloud Native Computing Foundation." https://thenewstack.io/cloud-native-live-twistlocks-virtual-conference/
>>>
>>> print(string_2)
"You can learn how to use the power of Python for data analysis with a series of courses covering fundamental theory and project-based learning." https://blog.coursera.org/unlock-the-power-of-data-with-python-university-of-michigan-offers-new-programming-specializations-on-coursera/
>>>
Si vous utilisez à la placereturn
, vous ne pourrez pas obtenir les chaînes une par une et dans une séquence. Si vous remplacez simplement lesyield
parreturn
dansscrape_coursera()
, vous obtiendrez toujours la chaîne correspondant au premier article de blog, au lieu d'obtenir le premier dans le premier appel, le deuxième dans le deuxième appel, et ainsi de suite. Vous pouvez modifier la fonction pour renvoyer simplement unlist de toutes les chaînes correspondant à tous les liens, mais cela demande plus de mémoire. En outre, ce type de programme pourrait potentiellement faire beaucoup de requêtes aux serveurs de Coursera dans un court laps de temps si vous voulez que leslistentiers soient rapidement. Cela pourrait empêcher votre bot d'accéder temporairement à un site Web. Par conséquent,yield
est la meilleure solution pour une grande variété de travaux de grattage, où vous n'avez besoin que des informations grattées une à la fois.
[[step-4 -—- scraping-additional-content]] == Étape 4 - Scraping Additional Content
Dans cette étape, vous allez créer un grattoir pourthenewstack.io. Le processus est similaire à celui que vous avez effectué à l’étape précédente. Ce sera donc un aperçu rapide.
Ouvrez le site Web dans votre navigateur et inspectez la source de la page. Vous trouverez ici que toutes les sections de blog sont des élémentsdiv
de la classenormalstory-box
.
Vous allez maintenant créer une nouvelle fonction de récupération nomméescrape_thenewstack()
et faire une requête GET àthenewstack.io à partir de celle-ci. Ensuite, extrayez les liens vers les blogs à partir de ces éléments, puis parcourez chaque lien. Ajoutez le code suivant pour y parvenir:
bird/bot.py
...
def scrape_coursera():
...
yield '"%s" %s' % (text, link)
def scrape_thenewstack():
"""Scrapes news from thenewstack.io"""
r = requests.get('https://thenewstack.io', verify=False)
tree = fromstring(r.content)
links = tree.xpath('//div[@class="normalstory-box"]/header/h2/a/@href')
for link in links:
Vous utilisez l'indicateurverify=False
car les sites Web peuvent parfois avoir des certificats de sécurité expirés et vous pouvez y accéder si aucune donnée sensible n'est impliquée, comme c'est le cas ici. L'indicateurverify=False
indique à la méthoderequests.get
de ne pas vérifier les certificats et de continuer à récupérer les données comme d'habitude. Sinon, la méthode renvoie une erreur à propos des certificats de sécurité expirés.
Vous pouvez maintenant extraire les paragraphes du blog correspondant à chaque lien et utiliser la fonctionextract_paratext()
que vous avez créée à l'étape précédente pour extraire un paragraphe aléatoire de la liste des paragraphes disponibles. Enfin, extrayez une phrase aléatoire de ce paragraphe en utilisant la fonctionextract_text()
, puisyield
avec le lien de blog correspondant. Ajoutez le code en surbrillance suivant à votre fichier pour accomplir ces tâches:
bird/bot.py
...
def scrape_thenewstack():
...
links = tree.xpath('//div[@class="normalstory-box"]/header/h2/a/@href')
for link in links:
r = requests.get(link, verify=False)
tree = fromstring(r.content)
paras = tree.xpath('//div[@class="post-content"]/p')
para = extract_paratext(paras)
text = extract_text(para)
if not text:
continue
yield '"%s" %s' % (text, link)
Vous avez maintenant une idée de ce qu'un processus de grattage englobe généralement. Vous pouvez maintenant créer vos propres grattoirs personnalisés qui peuvent, par exemple, gratter les images dans des articles de blog au lieu de citations aléatoires. Pour cela, vous pouvez rechercher les balises<img>
pertinentes. Une fois que vous avez le bon chemin pour les balises, qui servent d’identificateurs, vous pouvez accéder aux informations contenues dans les balises en utilisant le nom des attributs correspondants. Par exemple, dans le cas du scraping d'images, vous pouvez accéder aux liens des images en utilisant leurs attributssrc
.
À ce stade, vous avez créé deux fonctions de grattoir pour extraire le contenu de deux sites Web différents. Vous avez également créé deux fonctions auxiliaires pour réutiliser des fonctionnalités communes aux deux grattoirs. Maintenant que votre bot sait comment tweeter et quoi tweeter, vous écrirez le code pour tweeter le contenu récupéré.
[[step-5 -—- tweeting-the-scraped-content]] == Étape 5 - Tweeting the scraped content
Dans cette étape, vous allez étendre le bot pour extraire le contenu des deux sites Web et le tweeter via votre compte Twitter. Plus précisément, vous souhaitez tweeter le contenu des deux sites Web alternativement, et à intervalles réguliers de dix minutes, pendant une durée indéterminée. Ainsi, vous utiliserez uninfinite while loop pour implémenter la fonctionnalité souhaitée. Vous ferez cela dans le cadre d'une fonctionmain()
, qui implémentera le processus principal de haut niveau que vous voudrez que votre bot suive:
bird/bot.py
...
def scrape_thenewstack():
...
yield '"%s" %s' % (text, link)
def main():
"""Encompasses the main loop of the bot."""
print('---Bot started---\n')
news_funcs = ['scrape_coursera', 'scrape_thenewstack']
news_iterators = []
for func in news_funcs:
news_iterators.append(globals()[func]())
while True:
for i, iterator in enumerate(news_iterators):
try:
tweet = next(iterator)
t.statuses.update(status=tweet)
print(tweet, end='\n\n')
time.sleep(600)
except StopIteration:
news_iterators[i] = globals()[newsfuncs[i]]()
Vous créez d'abord une liste des noms des fonctions de scraping que vous avez définies précédemment et vous l'appelez en tant quenews_funcs
. Ensuite, vous créez une liste vide qui contiendra les fonctions de scraper réelles, et nommez cette liste commenews_iterators
. Vous le remplissez ensuite en parcourant chaque nom de la listenews_funcs
et en ajoutant l'itérateur correspondant dans la listenews_iterators
. Vous utilisez la fonctionglobals()
intégrée de Python. Cela renvoie un dictionnaire qui mappe les noms de variables aux variables réelles dans votre script. Un itérateur est ce que vous obtenez lorsque vous appelez une fonction de grattoir: par exemple, si vous écrivezcoursera_iterator = scrape_coursera()
, alorscoursera_iterator
sera un itérateur sur lequel vous pourrez appeler les appels denext()
. Chaque appel denext()
renverra une chaîne contenant un guillemet et son lien correspondant, exactement comme défini dans l'instructionyield
de la fonctionscrape_coursera()
. Chaque appel denext()
passe par une itération de la bouclefor
dans la fonctionscrape_coursera()
. Ainsi, vous ne pouvez faire autant d'appels ànext()
qu'il y a de liens de blog dans la fonctionscrape_coursera()
. Une fois que ce nombre dépasse, une exceptionStopIteration
sera déclenchée.
Une fois que les deux itérateurs remplissent la listenews_iterators
, la boucle principalewhile
démarre. À l'intérieur, vous avez une bouclefor
qui traverse chaque itérateur et tente d'obtenir le contenu à tweeter. Après avoir obtenu le contenu, votre bot le tweete puis dort pendant dix minutes. Si l'itérateur n'a plus de contenu à offrir, une exceptionStopIteration
est déclenchée, sur laquelle vous actualisez cet itérateur en le ré-instanciant, pour vérifier la disponibilité de contenu plus récent sur le site Web source. Ensuite, vous passez au prochain itérateur, s'il est disponible. Sinon, si l'exécution atteint la fin de la liste des itérateurs, vous redémarrez depuis le début et tweetez le prochain contenu disponible. Cela permet à votre bot de tweeter le contenu alternativement des deux grattoirs aussi longtemps que vous le souhaitez.
Il ne reste plus qu'à faire un appel à la fonctionmain()
. Vous faites cela lorsque le script est appelédirectly par l'interpréteur Python:
bird/bot.py
...
def main():
print('---Bot started---\n')<^>
news_funcs = ['scrape_coursera', 'scrape_thenewstack']
...
if __name__ == "__main__":
main()
Voici une version complète du scriptbot.py
. Vous pouvez également afficherthe script on this GitHub repository.
bird/bot.py
"""Main bot script - bot.py
For the DigitalOcean Tutorial.
"""
import random
import time
from lxml.html import fromstring
import nltk
nltk.download('punkt')
import requests
from twitter import OAuth, Twitter
import credentials
tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')
oauth = OAuth(
credentials.ACCESS_TOKEN,
credentials.ACCESS_SECRET,
credentials.CONSUMER_KEY,
credentials.CONSUMER_SECRET
)
t = Twitter(auth=oauth)
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5)'
' AppleWebKit/537.36 (KHTML, like Gecko) Cafari/537.36'
}
def extract_paratext(paras):
"""Extracts text from elements and returns a clean, tokenized random
paragraph."""
paras = [para.text_content() for para in paras if para.text_content()]
para = random.choice(paras)
return tokenizer.tokenize(para)
def extract_text(para):
"""Returns a sufficiently-large random text from a tokenized paragraph,
if such text exists. Otherwise, returns None."""
for _ in range(10):
text = random.choice(para)
if text and 60 < len(text) < 210:
return text
return None
def scrape_coursera():
"""Scrapes content from the Coursera blog."""
url = 'https://blog.coursera.org'
r = requests.get(url, headers=HEADERS)
tree = fromstring(r.content)
links = tree.xpath('//div[@class="recent"]//div[@class="title"]/a/@href')
for link in links:
r = requests.get(link, headers=HEADERS)
blog_tree = fromstring(r.content)
paras = blog_tree.xpath('//div[@class="entry-content"]/p')
para = extract_paratext(paras)
text = extract_text(para)
if not text:
continue
yield '"%s" %s' % (text, link)
def scrape_thenewstack():
"""Scrapes news from thenewstack.io"""
r = requests.get('https://thenewstack.io', verify=False)
tree = fromstring(r.content)
links = tree.xpath('//div[@class="normalstory-box"]/header/h2/a/@href')
for link in links:
r = requests.get(link, verify=False)
tree = fromstring(r.content)
paras = tree.xpath('//div[@class="post-content"]/p')
para = extract_paratext(paras)
text = extract_text(para)
if not text:
continue
yield '"%s" %s' % (text, link)
def main():
"""Encompasses the main loop of the bot."""
print('Bot started.')
news_funcs = ['scrape_coursera', 'scrape_thenewstack']
news_iterators = []
for func in news_funcs:
news_iterators.append(globals()[func]())
while True:
for i, iterator in enumerate(news_iterators):
try:
tweet = next(iterator)
t.statuses.update(status=tweet)
print(tweet, end='\n')
time.sleep(600)
except StopIteration:
news_iterators[i] = globals()[newsfuncs[i]]()
if __name__ == "__main__":
main()
Enregistrez et quittezbot.py
.
Voici un exemple d'exécution debot.py
:
python3 bot.py
Vous recevrez une sortie indiquant le contenu que votre bot a supprimé, dans un format similaire à celui-ci:
Output[nltk_data] Downloading package punkt to /Users/binaryboy/nltk_data...
[nltk_data] Package punkt is already up-to-date!
---Bot started---
"Take the first step toward your career goals by building new skills." https://blog.coursera.org/career-stories-from-inside-coursera/
"Other speakers include Priyanka Sharma, director of cloud native alliances at GitLab and Dan Kohn, executive director of the Cloud Native Computing Foundation." https://thenewstack.io/cloud-native-live-twistlocks-virtual-conference/
"You can learn how to use the power of Python for data analysis with a series of courses covering fundamental theory and project-based learning." https://blog.coursera.org/unlock-the-power-of-data-with-python-university-of-michigan-offers-new-programming-specializations-on-coursera/
"“Real-user monitoring is really about trying to understand the underlying reasons, so you know, ‘who do I actually want to fly with?" https://thenewstack.io/how-raygun-co-founder-and-ceo-spun-gold-out-of-monitoring-agony/
Après un exemple d’exécution de votre bot, vous verrez une chronologie complète des tweets programmés publiés par votre bot sur votre page Twitter. Cela ressemblera à ceci:
Comme vous pouvez le constater, le bot twitte les liens de blogs supprimés avec des citations aléatoires de chaque blog comme faits saillants. Ce flux est maintenant un flux d'informations avec des tweets alternant entre des citations de blogs de Coursera et thenewstack.io. Vous avez créé un bot qui agrège le contenu du Web et le publie sur Twitter. Vous pouvez maintenant élargir le champ d'application de ce bot selon vos souhaits en ajoutant plus de scrapeurs pour différents sites Web. Le bot tweetera le contenu provenant de tous les scrapeurs à la va-vite, dans les intervalles de temps souhaités.
Conclusion
Dans ce didacticiel, vous avez créé un bot Twitter de base avec Python et récupéré du contenu du Web pour que votre bot puisse tweeter. Il y a beaucoup d'idées de bots à essayer; vous pouvez également implémenter vos propres idées pour l’utilité d’un bot. Vous pouvez combiner les fonctionnalités polyvalentes offertes par l’API de Twitter et créer quelque chose de plus complexe. Pour une version d'un bot Twitter plus sophistiqué, consultezchirps, un framework de bot Twitter qui utilise des concepts avancés comme le multithreading pour que le bot fasse plusieurs choses simultanément. Il existe également des robots à idées amusantes, commemisheardly. Il n’ya pas de limites à la créativité que l’on peut utiliser pour créer des robots Twitter. Il est essentiel de trouver les points de terminaison d’API appropriés pour la mise en œuvre de votre bot.
Enfin, il est important de garder à l’esprit l’étiquette de bot ou «botiquette» lors de la construction de votre prochain bot. Par exemple, si votre bot intègre le retweet, faites passer le texte de tous les tweets à travers un filtre afin de détecter les propos abusifs avant de les retweet. Vous pouvez implémenter de telles fonctionnalités en utilisant des expressions régulières et un traitement en langage naturel. En outre, lorsque vous recherchez des sources à explorer, suivez votre jugement et évitez celles qui répandent des informations erronées. Pour en savoir plus sur la botiquette, vous pouvez visiterthis blog post de Joe Mayo sur le sujet.