| 1408 | TWITTER_RETWEET = re.compile(r"(\s|^RT )(@[a-z0-9_\-]+)", re.I) # Word starts with "RT @". |
| 1409 | |
| 1410 | class Twitter(SearchEngine): |
| 1411 | |
| 1412 | def __init__(self, license=None, throttle=0.5, language=None): |
| 1413 | SearchEngine.__init__(self, license or TWITTER_LICENSE, throttle, language) |
| 1414 | self._pagination = {} |
| 1415 | |
| 1416 | def _authenticate(self, url): |
| 1417 | url.query.update({ |
| 1418 | "oauth_version": "1.0", |
| 1419 | "oauth_nonce": oauth.nonce(), |
| 1420 | "oauth_timestamp": oauth.timestamp(), |
| 1421 | "oauth_consumer_key": self.license[0], |
| 1422 | "oauth_token": self.license[2][0], |
| 1423 | "oauth_signature_method": "HMAC-SHA1" |
| 1424 | }) |
| 1425 | url.query["oauth_signature"] = oauth.sign(url.string.split("?")[0], url.query, |
| 1426 | method = GET, |
| 1427 | secret = self.license[1], |
| 1428 | token = self.license[2][1] |
| 1429 | ) |
| 1430 | return url |
| 1431 | |
| 1432 | def search(self, query, type=SEARCH, start=1, count=10, sort=RELEVANCY, size=None, cached=False, **kwargs): |
| 1433 | """ Returns a list of results from Twitter for the given query. |
| 1434 | - type : SEARCH, |
| 1435 | - start: Result.id or int, |
| 1436 | - count: maximum 100. |
| 1437 | There is a limit of 150+ queries per 15 minutes. |
| 1438 | """ |
| 1439 | if type != SEARCH: |
| 1440 | raise SearchEngineTypeError |
| 1441 | if not query or count < 1 or (isinstance(start, (int, float)) and start < 1): |
| 1442 | return Results(TWITTER, query, type) |
| 1443 | if isinstance(start, (int, float)) and start < 10000: |
| 1444 | id = (query, kwargs.get("geo"), int(start), count) |
| 1445 | id = self._pagination.pop(id, "") |
| 1446 | else: |
| 1447 | id = start or "" |
| 1448 | # 1) Construct request URL. |
| 1449 | url = URL(TWITTER + "search/tweets.json?", method=GET) |
| 1450 | url.query = { |
| 1451 | "q": query, |
| 1452 | "max_id": id, |
| 1453 | "count": min(count, 100) |
| 1454 | } |
| 1455 | # 2) Restrict location with geo=(latitude, longitude, radius). |
| 1456 | # It can also be a (latitude, longitude)-tuple with default radius "10km". |
| 1457 | if "geo" in kwargs: |
| 1458 | url.query["geocode"] = ",".join((map(str, kwargs.pop("geo")) + ["10km"])[:3]) |
| 1459 | # 3) Restrict most recent with date="YYYY-MM-DD". |
| 1460 | # Only older tweets are returned. |
| 1461 | if "date" in kwargs: |
| 1462 | url.query["until"] = kwargs.pop("date") |
| 1463 | # 4) Restrict language. |
| 1464 | url.query["lang"] = self.language or "" |
| 1465 | # 5) Authenticate. |
| 1466 | url = self._authenticate(url) |
| 1467 | # 6) Parse JSON response. |
no outgoing calls
no test coverage detected
searching dependent graphs…