Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
43cbb83
Update 1.md
QuantumOverture Feb 12, 2020
d8c80a3
Update 2.md
QuantumOverture Feb 12, 2020
2a8017a
Update 3.md
QuantumOverture Feb 12, 2020
8f03c3b
Update 4.md
QuantumOverture Feb 12, 2020
252ba96
Update 5.md
QuantumOverture Feb 12, 2020
35a8740
Update 6.md
QuantumOverture Feb 12, 2020
6061472
Update 7.md
QuantumOverture Feb 12, 2020
a0912e2
Update 8.md
QuantumOverture Feb 12, 2020
81cf407
Create 9.md
QuantumOverture Feb 12, 2020
cb64ab0
Update 2.md
QuantumOverture Feb 12, 2020
27c6177
Update 2.md
QuantumOverture Feb 12, 2020
9d2d48c
Update 3.md
QuantumOverture Feb 12, 2020
07fe876
Update 1.md
QuantumOverture Feb 12, 2020
267ddb9
Update 2.md
QuantumOverture Feb 12, 2020
cece951
Update 3.md
QuantumOverture Feb 12, 2020
3ba9b24
Update 4.md
QuantumOverture Feb 12, 2020
a3aac2e
Update 5.md
QuantumOverture Feb 12, 2020
4d3bfc4
Update 1.md
QuantumOverture Feb 12, 2020
10ce467
Update 1.md
QuantumOverture Feb 13, 2020
748380a
Update 2.md
QuantumOverture Feb 13, 2020
82ac3ec
Update 3.md
QuantumOverture Feb 13, 2020
f712c8d
Update 4.md
QuantumOverture Feb 13, 2020
191e461
Update 6.md
QuantumOverture Feb 13, 2020
c18a013
Update 5.md
QuantumOverture Feb 13, 2020
834dc5d
Update 2.md
QuantumOverture Feb 13, 2020
e4e90a3
Update 1.md
QuantumOverture Feb 13, 2020
9d5cc9c
Update 2.md
QuantumOverture Feb 13, 2020
931ba02
Update 4.md
QuantumOverture Feb 13, 2020
e3a086d
Update 5.md
QuantumOverture Feb 13, 2020
c094911
Update 6.md
QuantumOverture Feb 13, 2020
be3d15f
Update 3.md
QuantumOverture Feb 13, 2020
cee1bd0
Update 4.md
QuantumOverture Feb 13, 2020
5058a98
Update 5.md
QuantumOverture Feb 13, 2020
b962229
Update 6.md
QuantumOverture Feb 13, 2020
bf0a607
Update 8.md
QuantumOverture Feb 13, 2020
5febd70
Update 9.md
QuantumOverture Feb 13, 2020
bcc0b24
Update 1.md
QuantumOverture Feb 13, 2020
613931f
Create 10.md
QuantumOverture Feb 13, 2020
0ab1f4a
Create 11.md
QuantumOverture Feb 13, 2020
b1e431a
Create 12.md
QuantumOverture Feb 13, 2020
f73b5f8
Create 13.md
QuantumOverture Feb 13, 2020
894a691
Create 14.md
QuantumOverture Feb 13, 2020
2b4ef4d
Update 2.md
QuantumOverture Feb 13, 2020
2ef4913
Update 3.md
QuantumOverture Feb 13, 2020
160128b
Update 4.md
QuantumOverture Feb 13, 2020
8c8b1a2
Update 5.md
QuantumOverture Feb 13, 2020
faeecb7
Update 6.md
QuantumOverture Feb 13, 2020
d7c555d
Delete 7.md
QuantumOverture Feb 13, 2020
37a3e2c
Update 8.md
QuantumOverture Feb 13, 2020
5860b55
Update 9.md
QuantumOverture Feb 13, 2020
e220062
Update 3.md
QuantumOverture Feb 17, 2020
197fcf1
Update 1.md
QuantumOverture Feb 17, 2020
2c92875
Update 2.md
QuantumOverture Feb 17, 2020
984ccf5
Update 13.md
QuantumOverture Feb 18, 2020
f0e6237
Update 14.md
QuantumOverture Feb 18, 2020
6f400eb
Update 2.md
QuantumOverture Feb 18, 2020
72bbb15
Update 3.md
QuantumOverture Feb 18, 2020
96ab22e
Update 8.md
QuantumOverture Feb 18, 2020
0273296
Update 2.md
QuantumOverture Feb 19, 2020
583ddfc
Update 5.md
QuantumOverture Feb 19, 2020
ebeb792
Update 4.md
QuantumOverture Feb 19, 2020
269457c
Create 10(real).md
QuantumOverture Feb 22, 2020
1cd2f8f
Create 11(real).md
QuantumOverture Feb 22, 2020
8b736d4
Update 8.md
QuantumOverture Feb 22, 2020
ca603fe
Update 6.md
QuantumOverture Feb 22, 2020
98a7938
Create 9(real).md
QuantumOverture Feb 22, 2020
22580a1
Update 10(real).md
QuantumOverture Feb 22, 2020
6a4b3f2
Update 11(real).md
QuantumOverture Feb 22, 2020
18d98a6
Create 12(real).md
QuantumOverture Feb 22, 2020
6d804d0
Create 13(real).md
QuantumOverture Feb 22, 2020
544ac86
Create 14(real).md
QuantumOverture Feb 22, 2020
260ddc3
Create 15(real).md
QuantumOverture Feb 22, 2020
e370863
Update 9.md
QuantumOverture Feb 22, 2020
5c1f9f2
Next iteration of activity 5
QuantumOverture Feb 22, 2020
5e12c0b
Update 5.md
QuantumOverture Feb 22, 2020
a695346
Update 13.md
QuantumOverture Feb 22, 2020
80e2fa8
Update 13.md
QuantumOverture Feb 22, 2020
7066d18
For Issue #641
QuantumOverture Feb 29, 2020
05db01e
For issue #638
QuantumOverture Feb 29, 2020
59098f9
More content for activity 4
QuantumOverture Feb 29, 2020
48182f6
Update 5.md
QuantumOverture Feb 29, 2020
b28855c
fixed minor grammar - rayna
Mar 4, 2020
58cb546
Addresses #829 #821 #822
QuantumOverture Mar 8, 2020
0bfd810
z
QuantumOverture Mar 8, 2020
ff6d764
merge repair
QuantumOverture Mar 8, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Module_Twitter_API/activities/Act3_Cursor and Pagination/1.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

