INST728E - Module 4. Collecting Social Media Data

This notebook contains examples for using web-based APIs (Application Programmer Interfaces) to download data from social media platforms. Our examples will include:

  • Reddit
  • Facebook
  • Twitter

For most services, we need to register with the platform in order to use their API. Instructions for the registration processes are outlined in each specific section below.

We will use APIs because they can be much faster than manually copying and pasting data from the web site, APIs provide uniform methods for accessing resources (searching for keywords, places, or dates), and it should conform to the platform's terms of service (important for partnering and publications). Note however that each of these platforms has strict limits on access times: e.g., requests per hour, search history depth, maximum number of items returned per request, and similar.

In [1]:
%matplotlib inline

import json


Topic 2.1: Reddit API

Reddit's API used to be the easiest to use since it did not require credentials to access data on its subreddit pages. Unfortunately, this process has been changed, and developers now need to create a Reddit application on Reddit's app page located here: (https://www.reddit.com/prefs/apps/).

In [15]:
# For our first piece of code, we need to import the package 
# that connects to Reddit. Praw is a thin wrapper around reddit's 
# web APIs and works well

import praw

Creating a Reddit Application

Go to https://www.reddit.com/prefs/apps/. Scroll down to "create application", select "web app", and provide a name, description, and URL (which can be anything).

After you press "create app", you will be redirected to a new page with information about your application. Copy the unique identifiers below "web app" and beside "secret". These are your client_id and client_secret values, which you need below.

In [16]:
# Now we specify a "unique" user agent for our code
# This is primarily for identification, I think, and some
# user-agents of bad actors might be blocked
redditApi = praw.Reddit(client_id='xxx',
                        client_secret='xxx',
                        user_agent='crisis_informatics_v01')

Capturing Reddit Posts

Now for a given subreddit, we can get the newest posts to that sub. Post titles are generally short, so you could treat them as something similar to a tweet.

In [20]:
subreddit = "worldnews"

targetSub = redditApi.subreddit(subreddit)

submissions = targetSub.new(limit=10)
for post in submissions:
    print(post.title, type(post.author.name))
France's Macron takes the reins when it comes to EU-China relations <class 'str'>
New MH370 search approved as Malaysia offers $70 million reward - Livemint <class 'str'>
Julian Assange’s bid for diplomatic status rejected by Britain | Media <class 'str'>
Government whistleblowers and journalists who report on leaked information could face 20 years’ imprisonment if changes to Australia’s official secrecy laws pass parliament <class 'str'>
A 7-year-old Pakistani girl was raped, strangled and left in a dumpster. <class 'str'>
Cold front claims 54 victims across Taiwan <class 'str'>
Shots reported fired at Cal State San Bernardino; classes canceled <class 'str'>
Norway’s prime minister told President Donald Trump on Wednesday that her country remains committed to the Paris climate agreement, making the business case of the “green economy” to the real estate developer-turned president. <class 'str'>
Illnesses affecting Canadian diplomats, families in Cuba still a mystery: Global Affairs official. Operations continue as normal and all eight people so far affected have returned to work or school, the official said Wednesday. <class 'str'>
Thai PM leaves cardboard cutout to take questions from the media <class 'str'>
In [13]:
subreddit = "equality"
targetSub = redditApi.subreddit(subreddit)

# Array for storing subreddit post titles
title_list = []
submissions = targetSub.new(limit=10)
for post in submissions:
        title_list.append(post.title)

print(title_list)


from nltk.tokenize import TweetTokenizer

tokenizer = TweetTokenizer()
for post_title in title_list:
    tokenizer.tokenize(post_title)
[]

Leveraging Reddit's Voting

Getting the new posts gives us the most up-to-date information. You can also get the "hot" posts, "top" posts, etc. that should be of higher quality. In theory. Caveat emptor

In [5]:
subreddit = "worldnews"

targetSub = redditApi.subreddit(subreddit)

submissions = targetSub.hot(limit=5)
for post in submissions:
    print(post.title)
Putin: Russia warns U.S. against 'meddling' in presidential election
Germany energy consumers paid to use power over Christmas as supply outstrips demand
World's Wealthiest Became $1 Trillion Richer in 2017
'Coral bleaching is getting worse ... but the biggest problem is pollution': Conservationists are battling to save the 700-mile Mesoamerican Barrier Reef in the Caribbean suffering the effects of mass tourism and global warming.
Scotland is starting a universal basic income experiment in 2018.

Following Multiple Subreddits

Reddit has a mechanism called "multireddits" that essentially allow you to view multiple reddits together as though they were one. To do this, you need to concatenate your subreddits of interesting using the "+" sign.

In [8]:
subreddit = "worldnews+news"

targetSub = redditApi.subreddit(subreddit)
submissions = targetSub.new(limit=10)
for post in submissions:
    print(post.title, post.author)
3 Big Cities Sue DoD Over Gun-Database Reporting After Texas Church Shooting AAVale
Turkey to review 11,480 cases linked to app used by coup suspects onepoint9
Russia has lost contact with Angola's first national telecoms satellite launched from Baikonur space pad...new embarrassment for country's once proud space industry after Russia in November lost contact with weather satellite after it was launched from new cosmodrome in country's far east. madazzahatter
The head of the Pacific Command for U.S. forces called on Tokyo to regulate drone flights over U.S. military installations in Japan before a "dangerous" incident, such as an accident or terrorist attack, occurs. madazzahatter
China, Afghanistan to strengthen military cooperation fuckyoudumbmods
Ottawa axes $1,000 application fee to hire foreign nannies & caregivers - new regulations apply to those who earn less than $150,000 a year & want to hire someone from abroad to look after their children. Those seeking to hire caregiver for people with physical or mental illness will also be exempt. madazzahatter
A business where human bodies were butchered, packaged and sold congenital-itch
Top German newspaper editor accuses churches of left-wing bias: Ulf Poschardt, head of one of Germany's leading newspapers, has sparked a social media row over supposed left-wing bias in church sermons during Christmas. Churches have denied the claim. madazzahatter
China’s Military Flybys Raise Alarm in Taiwan guanaco55
Martin Shkreli's ex-lawyer is convicted of aiding him in fraud scheme Living_Granger

Accessing Reddit Comments

While you're never supposed to read the comments, for certain live streams or new and rising posts, the comments may provide useful insight into events on the ground or people's sentiment. New posts may not have comments yet though.

Comments are attached to the post title, so for a given submission, you can pull its comments directly.

Note Reddit returns pages of comments to prevent server overload, so you will not get all comments at once and will have to write code for getting more comments than the top ones returned at first. This pagination is performed using the MoreXYZ objects (e.g., MoreComments or MorePosts).

In [9]:
subreddit = "worldnews"

breadthCommentCount = 5

targetSub = redditApi.subreddit(subreddit)

submissions = targetSub.hot(limit=1)

for post in submissions:
    print (post.title)
    
    post.comment_limit = breadthCommentCount
    
    # Get the top few comments
    for comment in post.comments.list():
        if isinstance(comment, praw.models.MoreComments):
            continue
        
        print ("---", comment.name, "---")
        print ("\t", comment.body)
        
        for reply in comment.replies.list():
            if isinstance(reply, praw.models.MoreComments):
                continue
            
            print ("\t", "---", reply.name, "---")
            print ("\t\t", reply.body)
Putin: Russia warns U.S. against 'meddling' in presidential election
--- t1_drtt2jh ---
	 This reads like an Onion headline
	 --- t1_dru3uva ---
		 Anything politics related has been sounding like an Onion article lately 
--- t1_drtr2ye ---
	 Putin: you can't really "meddle" with our pre-rigged election, but it would be fun to watch you try.
--- t1_drtluic ---
	 I mean, what would even be the point when the only choices are Putin and "People still alive/allowed on the ballot purely because they don't pose a political threat to Putin"?
	 --- t1_drtq340 ---
		 The point is literally just rhetoric. Putin gets to pretend to be elected, Russians get to pretend like they're choosing, and he's going to claim the US interfered anyway just to keep the conversation about somebody else. 
--- t1_dru3uva ---
	 Anything politics related has been sounding like an Onion article lately 
--- t1_drtq340 ---
	 The point is literally just rhetoric. Putin gets to pretend to be elected, Russians get to pretend like they're choosing, and he's going to claim the US interfered anyway just to keep the conversation about somebody else. 

Other Functionality

Reddit has a deep comment structure, and the code above only goes two levels down (top comment and top comment reply). You can view Praw's additional functionality, replete with examples on its website here: http://praw.readthedocs.io/


Topic 2.2: Facebook API

Getting access to Facebook's API is slightly easier than Twitter's in that you can go to the Graph API explorer, grab an access token, and immediately start playing around with the API. The access token isn't good forever though, so if you plan on doing long-term analysis or data capture, you'll need to go the full OAuth route and generate tokens using the approved paths.

In [2]:
# As before, the first thing we do is import the Facebook
# wrapper

import facebook

Connecting to the Facebook Graph

Facebook has a "Graph API" that lets you explore its social graph. For privacy concerns, however, Facebook's Graph API is extremely limited in the kinds of data it can view. For instance, Graph API applications can now only view profiles of people who already have installed that particular application. These restrictions make it quite difficult to see a lot of Facebook's data.

That being said, Facebook does have many popular public pages (e.g., BBC World News), and articles or messages posted by these public pages are accessible. In addition, many posts and comments made in reply to these public posts are also publically available for us to explore.

To connect to Facebook's API though, we need an access token (unlike Reddit's API). Fortunately, for research and testing purposes, getting an access token is very easy.

