Acum câteva luni am primit un challenge de la maică-mea – avea nevoie de twitt-uri (așa s-o scrie?) care conțineau un anumit hashtag (adica #ceva). Evident, poti să intri pe Twitter, să dai search și să primești o listă de rezultate, dar ideea aici era să fie scoase într-un format gestionabil (un Excel sau ceva în genul ăsta) – pentru a putea fi folosite într-un raport.
Sigur, cea mai simplă soluție pentru așa ceva este să folosești ceva tool care simulează un browser, să faci un search după hashtag-ul dorit, și după aia să scrii un parser pentru pagina rezultată. Boooooring și, might I add, foarte murdar.
Twitter este una din aplicațiile web care au pionierat facilitarea accesului la date printr-un API (bazat pe un protocol REST). Așa că am gugălit twitter api python și, deloc surprinzător am găsit python-twitter, un wrapper python peste API-ul de la twitter.
După câteva zeci de minute, câteva zeci de linii de cod (python este mega-concis din punctul ăsta de vedere) am reușit să scot datele de care aveam nevoie în format .csv. Principalele probleme de care m-am lovit au fost de codare (întotdeaună mă încurc la asta).
Suficientă introducere, să trecem la fapte:
import twitter
from twitter import *
from BeautifulSoup import BeautifulSoup
# Constante
path_to_file = "/path/to/file.csv"
search_term = "#hash_for_searching"
# Avem nevoie de o instanta a API-ului
api = twitter.Api()
def extractlinks(html):
'''
Extrage link-urile dintr-un text (ca sa nu fie afisate aiurea)
'''
soup = BeautifulSoup(html)
anchors = soup.findAll('a')
links = []
for a in anchors:
links.append(a['href'])
return links[0]
# Numaratoarea paginilor cu python-twitter incepe de la 1
i = 1
import codecs
with codecs.open(path_to_file, mode = "w", encoding = "utf-8") as f:
fields = ["CreatedAt", "Contributors", "Coordinates", "Favourited",
"Id", "InReplyToScreenName", "InReplyToStatusId", "InReplyToUserId",
"Location", "RelativeCreatedAt", "Retweeted", "Source", "Text",
"Truncated", "UID"]
# Scrie in CSV capul de tabel
f.write("|".join(fields))
f.write("\n\r")
# executa o cautare
# este o limita de twitt-uri pe care API-ul le trimite dintr-o data
# am gasit ca la 50 de inregistrari odata totul merge bine
res = api.GetSearch(search_term, per_page = 50, page = i)
# scriu in CSV toate datele ce le pot obtine despre un twit
# multe dintre ele sunt nule sau goale, si relevante pentru crearea
# de mesaje
while len(res):
for tweet in res:
try:
f.write("\"%s\"|" % tweet.GetCreatedAt())
f.write("\"%s\"|" % tweet.GetContributors())
f.write("\"%s\"|" % tweet.GetCoordinates())
f.write("\"%s\"|" % tweet.GetFavorited())
f.write("\"%d\"|" % tweet.GetId())
if tweet.GetInReplyToScreenName():
f.write("\"%s\"|" % tweet.GetInReplyToScreenName())
else:
f.write("|")
if tweet.GetInReplyToStatusId():
f.write("\"%d\"|" % tweet.GetInReplyToStatusId())
else:
f.write("|")
if tweet.GetInReplyToUserId():
f.write("\"%d\"|" % tweet.GetInReplyToUserId())
else:
f.write("|")
from BeautifulSoup import BeautifulStoneSoup
if tweet.GetLocation():
f.write("\"%s\"|" % tweet.GetLocation())
else:
f.write("|")
f.write("\"%s\"|" % tweet.GetRelativeCreatedAt())
f.write("\"%s\"|" % tweet.GetRetweetCount())
if tweet.GetSource():
source_link = extractlinks(BeautifulStoneSoup(tweet.GetSource(), convertEntities=BeautifulStoneSoup.HTML_ENTITIES).contents[0])
f.write("\"%s\"|" % source_link)
f.write(u"\"%s\"|" % tweet.GetText())
f.write("\"%s\"|" % tweet.GetTruncated())
f.write("\"%s\"|" % tweet.GetUser().GetScreenName())
except UnicodeDecodeError, e:
f.write(str(e))
continue
f.write(u"\r\n")
i += 1
res = api.GetSearch(search_term, per_page = 50, page = i)
Si ce info stie sa iti exporte despre twitturile alea? :)
Este un dictionar acolo, se numește fields – alea sunt câmpurile care sunt definite de protocol – dar dupa cum am scris în comentariu, sunt doar câteva completate pentru twitt-uri venite din afară.