# Continue from Streaming Live Tweets

<img src="https://i.ibb.co/KzVK30f/twitter-dev-logo.png" style="zoom: 100%;" />

In this part of the activity, we will now continue writing the code for the Tweepy application. Start off by importing two things to the Python file named **tweepy_streamer.py** which we will use in this activity to make it more streamlined and modular:

```python
Expand Down
31 changes: 26 additions & 5 deletions Module_Twitter_API/activities/Act3_Cursor and Pagination/2.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@

# Making Authentication into Its Own Class

Now let's abstract the Authentication into its own class so that we can use it to authenticate for other purposes in this activity.
![](https://upload.wikimedia.org/wikipedia/commons/thumb/d/d2/Oauth_logo.svg/180px-Oauth_logo.svg.png)

You wouldn't want to let unauthorized users messing with your account,right? Here "authentication" comes into play. So lets integrate it right into our class so it becomes an integral part of all our requests to the Twitter API.

Now let's abstract the Authentication into its own class so that we can use it to authenticate for other purposes in this activity. Abstraction makes our code still human readable even though we are doing some very complex things in the background.

First, we are going to do some changes to the code we wrote in **tweepy_streamer.py**:

Expand All @@ -28,16 +32,33 @@ First, we are going to do some changes to the code we wrote in **tweepy_streamer

```python
def __init__(self):
self.twitter_autenticator = TwitterAuthenticator()
self.twitter_autenticator = TwitterAuthenticator()
```

* The above setups our authentication (i.e shows Twitter our credentials, which in turn allow us to use their services).

```python
def stream_tweets(self, fetched_tweets_filename, hash_tag_list):
# This handles Twitter authetification and the connection to Twitter Streaming API
listener = TwitterListener(fetched_tweets_filename)
```

* We declare a function called "stream_tweets" which is part of the **TwitterAuthenticator** class. It accepts a file name (where will be depositing our found tweets) and a hash tag list(which holds the hash tags we need to use to find said tweets).

```python
listener = TwitterListener(fetched_tweets_filename)
auth = self.twitter_autenticator.authenticate_twitter_app()
stream = Stream(auth, listener)