Acquiring a Facebook Access Token

  1. Log in to your Facebook account
  2. Go to Facebook's Graph Explorer (https://developers.facebook.com/tools/explorer/)
  3. Copy the long string out of "Access Token" box and paste it in the code cell bedlow

In [14]:
fbAccessToken = "xxx"

Now we can use the Facebook Graph API with this temporary access token (it does expire after maybe 15 minutes).

In [15]:
# Connect to the graph API, note we use version 2.7
graph = facebook.GraphAPI(access_token=fbAccessToken, version='2.7')

Parsing Posts from a Public Page

To get a public page's posts, all you need is the name of the page. Then we can pull the page's feed, and for each post on the page, we can pull its comments and the name of the comment's author. While it's unlikely that we can get more user information than that, author name and sentiment or text analytics can give insight into bursting topics and demographics.

In [21]:
# What page to look at?
targetPage = "JcibClassOf2003"

# Other options for pages:
# nytimes, bbc, bbcamerica, bbcafrica, redcross, disaster

maxPosts = 10 # How many posts should we pull?
maxComments = 5 # How many comments for each post?

post = graph.get_object(id=targetPage + '/feed')

# For each post, print its message content and its ID
for v in post["data"][:maxPosts]:
    print ("---")
    print (v["message"], v["id"], list(v.keys()))
        
    # For each comment on this post, print its number, 
    # the name of the author, and the message content
    print ("Comments:")
    comments = graph.get_object(id='%s/comments' % v["id"])
    for (i, comment) in enumerate(comments["data"][:maxComments]):
        print ("\t", i, comment["message"], list(comment.keys()))
---
Hey Class of 2003. I am currently a senior at JCIB.  Madame George is retiring this year and we are making a video with messages and pictures from Alumni. If you would like to be in the video send me the picture you'd like to use, a message to Madame, your French name, and your graduation year. And if you know any other Alumni from previous classes would you please let them know, and let them know they can send their information to me via Facebook or email. My email is lildot96@yahoo.com.  We have to have all the pictures by April 1. 389717567786380_784453528312780 ['message', 'created_time', 'id']
Comments:
---
Does anyone have any updates on Mrs Ball? 389717567786380_586745338083601 ['message', 'created_time', 'id']
Comments:
---
Hey guys! Did anyone happen to take pictures from the reunion? I know I'd love to see some! 389717567786380_572769072814561 ['message', 'created_time', 'id']
Comments:
---
Thought I'd share this sweet note I received over the weekend from Mrs. Ball thanking us for our donation. In case you can't read it, she says she's doing well and has recently received test results showing reduced cancer markers! She is otherwise keeping busy & enjoying retirement. 389717567786380_10101525195582691 ['message', 'created_time', 'id']
Comments:
---
Per Cody's suggestion, the donation has been made to St Jude's Hospital in Mrs. Ball's honor. I also just dropped a note in the mail to her regarding the donation & how much we appreciate all her support through the years at IB. -H 389717567786380_470205253070944 ['message', 'created_time', 'id']
Comments:
---
Guys I love Ms. Ball like you all do, but I feel like this money should be going to St. Judes.  Not only does it have a personal touch because Haley's niece is there, but they are non-profit and help families who can't afford the medical treatment otherwise.  They are also doing amazing things with research that could pave the way for our kids and/or grand kids. The major way that this facility stays afloat is by donations.  I can't think of a more worthy cause.- Joanna 389717567786380_463018280456308 ['message', 'created_time', 'id']
Comments:
	 0 I fully support either giving to St. Jude's or something in Kelly's memory. ['created_time', 'message', 'id']
	 1 Thanks Joanna. I'm good with whatever the group decides. We could also split the funds between the two. My only concern with doing something for Mrs Ball is what do we do? It's not exactly something you send flowers for & with a card that says "sorry you're sick". I'd be more comfortable with flowers if a handful of people were willing to deliver them personally which we would need to arrange with her. Does anybody have any good ideas for this situation? ['created_time', 'message', 'id']
	 2 Forgot to look at the results of the poll. It's actually split between St. Jude's and Mrs. Ball. Perhaps we move forward with the half-and-half thing? Or we could make half of the donation (or all of it even) to St. Jude's in Mrs. Ball's name since she is also dealing with cancer. I think maybe a card or person telling her that would be nice. ['created_time', 'message', 'id']