```

* ​ The above lines:
* Give the API a file so it can put tweets on a file in your computer.
* We authenticate ourselves.
* And we finally, crack open a stream and prepare to filter it with our hash tag list...which we will do in the next step.

```python
# This line filter Twitter Streams to capture data by the keywords:
stream.filter(track=hash_tag_list)
```

* This line filter Twitter Streams to capture data by the keywords.

> Here, we changed the init fucntions to the class. We also changed auth = self.twitter_autenticator.authenticate_twitter_app() within the stream_tweets class method
12 changes: 10 additions & 2 deletions Module_Twitter_API/activities/Act3_Cursor and Pagination/3.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@

# Rate limiting

Twitter API has a rate limit. Rate limiting of the standard API is primarily on a per-user basis — or more accurately described, per user access token. If a method allows for 15 requests per rate limit window, then it allows 15 requests per window per access token.
Twitter API has a rate limit. Rate limiting of the standard API is primarily on a per-user basis — or more accurately described, per user access token. If a method allows for 15 requests per rate limit window, then it allows 15 requests per window per access token. In other words, Twitter only allows us to make a certain number of calls to its API during a specified window of time.

When using application-only authentication, rate limits are determined globally for the entire application. If a method allows for 15 requests per rate limit window, then it allows you to make 15 requests per window. If we go over this limit, twitter will throw error code 420 for making too many requests and we might be locked out of the access information.
![](https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTWV_O4lWOgYxv8clbuw3xweMgbCYDELHpzZFmpTfmnyzHLlapY)


> Think of it like a speed limit!



When using application-only authentication, rate limits are determined globally for the entire application(so add up all our calls to the API in our code and that is how many total calls we make). If a method allows for 15 requests per rate limit window, then it allows you to make 15 requests per window. If we go over this limit, twitter will throw error code 420 for making too many requests and we might be locked out of the access information.

This is why it is worthwhile to check that the status message you are receiving is not an error message. Therefore, we are going to change the ```on_error(self, status)``` function to handle a rate limit error:

Expand Down
23 changes: 11 additions & 12 deletions Module_Twitter_API/activities/Act3_Cursor and Pagination/4.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,33 @@ Let's start by declaring a new class and constructor method:
```python
class TwitterClient():
def __init__(self, twitter_user=None):
```

Next we add the following lines to set up the authentication aspect of the code. Here self.auth is the authenticator object (We use this to properly authenticate to communicate with the Twitter API).

self.auth = TwitterAuthenticator().authenticate_twitter_app()
self.twitter_client = API(self.auth)
self.twitter_user = twitter_user
```

>self.auth is the authenticator object (We use this to properly authenticate to communicate with the Twitter API)
Now, let's make a function that allows a user to get tweets.

In the following declaration: "num_tweets" allows us to know how many tweets we actually want to show or extract.

```python
def get_user_timeline_tweets(self, num_tweets):
```

Now, let's make a function that allows a user to get tweets:
Furthermore, there's a method for every object derived from this API class that has this user timeline functionality and that allows you to specify a user to get the tweets off that user's timeline. We have not specified a user; therefore, it defaults to you and will get tweets from your own timeline. There's a parameter for the cursor object called `.items` that allows you to specify the amount of tweets to receive from the timeline. We go through our timeline(in the default case) and add our tweets to a tweets list.

```python
def get_user_timeline_tweets(self, num_tweets):
tweets = [] //Empty list
for tweet in Cursor(self.twitter_client.user_timeline).items(num_tweets):
tweets.append(tweet)
return tweets
```

> num_tweets allows us to know how many tweets we actually want to show or extract

> The client object that we created here in the in the constructor. There's a method for every object derived from this API class that has this user timeline functionality and that allows you to specify a user to get the tweets off that user's timeline. We have not specified a user; therefore, it defaults to you and will get tweets from your own timeline. There's a parameter for the cursor object called `.items` that allows you to specify the amount of tweets to receive from the timeline.



Now let's test what we have works so far:

Under `if_name _ == '_ main_ '` insert:
Under `if_name _ == '_ main_ '` insert the following lines that will give us a tweet in our timeline.

```python
twitter_client = TwitterClient()
Expand Down
7 changes: 5 additions & 2 deletions Module_Twitter_API/activities/Act3_Cursor and Pagination/5.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class TwitterClient():
def __init__(self, twitter_user=None):
```

Then to specify a user, we need to add `id` in the `get_user_timeline_tweets` function for loop:
Then to specify a user, we need to add `id` in the `get_user_timeline_tweets` function for loop. We go through the specified user's time and add them to a tweet list(which we return).

```python
def get_user_timeline_tweets(self, num_tweets):
Expand All @@ -36,4 +36,7 @@ twitter_client = TwitterClient('pycon')
print(twitter_client.get_user_timeline_tweets(1))
```

If this works properly, you will see the recent tweets from @pycon's timeline showing on the text field.
<img src="https://i.ibb.co/PCmPpRZ/pycon.png" style="zoom: 67%;" />

If this works properly, you will see the recent tweets from @pycon's timeline showing on the text field.

12 changes: 9 additions & 3 deletions Module_Twitter_API/activities/Act3_Cursor and Pagination/6.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,26 @@

# Some other Class Methods for the Cursor class

These two are also some of the class methods we can use for the Cursor class. They are pretty similar to the one we wrote before. We're looping over `twitter_client.friends` in this case instead of the user timeline. Then, we're getting a certain number of friends of that user based on the argument that we passed into the function. The patterns are very similar!

```python
def get_friend_list(self, num_friends):
def get_friend_list(self, num_friends):
friend_list = []
for friend in Cursor(self.twitter_client.friends, id=self.twitter_user).items(num_friends):
friend_list.append(friend)
return friend_list
```

In the following function, we go through a specified user's timeline tweets(that appear on their home page) and return them as a python list.

<img src="C:\Users\ismai\AppData\Roaming\Typora\typora-user-images\image-20200212194243590.png" style="zoom:50%;" />

>An example of what a home timeline looks like can be seen above.

```python
def get_home_timeline_tweets(self, num_tweets):
home_timeline_tweets = []
for tweet in Cursor(self.twitter_client.home_timeline, id=self.twitter_user).items(num_tweets):
home_timeline_tweets.append(tweet)
return home_timeline_tweets
```

> These two are also some of the class methods we can use for the Cursor class. They are pretty similar to the one we wrote before. We're looping over `twitter_client.friends` in this case instead of the user timeline. Then, we're getting a certain number of friends of that user based on the argument that we passed into the function. The patterns are very similar!
22 changes: 20 additions & 2 deletions Module_Twitter_API/activities/Act4_Analyzing tweets/1.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,29 @@
By the end of this activity, we'll be able to stream and analyze tweets from a specific user. We'll be using the tweepy library along with Pandas and Numpy to format our tweet data that we'll be analyzing later. So let's start by setting up Pandas and Numpy.

<h1>Setting up Pandas and Numpy</h1>
Let's start by setting up Pandas and Numpy. If you don't have these installed, you'll have to run the following commands.
Let's start by setting up Pandas🐼 and Numpy🔢.

Pandas is a open-source and free to use python library/package that allows us to analysis and collect our data from various sources much more easily.<sup>1</sup> We will use it to collate and analyse our tweets.

<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/ed/Pandas_logo.svg/1200px-Pandas_logo.svg.png" style="zoom: 25%;" />

Numpy is a free to use python package that allows us to use more complicated and useful mathematical functions in our code.<sup>2</sup> We will be using it for its "Array" type/class, which will allow use to add data that we can manipulate (in a efficient manner) to our Pandas "data frame" or table.

<img src="https://user-images.githubusercontent.com/1217238/65364991-9f0fcb80-dbca-11e9-89a1-f369aa2be57a.png" style="zoom: 50%;" />

If you don't have these installed, you'll have to run the following commands. "pip" installs these third party packages and makes them available to you when you use the import command.

```bash
pip install Pandas
pip install Numpy
```