---
Random question to anyone: did anyone actually get video of the ridiculous dance number at the reunion?   389717567786380_462810273810442 ['message', 'created_time', 'id']
Comments:
---
I put together a quick anonymous poll for the additional funds. It closes Friday, so get your selection in by then! Note that if you select *Other*, please put your suggestion in the comment box. 389717567786380_791445735023 ['message', 'created_time', 'id']
Comments:
---
We have just north of $100 left over from the reunion once accounts were settled & refunds issued. Given that it might be ridiculous to keep the funds for the next reunion in 10 yrs, I'd like to donate it to a worthy cause. If you have a suggestion for a cause, please list it in a comment below. If you suggest it, you must be willing to find donation contact info or an avenue of payment. Vote for a cause by "liking" the comment it's posted in. I'll 'close' the voting a week from today. Thanks! -H 389717567786380_462376613853808 ['message', 'created_time', 'id']
Comments:
	 0 Can I suggest Neverthirst? My friend is biking from Bham to Montana to raise money for a water well in Cambodia through an organization called Neverthirst. They go to impoverished countries and provide clean water....amazing cause and amazing group of people.... ['created_time', 'message', 'id']
	 1 Many of you guys know that my 3 yr old niece Kate was diagnosed back in March with leukemia. It's my sister (who also went to IB) Erin's oldest daughter. After seeing what an amazing hospital it is & learning that they make it cost-free to the families there, I'd like to donate the funds to St Jude's Research Hospital to help the efforts in the search for a cure of childhood cancer. ['created_time', 'message', 'id']
	 2 Gresham Elementary school playground! We've been raising money for five years!!! ['created_time', 'message', 'id']
	 3 We could take that $100 and send something nice to Ms Ball and her family? Since some of us were looking to send her something anyways... ['created_time', 'message', 'id']
	 4 I think Kera's idea is pretty great! ['created_time', 'message', 'id']
---
Hey All, Mrs. Ball from IB was recently diagnosed with stage 4 breast cancer, after losing her husband to cancer just this past fall. If you'd like to get her address to send a card or something, please get in touch with Taylor Narewski.  -H 389717567786380_459475010810635 ['message', 'created_time', 'id']
Comments:


Topic 2.1: Twitter API

Twitter's API is probably the most useful and flexible but takes several steps to configure. To get access to the API, you first need to have a Twitter account and have a mobile phone number (or any number that can receive text messages) attached to that account. Then, we'll use Twitter's developer portal to create an "app" that will then give us the keys tokens and keys (essentially IDs and passwords) we will need to connect to the API.

So, in summary, the general steps are:

  1. Have a Twitter account,
  2. Configure your Twitter account with your mobile number,
  3. Create an app on Twitter's developer site, and
  4. Generate consumer and access keys and secrets.

We will then plug these four strings into the code below.

In [2]:
# For our first piece of code, we need to import the package 
# that connects to Twitter. Tweepy is a popular and fully featured
# implementation.

import tweepy

Creating Twitter Credentials

For more in-depth instructions for creating a Twitter account and/or setting up a Twitter account to use the following code, I will provide a walkthrough on configuring and generating this information.

First, we assume you already have a Twitter account. If this is not true, either create one real quick or follow along. See the attached figures.

  • Step 1. Create a Twitter account If you haven't already done this, do this now at Twitter.com.

  • Step 2. Setting your mobile number Log into Twitter and go to "Settings." From there, click "Mobile" and fill in an SMS-enabled phone number. You will be asked to confirm this number once it's set, and you'll need to do so before you can create any apps for the next step.

  • Step 3. Create an app in Twitter's Dev site Go to (apps.twitter.com), and click the "Create New App" button. Fill in the "Name," "Description," and "Website" fields, leaving the callback one blank (we're not going to use it). Note that the website must be a fully qualified URL, so it should look like: http://test.url.com. Then scroll down and read the developer agreement, checking that agree, and finally click "Create your Twitter application."

  • Step 4. Generate keys and tokens with this app After your application has been created, you will see a summary page like the one below. Click "Keys and Access Tokens" to view and manage keys. Scroll down and click "Create my access token." After a moment, your page should refresh, and it should show you four long strings of characters and numbers, a consume key, consumer secret, an access token, and an access secret (note these are case-sensitive!). Copy and past these four strings into the quotes in the code cell below.

In [3]:
# Use the strings from your Twitter app webpage to populate these four 
# variables. Be sure and put the strings BETWEEN the quotation marks
# to make it a valid Python string.

consumer_key = "xxx"
consumer_secret = "xxx"
access_token = "xxx"
access_secret = "xxx"

Connecting to Twitter

Once we have the authentication details set, we can connect to Twitter using the Tweepy OAuth handler, as below.

In [4]:
# Now we use the configured authentication information to connect
# to Twitter's API
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_secret)

api = tweepy.API(auth)

print("Connected to Twitter!")
Connected to Twitter!

Testing our Connection

Now that we are connected to Twitter, let's do a brief check that we can read tweets by pulling the first few tweets from our own timeline (or the account associated with your Twitter app) and printing them.

In [5]:
# Get tweets from our timeline
public_tweets = api.home_timeline()

# print the first five authors and tweet texts
for tweet in public_tweets[:5]:
    print (tweet.author.screen_name, tweet.author.name, "said:", tweet.text)
TheJusticeDept Justice Department said: Algerian Man Pleads Guilty to Conspiring with Pennsylvania Woman and Others to Provide Material Support to Terroris… https://t.co/oDaLwqMnDX
Code2040 Code2040 said: When they're not helping non-profits grow their digital fundraising programs, they spend their time traveling, cura… https://t.co/9hX9BUvQlo
msuster Mark Suster said: RT @upfrontvc: Building a world-class sneaker @goatapp marketplace takes best-in-class technical innovation, exhibit A: https://t.co/p8Jjk9…
Code2040 Code2040 said: They joined the Advocacy team after a few years of organizing, facilitating, and doing advocacy work focused on eco… https://t.co/8uijuQbNou
Code2040 Code2040 said: About @arosembert: Adrianna Rosembert is an Advocacy Associate at @actblue, a Code2040 Supporting Partner. After bu… https://t.co/XodhHhqiki