And then, In order to use Pandas and Numpy in your Python IDE ([Integrated Development Environment](https://en.wikipedia.org/wiki/Integrated_development_environment)), you need to *import* them first as `import pandas as pd ` and `import numpy as np `.
And then, In order to use Pandas and Numpy in your Python IDE ([Integrated Development Environment](https://en.wikipedia.org/wiki/Integrated_development_environment)), you need to *import* them first as `import pandas as pd ` and `import numpy as np `.

***

*Sources / Further Reading Section:*

1) https://towardsdatascience.com/a-quick-introduction-to-the-pandas-python-library-f1b678f34673

2) https://numpy.org/
95 changes: 82 additions & 13 deletions Module_Twitter_API/activities/Act4_Analyzing tweets/2.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,95 @@
<!--title={Getting the Twitter Client API}-->
<!--title={Brief Intro to JSON}-->

<!--badges={Web Development:20}-->
<h1>Brief Intro to JSON</h1>

<h1>Getting the Twitter Client API</h1>
Let's start by getting the twitter api. Firstly, let's setup a function inside our `TwitterClient` class that will return the api. We do so as follows:
We store all our tweets in a *"JSON"* format(this becomes important in the later cards). But what is JSON and why are we using it!
![](https://www.ydop.com/wp-content/uploads/2015/06/json-logo-300x143.png)

JSON stands for **JavaScript Object Notation**. In essence, it is a standardized data writing format based on the way the programming language JavaScript stores its objects.

Think of JSON as a compressed way of writing things like Morse code! It can be decoded and read by programs in such a way that makes it more intuitive to handle data.

But what does "intuitive" mean here? You'll soon find out!

#### Writing and Reading JSON

***

You always start a JSON file with brackets, with each data element seperated by a ```,```:

```python
def get_twitter_client_api(self):
return self.twitter_client
```
{
...,
}
```

Next, let's create a twitter client which we'll use to analyze the tweet data of the user we'll be specifying that we'll be receiving in JSON format. We'll start by removing the existing code inside the main portion of our file and create an object of the `TwitterClient()` class called `twitter_client`.
You then add your data in a key-value format! You can think of the key as a category or type while the value is the actual data. Something like this: `"Key":"Value",` . You can also make lists in your JSON file!

```python
twitter_client = TwitterClient()
```
{
"Name" : "John Smith",
"Age" : 23,
"College" : "UC Redding",
"Favorite Colleges" : ["UC Redding", "UC Santa Rosa" , "UC San Jose"],
}
```

Now let's get the api through the function we just created and store it inside a variable for analyzing in the future.
> Notice we implicitly specify the types of our data above by using ".." for strings and numbers without quotations as integers.


```python
api = twitter_client.get_twitter_client_api()

#### Accessing data

***

Now to the reason why we use JSON: it allows us to interface with our data in a very simple way.

Remember we access an array by giving the index or address of the value we want to access. In JSON we do the same thing but this time we can give it anything as an index(as long as it is a valid key)!

```
{
"Name" : "John Smith",
"Age" : 23,
"College" : "UC Redding",
"Favorite Colleges" : ["UC Redding", "UC Santa Rosa" , "UC San Jose"],
}
```

If we want John's age all we need to do is : load the JSON values into a variable like `John_Data` and make the following access : ` John_Data["Age"]`.

#### Nesting

***

The final topic we will discuss here is nesting - yes you can have JSON in yo' JSON.

![](https://i.chzbgr.com/full/8759438080/hC74C9921/i-heard-you-like-json-so-im-going-to-put-json-inside-json-so-you-can-parse-what-is-parsed)

Here is an example:

```
{
"Fruits":{
"Favorites" : ["Apples","Oranges"],
"Dislike" : ["Banana","Pineapple"]
},
}
```

The way you would access them is quiet similar to what you say above(but with layers this time). You load it into a variable called Food. And access the `Dislike`s like this: `Food["Fruits"]["Dislike"]`



#### Finishing Up

***

Recall that we store our tweet data in groups like by text,source,etc. . So it only makes sense to use a data storage format that complements this: JSON.



***

*Sources / Further Reading Section:*

* https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/JSON
24 changes: 18 additions & 6 deletions Module_Twitter_API/activities/Act4_Analyzing tweets/3.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
<!--title={Streaming our first tweets}-->
<!--title={Getting the Twitter Client API}-->

<!--badges={Web Development:20}-->

<h1>Streaming our first tweets</h1>
So now that we have an api set up, we can start by streaming some tweets. So let's go ahead and create a variable called `tweets` that will store the data we'll be obtaining from the client that we just created. We'll use a inbuilt function, `user_timeline` to stream the tweets. So let's go ahead and specify someone well known as the twitter handle and specify the number of tweets we need.
<h1>Getting the Twitter Client API</h1>
<img src="https://static01.nyt.com/images/2014/08/10/magazine/10wmt/10wmt-superJumbo-v4.jpg" style="zoom: 10%;" />

Let's start by setting up the twitter API. Firstly, let's setup a function inside our `TwitterClient` class that will return the API. Remeber, we are not adding object orientated features to make our life harder, these abstractions or high-level calls and methods will make our code readable and easy to extend or add on to, especiallt when we start with bigger and more complex data sets.This will help us understand what we are doing more clearly later on. We do so as follows:

```python
def get_twitter_client_api(self):
return self.twitter_client
```

Next, let's create a twitter client which we'll use to analyze the tweet data of the user we'll be specifying that we'll be receiving in JSON format(which is just a useful and standardized way to store our data). We'll start by removing the existing code inside the main portion of our file and create an object of the `TwitterClient()` class called `twitter_client`.

```python
tweets = api.user_timeline(screen_name="realDonaldTrump", count=20)
twitter_client = TwitterClient()
```

Now on printing `tweets`, we should get the most recent 20 tweets in JSON format.

<img src="https://i.postimg.cc/XvVSKhTw/Annotation-2020-01-09-214126.png">
Now let's get the API through the function we just created and store it inside a variable for analyzing in the future. With this object we will be able to access the other and fundamental parts of our class (i.e methods that actually modify and manipulate our tweets).

```python
api = twitter_client.get_twitter_client_api()
```
Loading