Searching Twitter for Keywords

Now that we're connected, we can search Twitter for specific keywords with relative ease just like you were using Twitter's search box. While this search only goes back 7 days and/or 1,500 tweets (whichever is less), it can be powerful if an event you want to track just started.

Note that you might have to deal with paging if you get lots of data. Twitter will only return you one page of up to 100 tweets at a time.

In [20]:
# Our search string
queryString = "earthquake"

# Perform the search
matchingTweets = api.search(queryString)

print ("Searched for:", queryString)
print ("Number found:", len(matchingTweets))

# For each tweet that matches our query, print the author and text
print ("\nTweets:")
for tweet in matchingTweets:
    print (tweet.author.screen_name, tweet.author.name, tweet.text)
Searched for: earthquake
Number found: 10

Tweets:
earthquake_all2 全地震速報2🐾 【微小地震速報】
2017/12/28 8:18:35 JST, 
アメリカ合衆国 アンカレッジの北東154km, 
ML1.9, TNT10.7kg, 深さ22.7km, 
https://t.co/HIOEc1rfJL
rascal8346 rascal8346 RT @CNN: 9-year-old Schnaika was brought to the US for treatment after she was injured in Haiti's 2010 earthquake. But despite her increasi…
TodoTiempo TodoTiempo #Temblor♨ M 2.7 - 22km NW of Cedar City, Utah https://t.co/Yi00JimJGm #Temblor #EarthQuake
njazlynda 🔫 RT @MajalahMastika: 6. Earthquake 9.5 skala richter, gempa paling terkuat yg pernah tercatat dalam sejarah gempa bumi. Berlaku di Chile, 19…
MalayaoJm John Miguel Malayao RT @dosomething: 15. @ShawnMendes is number fifteen on our Celebs Gone Good 2017 list! A staple of the Celebs Gone Good list, the singer ra…
TakumiSoftware 地震情報 【USGS震源情報】
発生:2017/12/28 01:33:07 JST
震源地:ソロモン諸島
深さ:160.5km
マグニチュード:4.7
https://t.co/CMSWLdKozU
EMSC AllQuakes - EMSC Update: M4.6 #earthquake (#sismo) strikes 86 km S of #Akhiok (#Alaska) 1hr 1min ago. https://t.co/5PskHpZjGN
SubCastCo Submarine Broadcasting Co RT @41Strange: In Japanese Folklore, Ōkubi are giant decapitated heads which fly in the sky or hide in barns. If you encounter an Ōkubi, it…
PatriclaDawn Patricia Swicegood RT @EdminLord: Is this the big #earthquake in California?
earthquake_all2 全地震速報2🐾 【微小地震速報】
2017/12/28 8:07:15 JST, 
アメリカ合衆国 ハワイ ホノルルの南東364km, 
MD1.7, TNT5.4kg, 深さ6.1km, 
https://t.co/QRNvsHBATy

More Complex Queries

Twitter's Search API exposes many capabilities, like filtering for media, links, mentions, geolocations, dates, etc. We can access these capabilities directly with the search function.

For a list of operators Twitter supports, go here: https://dev.twitter.com/rest/public/search

In [21]:
# Lets find only media or links about earthquakes
queryString = "earthquake (filter:media OR filter:links)"

# Perform the search
matchingTweets = api.search(queryString)

print ("Searched for:", queryString)
print ("Number found:", len(matchingTweets))

# For each tweet that matches our query, print the author and text
print ("\nTweets:")
for tweet in matchingTweets:
    print (tweet.author.screen_name, tweet.text)
Searched for: earthquake (filter:media OR filter:links)
Number found: 11

Tweets:
QuakesToday 1.6 magnitude #earthquake. 15 km from #Lincoln, MT, United States https://t.co/Uv0tZjx5W3
QuakesToday 2.7 magnitude #earthquake. 22 km from #Enoch, UT, United States https://t.co/RL9U3ZO6AL
Quake_Tracker Mag: 2.65 - Depth: 7 km - UTC 9:52 PM -  Cedar City, Utah - USGS Info: https://t.co/i6n2kjisZt
raspishake #RT A NEW #RaspberryShake 1D #earthquake monitor is online in- #Austria!: AM.R655B

Get yours: https://t.co/EJKlmcHPV4
earthquake_all2 【微小地震速報】
2017/12/28 8:18:35 JST, 
アメリカ合衆国 アンカレッジの北東154km, 
ML1.9, TNT10.7kg, 深さ22.7km, 
https://t.co/HIOEc1rfJL
rascal8346 RT @CNN: 9-year-old Schnaika was brought to the US for treatment after she was injured in Haiti's 2010 earthquake. But despite her increasi…
TodoTiempo #Temblor♨ M 2.7 - 22km NW of Cedar City, Utah https://t.co/Yi00JimJGm #Temblor #EarthQuake
njazlynda RT @MajalahMastika: 6. Earthquake 9.5 skala richter, gempa paling terkuat yg pernah tercatat dalam sejarah gempa bumi. Berlaku di Chile, 19…
MalayaoJm RT @dosomething: 15. @ShawnMendes is number fifteen on our Celebs Gone Good 2017 list! A staple of the Celebs Gone Good list, the singer ra…
TakumiSoftware 【USGS震源情報】
発生:2017/12/28 01:33:07 JST
震源地:ソロモン諸島
深さ:160.5km
マグニチュード:4.7
https://t.co/CMSWLdKozU
EMSC Update: M4.6 #earthquake (#sismo) strikes 86 km S of #Akhiok (#Alaska) 1hr 1min ago. https://t.co/5PskHpZjGN

Dealing with Pages

As mentioned, Twitter serves results in pages. To get all results, we can use Tweepy's Cursor implementation, which handles this iteration through pages for us in the background.

In [22]:
# Lets find only media or links about earthquakes
queryString = "earthquake (filter:media OR filter:links)"

# How many tweets should we fetch? Upper limit is 1,500
maxToReturn = 100

# Perform the search, and for each tweet that matches our query, 
# print the author and text
print ("\nTweets:")
for status in tweepy.Cursor(api.search, q=queryString).items(maxToReturn):
    print (status.author.screen_name, status.text)
Tweets:
CEISismologia #Sismo Ml 2.7  UTAH #Earthquake #Temblor #EMSC updates ➡️ https://t.co/GGed8bORLf
earthshook 2.7 earthquake occurred at 27 Dec 2017 22:00:43 UTC, 6.0 km (3.7 mi) NW of Iron Springs, Utah. https://t.co/D4IDo8HE0U
umbrios RT @MeeuRotaru: TY4RT @MalickNormand &amp; @ElleInTheUK &amp; @umbrios !
Quick solution to replacing disaster-destroyed homes
https://t.co/kpPlV558…
DeeViviana_ What y’all bouta charge this earthquake with? https://t.co/CSQQ6khHlm
tomodoragon531 RT @earthquake_jp: [速報LV1]27日 22時05分頃 千葉県北西部(N35.6/E140.1)(推定)にて M4.5(推定)の地震が発生。 震源の深さは推定68.8km。( https://t.co/bfKlIpHKjd ) #saigai #jishin…
EQTracker ML 2.6  UTAH | Details: https://t.co/SPO9r7ytnV via EMSC©
PreppersGuide #preppertalk https://t.co/ZdeEkHcqQV M 1.9 - 69km NE of Sutton-Alpine, Alaska - Time 2017-12-27 23:18:35 UTC 2017-1… https://t.co/OSrNiu5lRT
from___japan 【#USGS #Breaking】#earthquake M 3.8 - 89km ENE of Chirikof Island, Alaska https://t.co/zXnqoCwydP #alert #tsunami #prayfromjapan
MissMaximus69 RT @QuakesToday: 1.6 magnitude #earthquake. 15 km from #Lincoln, MT, United States https://t.co/Uv0tZjx5W3
myearthquakeapp 2.65 earthquake occurred 22km NW of Cedar City, Utah at 21:52 UTC! #earthquake #CedarCity https://t.co/aUXSYi5dWJ
_Elizabeth_K RT @latimes: Earthquake: 4.0 quake strikes near San Jose https://t.co/sHHM69drAi https://t.co/aWOwzoMGIp
peucer RT @OWC_Oxford: "It is not light that is needed but fire. Not the gentle shower, but thunder. We need the storm, the whirlwind, and the ear…
MissMaximus69 RT @QuakesToday: 2.7 magnitude #earthquake. 22 km from #Enoch, UT, United States https://t.co/RL9U3ZO6AL
QuakesToday 1.6 magnitude #earthquake. 15 km from #Lincoln, MT, United States https://t.co/Uv0tZjx5W3
QuakesToday 2.7 magnitude #earthquake. 22 km from #Enoch, UT, United States https://t.co/RL9U3ZO6AL
Quake_Tracker Mag: 2.65 - Depth: 7 km - UTC 9:52 PM -  Cedar City, Utah - USGS Info: https://t.co/i6n2kjisZt
raspishake #RT A NEW #RaspberryShake 1D #earthquake monitor is online in- #Austria!: AM.R655B

Get yours: https://t.co/EJKlmcHPV4
earthquake_all2 【微小地震速報】
2017/12/28 8:18:35 JST, 
アメリカ合衆国 アンカレッジの北東154km, 
ML1.9, TNT10.7kg, 深さ22.7km, 
https://t.co/HIOEc1rfJL
rascal8346 RT @CNN: 9-year-old Schnaika was brought to the US for treatment after she was injured in Haiti's 2010 earthquake. But despite her increasi…
TodoTiempo #Temblor♨ M 2.7 - 22km NW of Cedar City, Utah https://t.co/Yi00JimJGm #Temblor #EarthQuake
njazlynda RT @MajalahMastika: 6. Earthquake 9.5 skala richter, gempa paling terkuat yg pernah tercatat dalam sejarah gempa bumi. Berlaku di Chile, 19…
MalayaoJm RT @dosomething: 15. @ShawnMendes is number fifteen on our Celebs Gone Good 2017 list! A staple of the Celebs Gone Good list, the singer ra…
TakumiSoftware 【USGS震源情報】
発生:2017/12/28 01:33:07 JST
震源地:ソロモン諸島
深さ:160.5km
マグニチュード:4.7
https://t.co/CMSWLdKozU
EMSC Update: M4.6 #earthquake (#sismo) strikes 86 km S of #Akhiok (#Alaska) 1hr 1min ago. https://t.co/5PskHpZjGN
SubCastCo RT @41Strange: In Japanese Folklore, Ōkubi are giant decapitated heads which fly in the sky or hide in barns. If you encounter an Ōkubi, it…
earthquake_all2 【微小地震速報】
2017/12/28 8:07:15 JST, 
アメリカ合衆国 ハワイ ホノルルの南東364km, 
MD1.7, TNT5.4kg, 深さ6.1km, 
https://t.co/QRNvsHBATy
jurylady5 RT @NDisaster_Newz: #Earthquake near Tehran, #Iran kills one https://t.co/PJgxKN1y6K https://t.co/hUu46jSOSM
russterry Two earthquakes shake Santa Clara County https://t.co/BXU6YAxsto via @mercnews
earthquake_all2 【微小地震速報】
2017/12/28 8:04:45 JST, 
アメリカ合衆国 アラスカ フェアバンクスの東南東45km, 
ML1.5, TNT2.7kg, 深さ10.3km, 
https://t.co/xmJXwPNd7u
SusanAlijani RT @Iran_probe: One dead and 75 injured in Tehran's last night's #earthquake
#Iran #tehranearthquake 
#Tehran #Iranian 
https://t.co/1U514R…
NDisaster_Newz #Earthquake near Tehran, #Iran kills one https://t.co/PJgxKN1y6K https://t.co/hUu46jSOSM
myearthquakeapp 1.53 earthquake occurred 15km SE of Lincoln, Montana at 13:50 UTC! #earthquake #Lincoln https://t.co/GI2V3vPisP
Earthquakesaler #Earthquake Magnitude 2.6, Petermann Ranges, NT.: Date and time 
 UTC: 27 December 2017 23:02:30 (UTC)
Canberra,... https://t.co/VcaJTRzQGA
spacejjk doesn't anyone just leave it half closed?? like, if there's an earthquake I don't wanna be trapped here but I don't… https://t.co/Y3YGeSeSIA
CEISismologia #Sismo ML 2.6  UTAH #Earthquake #Temblor #EMSC updates ➡️ https://t.co/2JozWi7kZ7
myearthquakeapp 1.9 earthquake occurred 68km NE of Sutton-Alpine, Alaska at 23:18 UTC! #earthquake #SuttonAlpine https://t.co/tjtpg7t2KS
t_hisashi RT @nytimesbooks: "Spare a thought for the poor geologist Stephen Taber, who assessed the 1920 Los Angeles earthquake by counting broken bo…
KLM390 RT @TimesSport: .@AlexMLowe discovers how the RFU is using earthquake training in an attempt to mould the new Martin Johnson https://t.co/N…
julialoveskatya RT @tracysmartel: Alyssa Edwards' earthquake experience https://t.co/wFHjnRCevy
Kaylynndunlap RT @MDavisbot: Back to Back Earthquakes Rattle San Jose California Today.
Magnitude 3.1 and
Magnitude 3.9 Earthquake.
#Earthquake #SanJose…
888theQuake NowPlaying 13 Quinn Tha Earthquake Freestyle - 13 Quinn Tha Earthquake Freestyle https://t.co/dJQHRXJKzP 17:24
earthquake_all2 【小地震速報】
2017/12/28 8:04:09 JST, 
アメリカ合衆国 アラスカ コディアクの南西161km, 
ML3.3, TNT1.3トン, 深さ12.0km, 
https://t.co/sfn3o3JIij
Rotaract_LA RT @Rotary: Rotary members in Italy are helping earthquake damaged communities rebound economically by funding business incubators and ment…
TakumiSoftware (更新)
【USGS震源情報】
発生:2017/12/28 01:33:07 JST
震源地:ソロモン諸島
深さ:160.5km
マグニチュード:4.7
https://t.co/CMSWLdKozU
QuakesToday 1.9 magnitude #earthquake. 67 km from Sutton-Alpine, #AK, United States https://t.co/ZljjHwmipt
MissMaximus69 RT @QuakesToday: 1.5 magnitude #earthquake. 8 km from #EielsonAirForceBase, AK, United States https://t.co/3EPdKIC7hx
debeso0816 08:23:51 震度0 茨城  #地震 #震度 #災害  #earthquake https://t.co/UqJsVmAqsV
earthquake_bot_ 08:23:53 震度0 茨城  #地震関連 #黒豆12028 https://t.co/vOEqWhdTzK
earthquake_bot_ 08:23:53 震度0未満 山形 宮城 福島  #地震関連 #黒豆12028 https://t.co/wyYtjD0Xjs
debeso0816 08:23:51 震度0未満 福島  #地震 #震度 #災害  #earthquake https://t.co/UdxNFpuAb3
Earthquake_nyan 地震検知2017/12/28 08:24:57
第2報
時刻:08:24:21
計測震度:0.2
地震検知都道府県数:2
福島県 0.4gal,宮城県 0.4gal #地震 https://t.co/1ZTj6t1HJI
earthshook 2.7 earthquake occurred at 27 Dec 2017 21:52:37 UTC, 5.9 km (3.6 mi) NW of Iron Springs, Utah. https://t.co/rDqqyivD0G
earthquake_all 【極微小地震速報 大分県3/124】
2017/12/28 7:51:26 JST, 
日本 大分県 別府市役所の西10km, 
M0.6, TNT119.8g, 深さ8.7km, 
MAP https://t.co/EAU09oCimn 1479
Earthquake_nyan 地震検知2017/12/28 08:24:41
第1報
時刻:08:24:04
計測震度:0.2
地震検知都道府県数:1
福島県 0.4gal #地震 https://t.co/mP59oDKzNV
JaBBa_ RT @41Strange: In Japanese Folklore, Ōkubi are giant decapitated heads which fly in the sky or hide in barns. If you encounter an Ōkubi, it…
latinlifedenver INTERNATIONAL PERFORMER AND FASHION DESIGNER, XITLALI, HOSTS ELABORATE BENEFIT SHOW IN THE SANTA FE ARTS... https://t.co/XcspuM56aE
earthquake_all2 【小地震速報】
2017/12/28 8:04:09 JST, 
アメリカ合衆国 アラスカ コディアクの南西159km, 
ML3.3, TNT1.3トン, 深さ9.2km, 
https://t.co/A1U0gBVmJ7
everyEarthquake USGS reports a M1.9 #earthquake 68km NE of Sutton-Alpine, Alaska on 12/27/17 @ 23:18:35 UTC https://t.co/y5hPvl4Vvh #quake
mikel_lisconja RT @pilawk: Wow.. Your fart literally caused an earthquake. You deserve to be in the Guinness book of records. 😄😄 https://t.co/JcbGvzCiTC
Russell_Reports Magnitude 4.8 earthquake in Poland 2 days ago, near to #Polkowice. Anybody feel it? https://t.co/CfHZE47Vw1
earthquake_all 【微小地震速報 福島県21/123】
2017/12/28 7:50:29 JST, 
日本 福島県 富岡町役場の南13km, 
M1.4, TNT1.9kg, 深さ20.0km, 
MAP https://t.co/Z2a4VqRVBY 1474
Xyz_mrmc RT @maymayentrata07: Alam nyo kung anong pinaka pinapasalamatan  namin?"Kayo" dahil sa  suporta na kahit bumagyo man at mag ka earthquake p…
MshreeKumar RT @Chellaney: An example of irresponsible journalism: PTI secures a comment from the Chinese foreign ministry spokesperson not at the dail…
Christsavedme77 RT @Jerusalem_Post: #BREAKING: One dead after 4.2 magnitude earthquake strikes Tehran https://t.co/Iz8wa5puBk https://t.co/EOtEVQu70Y
BenBelonejr RT @OWC_Oxford: "It is not light that is needed but fire. Not the gentle shower, but thunder. We need the storm, the whirlwind, and the ear…
QuakesToday 1.5 magnitude #earthquake. 8 km from #EielsonAirForceBase, AK, United States https://t.co/3EPdKIC7hx
sleep_myy813 RT @eq_map: 【M4.1】KODIAK ISLAND REGION, ALASKA 23.4km 2017/12/28 07:27:20 JST[UTC+9]
(G)https://t.co/bCRyrQUzto (USGS)https://t.co/51CbbXzH…
debeso0816 08:18:42 震度0未満 岩手  #地震 #震度 #災害  #earthquake https://t.co/AJEO5Lkp7f
earthquake_bot_ 08:18:42 震度0未満 岩手  #地震関連 #黒豆12028 https://t.co/dCeYvNPrhj
earthquakeinfos M 1.7 - 18km S of Fern Acres, Hawaii https://t.co/zubWjZwnus
dan_covfefe RT @dovorah001: Do you hear that? It’s the sound of the Soros/Bush/Clinton/Obama underground government being hit by a earthquake.  https:/…
earthquakeinfos M 1.3 - 7km ESE of Eielson Air Force Base, Alaska https://t.co/TGkQNfFCgj
earthquakeinfos M 2.9 - 72km S of Cantwell, Alaska https://t.co/xIn3IzBc4u
earthquakeinfos M 3.3 - 112km S of Larsen Bay, Alaska https://t.co/vesP6qBwxE
earthquakeinfos M 2.9 - 79km NE of Chirikof Island, Alaska https://t.co/OmxrpNBFMl
earthquakeinfos M 3.8 - 89km ENE of Chirikof Island, Alaska https://t.co/xFF29empu1
Earthquake_nyan 地震検知2017/12/28 08:19:29
第1報
時刻:08:18:52
計測震度:0.4
地震検知都道府県数:1
岩手県 0.2gal #地震 https://t.co/LDn08K3Ga8
GreatDestroyer_ https://t.co/0jjZPhNrwL Angry Residents Thought Bassnectar Concert ‘Was An Earthquake’

lmao
EMSC Update: M3.3 #earthquake (#sismo) strikes 109 km S of #Akhiok (#Alaska) 15 min ago. https://t.co/1oudH8dqsS
earthquake_all 【微小地震速報 岐阜県1/122】
2017/12/28 7:49:52 JST, 
日本 岐阜県 恵那市役所の西北西5km, 
M1.3, TNT1.3kg, 深さ16.7km, 
MAP https://t.co/w6fWrR3XBP 1474
neyney2go RT @SpikedCranium: That was no #earthquake ;) https://t.co/b5hWkezHrI
taO_Oti RT @41Strange: In Japanese Folklore, Ōkubi are giant decapitated heads which fly in the sky or hide in barns. If you encounter an Ōkubi, it…
OWC_Oxford "It is not light that is needed but fire. Not the gentle shower, but thunder. We need the storm, the whirlwind, and… https://t.co/qwZp1DY8Sk
WorldEarthquake NEW: M 3.3 - 102km S of Larsen Bay, Alaska https://t.co/h495ws9wNb
seismicupdate USGS:M 3.3 - 102km S of Larsen Bay, Alaska https://t.co/WsEA6QXEK6 #earthquake https://t.co/fjXvznAzc6
koienowakasama RT @tenkijp_jishin: 27日22時5分頃、埼玉県・神奈川県で最大震度3を観測する地震がありました。震源地は千葉県北西部、M4.5。この地震による津波の心配はありません。 https://t.co/wMixbxmoeh #jishin #地震
myearthquakeapp 3.3 earthquake occurred 112km S of Larsen Bay, Alaska at 23:04 UTC! #earthquake #LarsenBay https://t.co/8ozgCMdsgl
tbailey5477 RT @RealBobAxelrod: The only #earthquake I know is this amazing patriot @G1rly_Tattooed . 

Thank you for your positive tweets, and support…
pilawk Wow.. Your fart literally caused an earthquake. You deserve to be in the Guinness book of records. 😄😄 https://t.co/JcbGvzCiTC
from___japan 【#USGS #Breaking】#earthquake M 1.1 - 3km NNE of Colton, CA https://t.co/IHfFKuURvd #alert #tsunami #prayfromjapan
myearthquakeapp 1.3 earthquake occurred 7km ESE of Eielson Air Force Base, Alaska at 23:04 UTC! #earthquake https://t.co/kpbjHoH53G
koienowakasama RT @tenkijp_jishin: 27日22時5分頃、埼玉県・神奈川県などで最大震度3を観測する地震がありました。今後の情報にご注意下さい。 https://t.co/wMixbxmoeh #jishin
gph866 RT @EMSC: Update: M4.8 #earthquake (#زلزله) strikes 63 km N of #Kermān (#Iran) 8 min ago. https://t.co/GrrHiLoLEA
badjerry_1 RT @QLDWhitsundays: 28yrs ago today a magnitude 5.6 earthquake hits Newcastle, New South Wales, killing 13 people https://t.co/vpADCLNIEK h…
myearthquakeapp 1.7 earthquake occurred 18km S of Fern Acres, Hawaii at 23:07 UTC! #earthquake #FernAcres https://t.co/fBRR4NTs2C
Mariehoiles12 RT @dovorah001: Do you hear that? It’s the sound of the Soros/Bush/Clinton/Obama underground government being hit by a earthquake.  https:/…
HeatherRenwick RT @Gjallarhornet: One #dead after 4.2 magnitude #earthquake strikes #Tehran 
#Iran
https://t.co/FUpW4akeFm https://t.co/RprJNuMghY
QuakesToday 1.7 magnitude #earthquake. 18 km from Fern Acres, #HI, United States https://t.co/GPHXyf7L5N
Chairmnoomowmow RT @dovorah001: Do you hear that? It’s the sound of the Soros/Bush/Clinton/Obama underground government being hit by a earthquake.  https:/…
happiness073734 RT @TVXQ: #TVXQ! Donates 50Million Won to Aid Children Affected by Pohang Earthquake
비주얼도 마음도 훈훈한 #동방신기❤️👏  
https://t.co/iaaHaawMAC

Other Search Functionality

The Tweepy wrapper and Twitter API is pretty extensive. You can do things like pull the last 3,200 tweets from other users' timelines, find all retweets of your account, get follower lists, search for users matching a query, etc.

More information on Tweepy's capabilities are available at its documentation page: (http://tweepy.readthedocs.io/)

Other information on the Twitter API is available here: (https://developer.twitter.com/en/docs/tweets/search/overview).

Twitter Streaming

Up to this point, all of our work has been retrospective. An event has occurred, and we want to see how Twitter responded over some period of time.

To follow an event in real time, Twitter and Tweepy support Twitter streaming. Streaming is a bit complicated, but it essentially lets of track a set of keywords, places, or users.

To keep things simple, I will provide a simple class and show methods for printing the first few tweets. Larger solutions exist specifically for handling Twitter streaming.

You could take this code though and easily extend it by writing data to a file rather than the console. I've marked where that code could be inserted.

In [6]:
# First, we need to create our own listener for the stream
# that will stop after a few tweets
class LocalStreamListener(tweepy.StreamListener):
    """A simple stream listener that breaks out after X tweets"""
    
    # Max number of tweets
    maxTweetCount = 10
    
    # Set current counter
    def __init__(self):
        tweepy.StreamListener.__init__(self)
        self.currentTweetCount = 0
        
        # For writing out to a file
        self.filePtr = None
        
    # Create a log file
    def set_log_file(self, newFile):
        if ( self.filePtr ):
            self.filePtr.close()
            
        self.filePtr = newFile
        
    # Close log file
    def close_log_file(self):
        if ( self.filePtr ):
            self.filePtr.close()
    
    # Pass data up to parent then check if we should stop
    def on_data(self, data):

        print (self.currentTweetCount)
        
        tweepy.StreamListener.on_data(self, data)
            
        if ( self.currentTweetCount >= self.maxTweetCount ):
            return False

    # Increment the number of statuses we've seen
    def on_status(self, status):
        self.currentTweetCount += 1
        
        # Could write this status to a file instead of to the console
        print (status.text)
        
        # If we have specified a file, write to it
        if ( self.filePtr ):
            self.filePtr.write("%s\n" % status._json)
        
    # Error handling below here
    def on_exception(self, exc):
        print (exc)

    def on_limit(self, track):
        """Called when a limitation notice arrives"""
        print ("Limit", track)
        return

    def on_error(self, status_code):
        """Called when a non-200 status code is returned"""
        print ("Error:", status_code)
        return False

    def on_timeout(self):
        """Called when stream connection times out"""
        print ("Timeout")
        return

    def on_disconnect(self, notice):
        """Called when twitter sends a disconnect notice
        """
        print ("Disconnect:", notice)
        return

    def on_warning(self, notice):
        print ("Warning:", notice)
        """Called when a disconnection warning message arrives"""

Now we set up the stream using the listener above

In [7]:
listener = LocalStreamListener()
localStream = tweepy.Stream(api.auth, listener)
In [8]:
localStream.sample()
0
0
0
0
0
0
0
0
0
0
RT @Katiohead: I love the owners of this restaurant. https://t.co/72leFn28TR
1
I hope tomorrow is a better day
2
RT @IamAkademiks: Wanna thank God for working way harder than satan 🙏🏿
3
في يوم من الأيّام ستتنازل مجبرًا عن بعض أحلامك حتى تعيش واقعك.
4
RT @favellahaley: Bitches stop being ya friend &amp; think it’s automatically beef lol bitch you’re beefing wit yourself 🤣
5
RT @IamIanJacob: I’m in such an odd mood today. I really wanna fight Donald Trump but I also really wanna fuck Shawn Mendes.
6
RT @Neby_Nebs: the pretty face + small titty combo is UNSTOPPABLE
7
Which applications for I focus my energy on?
8
RT @sa0o__: على حالنا ما غيّر الوقت فينا شي
نعيش بكرامة نفس ونموت ما خنّا 
#انشهد
💙♥️

.
واقول لكم انا حضرت واسعد الله مساكم
 💭♥️
9
RT @Abel_Kills: ESTO ME HA SALVADO LA VIDA. https://t.co/lmeHfbbu60
In [25]:
# Stream based on keywords
localStream.filter(track=['earthquake', 'disaster'])
0
これやばみの極みだよねー https://t.co/kVxU8RJ7EB
1
RT @fchollet: The human mind is an infosec disaster. The way it forms opinions has many flaws (among them, so-called cognitive biases), and…
2
Just watched The Disaster Artist and all I gotta say is James Franco deserves an Oscar it's his best performance by far 👌🏼👍
3
RT @MajalahMastika: Kali ni admin buat THREAD video tentang Earthquake(gempa bumi) . Earthquake salah satu bencana alam yg dahsyat, lebih d…
4
Si pueden llegar al final :D https://t.co/uHzBrwbfFP
5
RT @KamalaHarris: Here are the pressing issues Congress must address once we get back to Washington:
✅ Passing the #DreamAct
✅ Long-term fu…
6
How to Protect a #Home-Based #Business From an Unforeseen Disaster https://t.co/mCbsXPxSZQ https://t.co/dgLFnIJHSc
7
RT @KamalaHarris: Here are the pressing issues Congress must address once we get back to Washington:
✅ Passing the #DreamAct
✅ Long-term fu…
8
RT @PopCrave: Movies turning 10 years old in 2018:

Twilight
Camp Rock
HSM3
Role Models
Step Brothers
The Dark Knight
Iron Man
Hancock
Clov…
9
RT @acgrayling: The Treasury’s study of Brexit’s impact says - it will be a disaster.
In [26]:
listener = LocalStreamListener()
localStream = tweepy.Stream(api.auth, listener)

# List of screen names to track
screenNames = ['bbcbreaking', 'CNews', 'bbc', 'nytimes']

# Twitter stream uses user IDs instead of names
# so we must convert
userIds = []
for sn in screenNames:
    user = api.get_user(sn)
    userIds.append(user.id_str)

# Stream based on users
localStream.filter(follow=userIds)
0
RT @nytimes: 2017: The year in visual stories and graphics https://t.co/KGDUZQKY9a
1
RT @nytimes: Mike Huckabee says President Trump is like Churchill. Historians disagree. https://t.co/oWE5QSkkb1
2
@CNEWS Ils s'y  connaissent mieux pour construire des murs pour isoler les palestiniens et à construire  des prison… https://t.co/8RjWrXd7XM
3
RT @nytimes: Opinion: He built a bot to expose bigots on Twitter. Then Twitter suspended it — and kept the Nazis. https://t.co/7p6FK2ff8D
4
RT @nytimes: Sorry, Twitter users. Your place in the historical record is no longer guaranteed. https://t.co/2Ck1cRWgpk
5
RT @nytimes: The tax bill passed. Now the hunt for creative loopholes can begin. https://t.co/SwWHMkSQN4
6
@nytimes You should see the PC rig my dude just bought. Financing isn't going to be an issue.
7
@nytimes Because most CPAs aren’t stoners? Or because most of the are...🤔
8
@nytimes This is simply fellating Trump because of his daughter. They're deliberately saying this crap because they… https://t.co/WO6ZUNu2gG
9
@nytimes I would most definitely disagree. Trump cannot be compared to Churchill in any way. Churchill was a leader, not an anarchist.
In [29]:
listener = LocalStreamListener()
localStream = tweepy.Stream(api.auth, listener)

# Specify coordinates for a bounding box around area of interest
# In this case, we use San Francisco
swCornerLat = 36.8
swCornerLon = -122.75
neCornerLat = 37.8
neCornerLon = -121.75

boxArray = [swCornerLon, swCornerLat, neCornerLon, neCornerLat]

# Say we want to write these tweets to a file
listener.set_log_file(open("tweet_log.json", "w"))

# Stream based on location
localStream.filter(locations=boxArray)

# Close the log file
listener.close_log_file()
0
Can you recommend anyone for this #job in #Danville, CA? https://t.co/Gyy8NL5ah2 #Banking #Hiring #CareerArc
1
Yet @VanityFair tells @HillaryClinton to go away in 2018....? https://t.co/zzUQmCdS6q
2
Roadtripping with @jimmy_marino pt.2

*sees a chihuahua in the aquarium*

J: That's my favorite kind of shark.
3
I saw the cutest boy today &amp; im so sad I'm never gonna see him again :((
4
So, where are your "fake news" folks?/ Alors où sont vos "fake news" mes amis? 🤠
5
Why did I spend so much money on Hipstamatic before LOL?! https://t.co/epx8nsCmT6
6
@gasca Use a tracker and have a clear goal on time reduction. I've also deleted apps off my phone or hide it in fol… https://t.co/ZKPXbEEs20
7
OMFG 😭❗️❗️❗️ https://t.co/u3MeiplWcR
8
@jacquelinebellm It’s shakes the building
9
Want to work at Robert Half Finance &amp; Accounting? We're #hiring in #SanFrancisco, CA! Click for details:… https://t.co/wXZCw7TYY5
In [ ]: