├── .gitignore
├── README.md
├── Untitled.ipynb
├── css_js.ipynb
├── data_analytics_basics.ipynb
├── enumerate.ipynb
├── exp.ipynb
├── format.ipynb
├── linear.ipynb
├── questions.ipynb
├── range.ipynb
├── reddit_sentiment.ipynb
├── style.css
├── style2.css
├── style3.css
├── supreme_bot
├── .ipynb_checkpoints
│ └── Bot-checkpoint.ipynb
├── Bot.ipynb
├── csrf.png
├── form_data.png
├── form_data_close.png
├── found_element.png
├── header_example.png
├── remove_cart_request_incognito.png
├── request_incognito.png
├── response_incognito.png
└── set_cookie_close.png
└── time.ipynb
/.gitignore:
--------------------------------------------------------------------------------
1 | .ipynb_checkpoints/*
2 | .DS_Store
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RGupyter
2 | Real time experiments with JS/CSS/HTML in JupyterLab with help from IPython
3 |
4 | # Open up any file and explore
5 |
--------------------------------------------------------------------------------
/Untitled.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": []
9 | }
10 | ],
11 | "metadata": {
12 | "kernelspec": {
13 | "display_name": "Python 3",
14 | "language": "python",
15 | "name": "python3"
16 | },
17 | "language_info": {
18 | "codemirror_mode": {
19 | "name": "ipython",
20 | "version": 3
21 | },
22 | "file_extension": ".py",
23 | "mimetype": "text/x-python",
24 | "name": "python",
25 | "nbconvert_exporter": "python",
26 | "pygments_lexer": "ipython3",
27 | "version": "3.6.6"
28 | }
29 | },
30 | "nbformat": 4,
31 | "nbformat_minor": 2
32 | }
33 |
--------------------------------------------------------------------------------
/css_js.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# JS/CSS/HTML with JupyterLab \n",
8 | "# (DON'T RUN CODE UNTIL YOU READ ALL OF MY TEXT)\n",
9 | "\n",
10 | "Real time commit history of my growth \n",
11 | "of applying JS/CSS/HTML inside JupyterLab using tools \n",
12 | "IPython, widgets, and extensions.\n",
13 | "\n",
14 | "Friday, October 19th:\n",
15 | "\n",
16 | "I was playing around with css values and ran into an interesting problem.\n",
17 | "I wanted to use the html in markdown cell with custom styling. I was only having success with over riding the styles of common tag names in my case p and div\n",
18 | "\n",
19 | "I was trying random letters and words like rg to see if I could bind the style from style.css to an uncommon tag name, but none of those alternatives were working, so I stuck with common tag names"
20 | ]
21 | },
22 | {
23 | "cell_type": "markdown",
24 | "metadata": {},
25 | "source": [
26 | "### Contents of style.css \n",
27 | "```css\n",
28 | "```"
40 | ]
41 | },
42 | {
43 | "cell_type": "markdown",
44 | "metadata": {},
45 | "source": [
46 | "The style tags have to appear somewhere to use this file opening HTML() way. \n",
47 | "Either in the .css file or using a string concatenation \n",
48 | "```python\n",
49 | "HTML('')\n",
50 | "```"
51 | ]
52 | },
53 | {
54 | "cell_type": "markdown",
55 | "metadata": {},
56 | "source": [
57 | "### Dependencies"
58 | ]
59 | },
60 | {
61 | "cell_type": "code",
62 | "execution_count": 57,
63 | "metadata": {},
64 | "outputs": [],
65 | "source": [
66 | "from IPython.core.display import HTML\n",
67 | "from jupyter_core.paths import jupyter_config_dir\n",
68 | "import os.path"
69 | ]
70 | },
71 | {
72 | "cell_type": "markdown",
73 | "metadata": {},
74 | "source": [
75 | "## CSS importing"
76 | ]
77 | },
78 | {
79 | "cell_type": "code",
80 | "execution_count": 58,
81 | "metadata": {},
82 | "outputs": [
83 | {
84 | "data": {
85 | "text/html": [
86 | ""
98 | ],
99 | "text/plain": [
100 | ""
101 | ]
102 | },
103 | "execution_count": 58,
104 | "metadata": {},
105 | "output_type": "execute_result"
106 | }
107 | ],
108 | "source": [
109 | "# This allows for my own custom style.css page to take over\n",
110 | "# CSS styling for outputs and markdown\n",
111 | "# CSS rules can affect the notebook top menus – be careful changing and - rules\n",
112 | "style = open('style.css', 'r').read()\n",
113 | "HTML(style)"
114 | ]
115 | },
116 | {
117 | "cell_type": "markdown",
118 | "metadata": {},
119 | "source": [
120 | "# Revert back to normal styling\n",
121 | "So the style is going to get crazy you should just run the block below right after to reset back to standard styling"
122 | ]
123 | },
124 | {
125 | "cell_type": "code",
126 | "execution_count": 55,
127 | "metadata": {},
128 | "outputs": [
129 | {
130 | "data": {
131 | "text/html": [
132 | ""
134 | ],
135 | "text/plain": [
136 | ""
137 | ]
138 | },
139 | "execution_count": 55,
140 | "metadata": {},
141 | "output_type": "execute_result"
142 | }
143 | ],
144 | "source": [
145 | "style = open('style2.css', 'r').read()\n",
146 | "HTML(style)"
147 | ]
148 | },
149 | {
150 | "cell_type": "markdown",
151 | "metadata": {},
152 | "source": [
153 | "# Ok just a little bit of styling now"
154 | ]
155 | },
156 | {
157 | "cell_type": "code",
158 | "execution_count": 56,
159 | "metadata": {},
160 | "outputs": [
161 | {
162 | "data": {
163 | "text/html": [
164 | ""
170 | ],
171 | "text/plain": [
172 | ""
173 | ]
174 | },
175 | "execution_count": 56,
176 | "metadata": {},
177 | "output_type": "execute_result"
178 | }
179 | ],
180 | "source": [
181 | "style = open('style3.css', 'r').read()\n",
182 | "HTML(style)"
183 | ]
184 | },
185 | {
186 | "cell_type": "markdown",
187 | "metadata": {},
188 | "source": [
189 | "ok funny enough I thought I knew how this worked, but all markdown text is already wrapped with a p text so thats why I was getting it to work. I really just picked a random tag to wrap with. So Currently I cannot edit custom tags, but I can edit the tags that Jupyter uses as you saw.\n",
190 | "\n",
191 | "And I also just learned that multiple style sheets can run at the same time!!\n",
192 | "\n",
193 | "But to make any changes after a catastrpohic font size and color change you have to delete the contents of the file and load that same exact file again with the HTML funciton to overwrite the CSS \n",
194 | "```python\n",
195 | "style = open(f'style{x}.css', 'r').read()\n",
196 | "HTML(style)\n",
197 | "```"
198 | ]
199 | },
200 | {
201 | "cell_type": "markdown",
202 | "metadata": {},
203 | "source": [
204 | "It might be useful to turn these 2 lines into a funciton, but I think its fine for now"
205 | ]
206 | },
207 | {
208 | "cell_type": "markdown",
209 | "metadata": {},
210 | "source": [
211 | "# Hello Rudy\n",
212 | "# Run These\n",
213 | "## These are Magicline functions"
214 | ]
215 | },
216 | {
217 | "cell_type": "code",
218 | "execution_count": 60,
219 | "metadata": {},
220 | "outputs": [
221 | {
222 | "data": {
223 | "application/javascript": [
224 | "console.log('hello');"
225 | ],
226 | "text/plain": [
227 | ""
228 | ]
229 | },
230 | "metadata": {},
231 | "output_type": "display_data"
232 | }
233 | ],
234 | "source": [
235 | "%%javascript\n",
236 | "console.log('hello');"
237 | ]
238 | },
239 | {
240 | "cell_type": "markdown",
241 | "metadata": {},
242 | "source": [
243 | "Open your log and the message will be there"
244 | ]
245 | },
246 | {
247 | "cell_type": "code",
248 | "execution_count": null,
249 | "metadata": {},
250 | "outputs": [],
251 | "source": [
252 | "%%javascript\n",
253 | "alert('hello')"
254 | ]
255 | },
256 | {
257 | "cell_type": "markdown",
258 | "metadata": {},
259 | "source": [
260 | "## Just imagine what you can do with these"
261 | ]
262 | },
263 | {
264 | "cell_type": "markdown",
265 | "metadata": {},
266 | "source": [
267 | "# JS importing\n",
268 | "There are similar things going on here"
269 | ]
270 | },
271 | {
272 | "cell_type": "code",
273 | "execution_count": 62,
274 | "metadata": {},
275 | "outputs": [],
276 | "source": [
277 | "def read_js():\n",
278 | " \"\"\"\n",
279 | " Functionality:\n",
280 | " Finds the custom.js file and returns the custom.js file\n",
281 | " \n",
282 | " Output:\n",
283 | " js text\n",
284 | " \n",
285 | " \"\"\"\n",
286 | " jupyter_dir = jupyter_config_dir()\n",
287 | " custom_js_path = os.path.join(jupyter_dir, 'custom', 'custom.js')\n",
288 | " if os.path.isfile(custom_js_path):\n",
289 | " with open(custom_js_path) as f:\n",
290 | " js = f.read()\n",
291 | " else:\n",
292 | " print(\"You don't have a custom.js file\")\n",
293 | " return\n",
294 | " \n",
295 | " return js"
296 | ]
297 | },
298 | {
299 | "cell_type": "code",
300 | "execution_count": 63,
301 | "metadata": {},
302 | "outputs": [
303 | {
304 | "data": {
305 | "text/html": [
306 | ""
307 | ],
308 | "text/plain": [
309 | ""
310 | ]
311 | },
312 | "metadata": {},
313 | "output_type": "display_data"
314 | }
315 | ],
316 | "source": [
317 | "js = read_js()\n",
318 | "display(HTML(js))"
319 | ]
320 | },
321 | {
322 | "cell_type": "markdown",
323 | "metadata": {},
324 | "source": [
325 | "So I got the custom.js alert to call, but I'm not sure how I really have it working"
326 | ]
327 | },
328 | {
329 | "cell_type": "code",
330 | "execution_count": null,
331 | "metadata": {},
332 | "outputs": [],
333 | "source": []
334 | }
335 | ],
336 | "metadata": {
337 | "kernelspec": {
338 | "display_name": "Python 3",
339 | "language": "python",
340 | "name": "python3"
341 | },
342 | "language_info": {
343 | "codemirror_mode": {
344 | "name": "ipython",
345 | "version": 3
346 | },
347 | "file_extension": ".py",
348 | "mimetype": "text/x-python",
349 | "name": "python",
350 | "nbconvert_exporter": "python",
351 | "pygments_lexer": "ipython3",
352 | "version": "3.6.6"
353 | }
354 | },
355 | "nbformat": 4,
356 | "nbformat_minor": 2
357 | }
358 |
--------------------------------------------------------------------------------
/data_analytics_basics.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": []
9 | }
10 | ],
11 | "metadata": {
12 | "kernelspec": {
13 | "display_name": "Python 3",
14 | "language": "python",
15 | "name": "python3"
16 | },
17 | "language_info": {
18 | "codemirror_mode": {
19 | "name": "ipython",
20 | "version": 3
21 | },
22 | "file_extension": ".py",
23 | "mimetype": "text/x-python",
24 | "name": "python",
25 | "nbconvert_exporter": "python",
26 | "pygments_lexer": "ipython3",
27 | "version": "3.6.6"
28 | }
29 | },
30 | "nbformat": 4,
31 | "nbformat_minor": 2
32 | }
33 |
--------------------------------------------------------------------------------
/enumerate.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": []
9 | }
10 | ],
11 | "metadata": {
12 | "kernelspec": {
13 | "display_name": "Python 3",
14 | "language": "python",
15 | "name": "python3"
16 | },
17 | "language_info": {
18 | "codemirror_mode": {
19 | "name": "ipython",
20 | "version": 3
21 | },
22 | "file_extension": ".py",
23 | "mimetype": "text/x-python",
24 | "name": "python",
25 | "nbconvert_exporter": "python",
26 | "pygments_lexer": "ipython3",
27 | "version": "3.6.6"
28 | }
29 | },
30 | "nbformat": 4,
31 | "nbformat_minor": 2
32 | }
33 |
--------------------------------------------------------------------------------
/exp.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# A small experiment with this line of IPython functionality\n",
8 | "```python\n",
9 | "obj?, obj?? : Get help, or more help for object (also works as\n",
10 | " ?obj, ??obj).```"
11 | ]
12 | },
13 | {
14 | "cell_type": "markdown",
15 | "metadata": {},
16 | "source": [
17 | "I am creating this class to test the obj? command\n",
18 | " \n",
19 | "What information will it display?\n",
20 | "* docstring\n",
21 | "* attribute names\n",
22 | "* functions\n",
23 | "* create a custom return funciton"
24 | ]
25 | },
26 | {
27 | "cell_type": "code",
28 | "execution_count": 18,
29 | "metadata": {},
30 | "outputs": [],
31 | "source": [
32 | "class tank:\n",
33 | " \"\"\"Creating a cool tank for test\n",
34 | " \n",
35 | " I like having a tiny little docstring with a lot of space\n",
36 | " \n",
37 | " Maybe some new line spacing. Especially for the last line.\n",
38 | " But, Also sometimes I like there to be no new line. \n",
39 | " My general rule is to include no new line if the last line is indented.\n",
40 | " \n",
41 | " This occurs regularly using my docstring style of\n",
42 | " \n",
43 | " Output:\n",
44 | " list of items\n",
45 | "\n",
46 | " But seeing it printed out by the ?obj function I think I will\n",
47 | " like it better with a new line\n",
48 | " It did make a change, but these lines will stay just like the new line\n",
49 | " \n",
50 | " \"\"\"\n",
51 | " #concludes my docstring rant\n",
52 | " \n",
53 | " def __init__(self, color, people_inside, gun):\n",
54 | " self.color = color\n",
55 | " self.people_inside = people_inside\n",
56 | " self.gun = gun\n",
57 | " \n",
58 | " def __str__():\n",
59 | " return 'we hit the __str__()function'\n",
60 | " "
61 | ]
62 | },
63 | {
64 | "cell_type": "markdown",
65 | "metadata": {},
66 | "source": [
67 | "## Will this work when the class exists, but there is no reference to an instance of it?\n",
68 | "\n",
69 | "### First of all I don't even know if it is\n",
70 | "```python\n",
71 | "obj? tank\n",
72 | "tank obj?\n",
73 | "tank() obj?\n",
74 | "tank() obj??\n",
75 | "?obj\n",
76 | "??obj\n",
77 | "```"
78 | ]
79 | },
80 | {
81 | "cell_type": "code",
82 | "execution_count": 19,
83 | "metadata": {},
84 | "outputs": [
85 | {
86 | "data": {
87 | "text/plain": [
88 | "\u001b[0;31mInit signature:\u001b[0m \u001b[0mtank\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcolor\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpeople_inside\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mgun\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
89 | "\u001b[0;31mDocstring:\u001b[0m \n",
90 | "Creating a cool tank for test\n",
91 | "\n",
92 | "I like having a tiny little docstring with a lot of space\n",
93 | "\n",
94 | "Maybe some new line spacing. Especially for the last line.\n",
95 | "But, Also sometimes I like there to be no new line. \n",
96 | "My general rule is to include no new line if the last line is indented.\n",
97 | "\n",
98 | "This occurs regularly using my docstring style of\n",
99 | "\n",
100 | "Output:\n",
101 | " list of items\n",
102 | "But seeing it printed out by the ?obj function I think I will\n",
103 | "like it better with a new line\n",
104 | "It did make a change, but these lines will stay just like the new line\n",
105 | "\u001b[0;31mType:\u001b[0m type\n"
106 | ]
107 | },
108 | "metadata": {},
109 | "output_type": "display_data"
110 | }
111 | ],
112 | "source": [
113 | "?tank"
114 | ]
115 | },
116 | {
117 | "cell_type": "markdown",
118 | "metadata": {},
119 | "source": [
120 | "This could be really useful when exploring \n",
121 | "a program for the first time in an IPython environment\n",
122 | "\n",
123 | "Super responsive to user inquiry"
124 | ]
125 | },
126 | {
127 | "cell_type": "code",
128 | "execution_count": null,
129 | "metadata": {},
130 | "outputs": [],
131 | "source": []
132 | }
133 | ],
134 | "metadata": {
135 | "kernelspec": {
136 | "display_name": "Python 3",
137 | "language": "python",
138 | "name": "python3"
139 | },
140 | "language_info": {
141 | "codemirror_mode": {
142 | "name": "ipython",
143 | "version": 3
144 | },
145 | "file_extension": ".py",
146 | "mimetype": "text/x-python",
147 | "name": "python",
148 | "nbconvert_exporter": "python",
149 | "pygments_lexer": "ipython3",
150 | "version": "3.6.6"
151 | }
152 | },
153 | "nbformat": 4,
154 | "nbformat_minor": 2
155 | }
156 |
--------------------------------------------------------------------------------
/format.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Exploring advanced functionality of `print()`\n",
8 | "Read these for a comprehensive analysis of the\n",
9 | "1. [The print() documentation in Python](https://docs.python.org/3/library/functions.html#print) \n",
10 | "2. [The Input and Output tutorial by the Python Software Foundation](https://docs.python.org/3/tutorial/inputoutput.html)"
11 | ]
12 | },
13 | {
14 | "cell_type": "markdown",
15 | "metadata": {},
16 | "source": [
17 | "`print(*objects, sep=' ', end='\\n', file=sys.stdout, flush=False*)` \n",
18 | "Print objects to the text stream file, separated by sep and followed by end. sep, end, file and flush, if present, must be given as keyword arguments.\n",
19 | "\n",
20 | "All non-keyword arguments are converted to strings like str() does and written to the stream, separated by sep and followed by end. Both sep and end must be strings; they can also be None, which means to use the default values. If no objects are given, print() will just write end.\n",
21 | "\n",
22 | "The file argument must be an object with a write(string) method; if it is not present or None, sys.stdout will be used. Since printed arguments are converted to text strings, print() cannot be used with binary mode file objects. For these, use file.write(...) instead.\n",
23 | "\n",
24 | "Whether output is buffered is usually determined by file, but if the flush keyword argument is true, the stream is forcibly flushed."
25 | ]
26 | },
27 | {
28 | "cell_type": "markdown",
29 | "metadata": {},
30 | "source": [
31 | "### Important attributes in print()\n",
32 | "The most important attribute I learned about print statement is the `end` attribute \n",
33 | "\n",
34 | "The biggest advantage of using the `end` attribute in the `print()` statement is you don't have to pass new line characters into the print statement as an object\n",
35 | "\n",
36 | "Also I think using `end` looks cleaner, even if people later read your code it"
37 | ]
38 | },
39 | {
40 | "cell_type": "markdown",
41 | "metadata": {},
42 | "source": [
43 | "#### First lets talk about how `print()` and `end` work together\n",
44 | "\n",
45 | "Print objects to the text stream file, separated by sep and followed by end\n",
46 | "\n",
47 | "By default `end = '\\n'`"
48 | ]
49 | },
50 | {
51 | "cell_type": "code",
52 | "execution_count": 1,
53 | "metadata": {},
54 | "outputs": [
55 | {
56 | "name": "stdout",
57 | "output_type": "stream",
58 | "text": [
59 | "top string\n",
60 | "^^^ by default there is always a new line\n"
61 | ]
62 | }
63 | ],
64 | "source": [
65 | "print('top string')\n",
66 | "print('^^^ by default there is always a new line')"
67 | ]
68 | },
69 | {
70 | "cell_type": "markdown",
71 | "metadata": {},
72 | "source": [
73 | "But you already knew thats how it worked \n",
74 | "What if we change `end`?"
75 | ]
76 | },
77 | {
78 | "cell_type": "code",
79 | "execution_count": 2,
80 | "metadata": {},
81 | "outputs": [
82 | {
83 | "name": "stdout",
84 | "output_type": "stream",
85 | "text": [
86 | "What happens if we remove the new line character from end?Run on lines\n"
87 | ]
88 | }
89 | ],
90 | "source": [
91 | "print('What happens if we remove the new line character from end?', end='')\n",
92 | "print('Run on lines')"
93 | ]
94 | },
95 | {
96 | "cell_type": "markdown",
97 | "metadata": {},
98 | "source": [
99 | "I didn't like how the strings just stuck together so let's use a space in `end` now"
100 | ]
101 | },
102 | {
103 | "cell_type": "code",
104 | "execution_count": 3,
105 | "metadata": {},
106 | "outputs": [
107 | {
108 | "name": "stdout",
109 | "output_type": "stream",
110 | "text": [
111 | "What happens if we remove the new line character from end? Run on lines\n"
112 | ]
113 | }
114 | ],
115 | "source": [
116 | "print('What happens if we remove the new line character from end?', end=' ')\n",
117 | "print('Run on lines')"
118 | ]
119 | },
120 | {
121 | "cell_type": "markdown",
122 | "metadata": {},
123 | "source": [
124 | "#### Reasons for using `end`: \n",
125 | "* `end` looks cleaner if you are going to add an extra new line character, but want to avoid using string concatenation\n",
126 | "\n",
127 | "This is more of a style thing up to your discretion when deemed necessary. Even when doing this I was making the argument for using `end` I realized this was a bit extra, but even seeing a new attribute in the `print()` statement may cause users to be more cautious to what is going on and do a little extra research. "
128 | ]
129 | },
130 | {
131 | "cell_type": "code",
132 | "execution_count": 4,
133 | "metadata": {},
134 | "outputs": [
135 | {
136 | "name": "stdout",
137 | "output_type": "stream",
138 | "text": [
139 | "discover\n",
140 | "\n",
141 | "discover\n",
142 | "\n",
143 | "This line is here to see the new line\n"
144 | ]
145 | }
146 | ],
147 | "source": [
148 | "def discover():\n",
149 | " x = 'discover'\n",
150 | " return x\n",
151 | "\n",
152 | "# These work the same way\n",
153 | "print(discover(), end = '\\n\\n')\n",
154 | "print(discover()+'\\n')\n",
155 | "print('This line is here to see the new line')"
156 | ]
157 | },
158 | {
159 | "cell_type": "markdown",
160 | "metadata": {},
161 | "source": [
162 | "* you want to add extra text to the end of each `print()` statement\n",
163 | "\n",
164 | "This could help you out if you want to improve formatting and separation of `print()` statement for an entire program instead of having extra `print()` statements"
165 | ]
166 | },
167 | {
168 | "cell_type": "code",
169 | "execution_count": null,
170 | "metadata": {},
171 | "outputs": [],
172 | "source": [
173 | "line = '-------------------------------------------------------'\n",
174 | "\n",
175 | "# Sneak preview on the useful ness of formatting outside of print()\n",
176 | "for quarter_num in range(1,13):\n",
177 | " print(f'quarter {quarter_num} results: profit', end=f'\\n{line}\\n')"
178 | ]
179 | },
180 | {
181 | "cell_type": "markdown",
182 | "metadata": {},
183 | "source": [
184 | "* you want to remove the newline character from the `print()` statement \n",
185 | "\n",
186 | "Maybe you are doing some art project where you `print()` random numbers with no spaces"
187 | ]
188 | },
189 | {
190 | "cell_type": "code",
191 | "execution_count": null,
192 | "metadata": {},
193 | "outputs": [],
194 | "source": [
195 | "import random\n",
196 | "for i in range(10):\n",
197 | " rand = random.randint(1,10000)\n",
198 | " print(rand, end = '')"
199 | ]
200 | },
201 | {
202 | "cell_type": "markdown",
203 | "metadata": {},
204 | "source": [
205 | "# *Formated string literals* or *f-strings* in Python version 3.6 or greater\n",
206 | "\n",
207 | "[If you want check the feature documentation click here](https://docs.python.org/3/reference/lexical_analysis.html#f-strings)\n",
208 | "\n",
209 | "While making this I found [this link on string formatting](https://realpython.com/python-string-formatting/) that takes my general approach and has this nice graphic on *when* and **why** each type of string formatting should be used. \n",
210 | "\n",
211 | ""
212 | ]
213 | },
214 | {
215 | "cell_type": "markdown",
216 | "metadata": {},
217 | "source": [
218 | "Since the current Python version is 3.7 I will just go over the formated string literals method because it is all I use now.\n",
219 | "\n",
220 | "The basics of f-string is to place an `f` or `F` before either your `''` or `\"\"` in a string with expressions delimited by curly braces `{}`"
221 | ]
222 | },
223 | {
224 | "cell_type": "code",
225 | "execution_count": null,
226 | "metadata": {},
227 | "outputs": [],
228 | "source": [
229 | "name = 'Ryan'\n",
230 | "\n",
231 | "# Same results\n",
232 | "print(f'My name is {name} Glenn')\n",
233 | "print('My name is',name,'Glenn')\n",
234 | "\n",
235 | "# You can handle this string formatting at many different times\n",
236 | "# I would pick the way that looks the best and is logically simple\n",
237 | "pre_formated = f'My name is {name} Glenn'\n",
238 | "print(pre_formated)"
239 | ]
240 | },
241 | {
242 | "cell_type": "markdown",
243 | "metadata": {},
244 | "source": [
245 | "I often use this string formatting inside a `print()` statement to pass in variables\n",
246 | "\n",
247 | "This works well for testing loops to track variables"
248 | ]
249 | },
250 | {
251 | "cell_type": "code",
252 | "execution_count": null,
253 | "metadata": {},
254 | "outputs": [],
255 | "source": [
256 | "for index in range(5):\n",
257 | " print(f'loop itteration {index}')"
258 | ]
259 | },
260 | {
261 | "cell_type": "markdown",
262 | "metadata": {},
263 | "source": [
264 | "You can perform operations inside the curly braces `{}`"
265 | ]
266 | },
267 | {
268 | "cell_type": "code",
269 | "execution_count": null,
270 | "metadata": {},
271 | "outputs": [],
272 | "source": [
273 | "x = 4\n",
274 | "y = 4\n",
275 | "print(f'the operation equals {x+y}')"
276 | ]
277 | },
278 | {
279 | "cell_type": "markdown",
280 | "metadata": {},
281 | "source": [
282 | "## Formatted string literals format_spec"
283 | ]
284 | },
285 | {
286 | "cell_type": "markdown",
287 | "metadata": {},
288 | "source": [
289 | "[Read about the format_spec](https://docs.python.org/3/library/string.html#formatspec)\n",
290 | "\n",
291 | "Created before the new f-string format this can be used in the string to provide improved formatting to numbers\n",
292 | "\n",
293 | "There is a lot of functionality with this, but I will just cover basic int or float formatting to string\n",
294 | "\n",
295 | "The format as seen in below examples is `f'{value:width.precision}'`\n",
296 | "\n",
297 | "where\n",
298 | "\n",
299 | "`value` = float or decimal \n",
300 | "\n",
301 | "`width` = is a decimal integer defining the minimum field width. If not specified, then the field width will be determined by the content.\n",
302 | "\n",
303 | "`precision` = The precision is a decimal number indicating how many digits should be displayed after the decimal point for a floating point value "
304 | ]
305 | },
306 | {
307 | "cell_type": "code",
308 | "execution_count": null,
309 | "metadata": {},
310 | "outputs": [],
311 | "source": [
312 | "import decimal\n",
313 | "\n",
314 | "width = 10\n",
315 | "percision = 1\n",
316 | "\n",
317 | "z = decimal.Decimal(\"1234.34567\")\n",
318 | "z_str = f'{z:{width}.{percision}f}'\n",
319 | "print(z_str)"
320 | ]
321 | },
322 | {
323 | "cell_type": "markdown",
324 | "metadata": {},
325 | "source": [
326 | "This will add commas where called needed"
327 | ]
328 | },
329 | {
330 | "cell_type": "code",
331 | "execution_count": null,
332 | "metadata": {},
333 | "outputs": [],
334 | "source": [
335 | "z = 1005550\n",
336 | "z_str = f'{z:,}'\n",
337 | "print(z_str)"
338 | ]
339 | },
340 | {
341 | "cell_type": "markdown",
342 | "metadata": {},
343 | "source": [
344 | "You can do just precision like this"
345 | ]
346 | },
347 | {
348 | "cell_type": "code",
349 | "execution_count": null,
350 | "metadata": {},
351 | "outputs": [],
352 | "source": [
353 | "z = 12.34524523452452452\n",
354 | "z_str = f'{z:.2f}'\n",
355 | "print(z_str)"
356 | ]
357 | },
358 | {
359 | "cell_type": "markdown",
360 | "metadata": {},
361 | "source": [
362 | "## Thanks for reading!!"
363 | ]
364 | }
365 | ],
366 | "metadata": {
367 | "kernelspec": {
368 | "display_name": "Python 3",
369 | "language": "python",
370 | "name": "python3"
371 | },
372 | "language_info": {
373 | "codemirror_mode": {
374 | "name": "ipython",
375 | "version": 3
376 | },
377 | "file_extension": ".py",
378 | "mimetype": "text/x-python",
379 | "name": "python",
380 | "nbconvert_exporter": "python",
381 | "pygments_lexer": "ipython3",
382 | "version": "3.6.6"
383 | }
384 | },
385 | "nbformat": 4,
386 | "nbformat_minor": 2
387 | }
388 |
--------------------------------------------------------------------------------
/linear.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Basics of Linear Algebra in Python\n",
8 | "## Using numpy and built-in data structures"
9 | ]
10 | },
11 | {
12 | "cell_type": "code",
13 | "execution_count": 1,
14 | "metadata": {},
15 | "outputs": [],
16 | "source": [
17 | "import numpy as np"
18 | ]
19 | },
20 | {
21 | "cell_type": "markdown",
22 | "metadata": {},
23 | "source": [
24 | "vector creation\n",
25 | "matrix creation\n",
26 | "matrix multiplication\n",
27 | "dot product\n",
28 | "broadcasting\n"
29 | ]
30 | },
31 | {
32 | "cell_type": "code",
33 | "execution_count": 6,
34 | "metadata": {},
35 | "outputs": [
36 | {
37 | "data": {
38 | "text/plain": [
39 | "\u001b[0;31mInit signature:\u001b[0m \u001b[0mtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m/\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
40 | "\u001b[0;31mDocstring:\u001b[0m \n",
41 | "type(object_or_name, bases, dict)\n",
42 | "type(object) -> the object's type\n",
43 | "type(name, bases, dict) -> a new type\n",
44 | "\u001b[0;31mType:\u001b[0m type\n"
45 | ]
46 | },
47 | "metadata": {},
48 | "output_type": "display_data"
49 | }
50 | ],
51 | "source": []
52 | },
53 | {
54 | "cell_type": "code",
55 | "execution_count": null,
56 | "metadata": {},
57 | "outputs": [],
58 | "source": []
59 | }
60 | ],
61 | "metadata": {
62 | "kernelspec": {
63 | "display_name": "Python 3",
64 | "language": "python",
65 | "name": "python3"
66 | },
67 | "language_info": {
68 | "codemirror_mode": {
69 | "name": "ipython",
70 | "version": 3
71 | },
72 | "file_extension": ".py",
73 | "mimetype": "text/x-python",
74 | "name": "python",
75 | "nbconvert_exporter": "python",
76 | "pygments_lexer": "ipython3",
77 | "version": "3.6.6"
78 | }
79 | },
80 | "nbformat": 4,
81 | "nbformat_minor": 2
82 | }
83 |
--------------------------------------------------------------------------------
/questions.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Best looping practices?\n",
8 | "## Which is better A or B?\n",
9 | "## Which is better 1 or 2?"
10 | ]
11 | },
12 | {
13 | "cell_type": "code",
14 | "execution_count": 37,
15 | "metadata": {},
16 | "outputs": [
17 | {
18 | "name": "stdout",
19 | "output_type": "stream",
20 | "text": [
21 | "listA1: [1, 1, 1]\n",
22 | "listA2: [1, 1, 1]\n"
23 | ]
24 | }
25 | ],
26 | "source": [
27 | "def functionA(x):\n",
28 | " return x + 1 \n",
29 | " \n",
30 | "listA = [0,0,0]\n",
31 | "listA1 = []\n",
32 | "listA2 = []\n",
33 | "\n",
34 | "# A1\n",
35 | "for x in listA:\n",
36 | " x = functionA(x)\n",
37 | " listA1.append(x)\n",
38 | "# A2\n",
39 | "for x in listA:\n",
40 | " listA2.append(functionA(x))\n",
41 | "\n",
42 | "print(f'listA1: {listA1}\\nlistA2: {listA2}')"
43 | ]
44 | },
45 | {
46 | "cell_type": "code",
47 | "execution_count": 29,
48 | "metadata": {},
49 | "outputs": [
50 | {
51 | "name": "stdout",
52 | "output_type": "stream",
53 | "text": [
54 | "listB1: [1, 1, 1]\n",
55 | "listB2: [1, 1, 1]\n"
56 | ]
57 | }
58 | ],
59 | "source": [
60 | "def functionB1(listB):\n",
61 | " new_listB = []\n",
62 | " for x in listB:\n",
63 | " x += 1\n",
64 | " new_listB.append(x)\n",
65 | " return new_listB\n",
66 | "\n",
67 | "def functionB2(listB):\n",
68 | " new_listB = []\n",
69 | " for x in listB:\n",
70 | " new_listB.append(x+1)\n",
71 | " return new_listB\n",
72 | " \n",
73 | "listB = [0,0,0]\n",
74 | "listB1 = functionB1(listB)\n",
75 | "listB2 = functionB2(listB)\n",
76 | "print(f'listB1: {listB1}\\nlistB2: {listB2}')"
77 | ]
78 | },
79 | {
80 | "cell_type": "markdown",
81 | "metadata": {},
82 | "source": [
83 | "# Best ways to handle list broadcasting\n",
84 | "How do you run a function on a list without passing it in or returning it?"
85 | ]
86 | },
87 | {
88 | "cell_type": "markdown",
89 | "metadata": {},
90 | "source": [
91 | "## Move items from old list, perform action, append to new list\n",
92 | "I think creating a new list to just append to another it is a little extra. \n",
93 | "\n",
94 | "if we are going to do the same action on every item in a list let them stay in the same list"
95 | ]
96 | },
97 | {
98 | "cell_type": "code",
99 | "execution_count": 6,
100 | "metadata": {},
101 | "outputs": [
102 | {
103 | "data": {
104 | "text/plain": [
105 | "[3, 2]"
106 | ]
107 | },
108 | "execution_count": 6,
109 | "metadata": {},
110 | "output_type": "execute_result"
111 | }
112 | ],
113 | "source": [
114 | "# 6 lines\n",
115 | "def function1(list1):\n",
116 | " new_list = []\n",
117 | " for x in list1:\n",
118 | " x += 1\n",
119 | " new_list.append(x)\n",
120 | " return new_list\n",
121 | "\n",
122 | "function1([2,1])"
123 | ]
124 | },
125 | {
126 | "cell_type": "markdown",
127 | "metadata": {},
128 | "source": [
129 | "## Index accessing\n",
130 | "Removes the creation of an extra list and having to appending the updated value"
131 | ]
132 | },
133 | {
134 | "cell_type": "code",
135 | "execution_count": 13,
136 | "metadata": {},
137 | "outputs": [
138 | {
139 | "data": {
140 | "text/plain": [
141 | "[3, 2]"
142 | ]
143 | },
144 | "execution_count": 13,
145 | "metadata": {},
146 | "output_type": "execute_result"
147 | }
148 | ],
149 | "source": [
150 | "# 4 lines\n",
151 | "def funciton2(list2):\n",
152 | " for i, x in enumerate(list2):\n",
153 | " list2[i] = x + 1\n",
154 | " return list2\n",
155 | "\n",
156 | "function2([2,1])"
157 | ]
158 | },
159 | {
160 | "cell_type": "markdown",
161 | "metadata": {},
162 | "source": [
163 | "## lambda map\n",
164 | "This is a short option, but it is very confusing"
165 | ]
166 | },
167 | {
168 | "cell_type": "code",
169 | "execution_count": 20,
170 | "metadata": {},
171 | "outputs": [
172 | {
173 | "name": "stdout",
174 | "output_type": "stream",
175 | "text": [
176 | "[3, 2]\n"
177 | ]
178 | }
179 | ],
180 | "source": [
181 | "# 2 lines\n",
182 | "list3 = [2,1]\n",
183 | "list3 = list(map(lambda x: x + 1, list3))\n",
184 | "\n",
185 | "print(list3)"
186 | ]
187 | },
188 | {
189 | "cell_type": "markdown",
190 | "metadata": {},
191 | "source": [
192 | "## Numpy Broadcasting\n",
193 | "read more about [Broadcasting in Numpy](https://docs.scipy.org/doc/numpy-1.10.0/user/basics.broadcasting.html)"
194 | ]
195 | },
196 | {
197 | "cell_type": "code",
198 | "execution_count": 18,
199 | "metadata": {},
200 | "outputs": [
201 | {
202 | "name": "stdout",
203 | "output_type": "stream",
204 | "text": [
205 | "[3 2]\n",
206 | "[3 2]\n"
207 | ]
208 | }
209 | ],
210 | "source": [
211 | "import numpy as np\n",
212 | "\n",
213 | "def function4(list4):\n",
214 | " list4 = list4 + 1\n",
215 | " return list4\n",
216 | "\n",
217 | "list4 = np.array([2,1])\n",
218 | "list4 = function4(list4)\n",
219 | "print(list4)\n",
220 | "\n",
221 | "# Or better yet\n",
222 | "\n",
223 | "list4 = np.array([2,1]) + 1\n",
224 | "print(list4)"
225 | ]
226 | },
227 | {
228 | "cell_type": "markdown",
229 | "metadata": {},
230 | "source": [
231 | "## Python list comprehension"
232 | ]
233 | },
234 | {
235 | "cell_type": "code",
236 | "execution_count": 23,
237 | "metadata": {},
238 | "outputs": [
239 | {
240 | "data": {
241 | "text/plain": [
242 | "[3, 2]"
243 | ]
244 | },
245 | "execution_count": 23,
246 | "metadata": {},
247 | "output_type": "execute_result"
248 | }
249 | ],
250 | "source": [
251 | "[x+1 for x in [2,1]]"
252 | ]
253 | },
254 | {
255 | "cell_type": "code",
256 | "execution_count": 24,
257 | "metadata": {},
258 | "outputs": [
259 | {
260 | "name": "stdout",
261 | "output_type": "stream",
262 | "text": [
263 | "[3, 2]\n"
264 | ]
265 | }
266 | ],
267 | "source": [
268 | "def function5(x):\n",
269 | " return x + 1\n",
270 | "\n",
271 | "list5 = [function5(x) for x in [2,1]]\n",
272 | "print(list5)"
273 | ]
274 | },
275 | {
276 | "cell_type": "markdown",
277 | "metadata": {},
278 | "source": [
279 | "----\n",
280 | "# Criteria for type of loop\n",
281 | "Obviously most of these examples above over complicates a simple operation on all items in a list, but I did this to cover a wide range of options you have to apply functions to all items of a list. As you can see they all do the same, but which one do you choose?\n",
282 | "\n",
283 | "# For looping, I select the solution that is the most readable\n",
284 | "## while balancing 2 ideas **instant readability** and **long term maintainability**\n",
285 | "\n",
286 | "### Instant readability\n",
287 | "\n",
288 | "#### If someone else reads this code will they: \n",
289 | "Instantly understand its purpose? \n",
290 | "*or* \n",
291 | "Have to spend minutes traversing your code following variables with their fingers? \n",
292 | "\n",
293 | "### Long term maintainability\n",
294 | "\n",
295 | "\n",
296 | "#### If **you** or someone else reads this code in 6 months will they:\n",
297 | "Be able to scroll through the code and get the high level ideas? \n",
298 | "*or* \n",
299 | "Have to spend hours sifting through your complicated, uncommented code reverse engineering the whole project? \n",
300 | "\n",
301 | "\n",
302 | "# What type of programmer do you want to be?\n",
303 | "\n",
304 | "----\n",
305 | "\n",
306 | "Taking some excerpted advice from [Python Enhancement Proposal 20](https://www.python.org/dev/peps/pep-0020/) \n",
307 | "```\n",
308 | "Complex is better than complicated.\n",
309 | "Readability counts.\n",
310 | "If the implementation is hard to explain, it's a bad idea.\n",
311 | "If the implementation is easy to explain, it may be a good idea.\n",
312 | "```\n",
313 | "Bringing that together my philosophy is to write **complex**, **readable**, and **easy to explain code**.\n",
314 | "\n",
315 | "When I am not able to fulfill those principles with python code alone I turn to *commenting*. Relying on commenting just the same way you rely on your `for` loops can bring extra **readability** to code that is not just reiterating what is visible in the code. I will cover more of this in the future, but it is always best practices to make your code as readable and easy to explain as possible without commenting then move to commenting to explain **complex** parts.\n",
316 | "\n",
317 | "\n",
318 | "To help readability I often look at the lengths of my repeatable operations and ask some more questions.\n",
319 | "\n",
320 | "## Many complex operations and function calls? \n",
321 | "Look at creating a function for all that work. Pretend `function()` is a function with 50 lines of code.\n",
322 | "```python\n",
323 | "new_list = []\n",
324 | "for x in listx:\n",
325 | " new_list.append(function(x))\n",
326 | "```\n",
327 | "## Single line operation?\n",
328 | "Tools like list comprehension, broadcasting, and mapping can help reduce the total lines of code from `for` loops and creating temporary\n",
329 | "```python\n",
330 | "squared_list = [x**2 x in listx]\n",
331 | "```\n",
332 | "---"
333 | ]
334 | },
335 | {
336 | "cell_type": "markdown",
337 | "metadata": {},
338 | "source": [
339 | "Every small decision you make in your code is the same as every stroke a painter makes in a painting. \n",
340 | "Make every action deliberate. "
341 | ]
342 | }
343 | ],
344 | "metadata": {
345 | "kernelspec": {
346 | "display_name": "Python 3",
347 | "language": "python",
348 | "name": "python3"
349 | },
350 | "language_info": {
351 | "codemirror_mode": {
352 | "name": "ipython",
353 | "version": 3
354 | },
355 | "file_extension": ".py",
356 | "mimetype": "text/x-python",
357 | "name": "python",
358 | "nbconvert_exporter": "python",
359 | "pygments_lexer": "ipython3",
360 | "version": "3.6.6"
361 | }
362 | },
363 | "nbformat": 4,
364 | "nbformat_minor": 2
365 | }
366 |
--------------------------------------------------------------------------------
/range.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# *class* `range(`*`stop`*`)`\n",
8 | "# *class* `range(`*`stop, stop[, step]`*`)`\n",
9 | "\n",
10 | "## [range() documentation](https://docs.python.org/3/library/stdtypes.html#range)\n",
11 | "\n",
12 | "The **arguments** to the range constructor **must be integers** (either built-in int or any object that implements the index special method). If the **step** argument is omitted, it **defaults to 1.** If the **start** argument is omitted, it **defaults to 0**. If step is zero, ValueError is raised.\n",
13 | "\n",
14 | "For a positive step, the contents of a range r are determined by the formula r[i] = start + step*i where i >= 0 and r[i] < stop.\n",
15 | "\n",
16 | "For a negative step, the contents of the range are still determined by the formula r[i] = start + step*i, but the constraints are i >= 0 and r[i] > stop.\n",
17 | "\n",
18 | "A range object will be empty if r[0] does not meet the value constraint. Ranges do support negative indices, but these are interpreted as indexing from the end of the sequence determined by the positive indices."
19 | ]
20 | },
21 | {
22 | "cell_type": "markdown",
23 | "metadata": {},
24 | "source": [
25 | "---\n",
26 | "## Let's explore *class* `range` using the IPython `obj?` tool\n",
27 | "#### read more about `obj?` in exp.ipynb"
28 | ]
29 | },
30 | {
31 | "cell_type": "markdown",
32 | "metadata": {},
33 | "source": [
34 | "the `range` class is something I keep forgetting is not a function and I think the python developers intended for that\n",
35 | "\n",
36 | "Functionally it is not important to know that `range` is a class and not a function, but `range` is a really simple class and demystifying it can allow you to really utilize the `range` function to its full potential"
37 | ]
38 | },
39 | {
40 | "cell_type": "code",
41 | "execution_count": 18,
42 | "metadata": {},
43 | "outputs": [
44 | {
45 | "name": "stdout",
46 | "output_type": "stream",
47 | "text": [
48 | "\n",
49 | "\n"
50 | ]
51 | }
52 | ],
53 | "source": [
54 | "# I always call classes or functions like this \n",
55 | "# to explore just a little of whats going on\n",
56 | "print(range)\n",
57 | "print(print)"
58 | ]
59 | },
60 | {
61 | "cell_type": "code",
62 | "execution_count": 4,
63 | "metadata": {},
64 | "outputs": [
65 | {
66 | "data": {
67 | "text/plain": [
68 | "\u001b[0;31mInit signature:\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m/\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
69 | "\u001b[0;31mDocstring:\u001b[0m \n",
70 | "range(stop) -> range object\n",
71 | "range(start, stop[, step]) -> range object\n",
72 | "\n",
73 | "Return an object that produces a sequence of integers from start (inclusive)\n",
74 | "to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.\n",
75 | "start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.\n",
76 | "These are exactly the valid indices for a list of 4 elements.\n",
77 | "When step is given, it specifies the increment (or decrement).\n",
78 | "\u001b[0;31mType:\u001b[0m type\n"
79 | ]
80 | },
81 | "metadata": {},
82 | "output_type": "display_data"
83 | }
84 | ],
85 | "source": [
86 | "# We can see more or less the same information from the documentation\n",
87 | "# This is useful because you can always quickly if you forget instead of googling\n",
88 | "range?"
89 | ]
90 | },
91 | {
92 | "cell_type": "markdown",
93 | "metadata": {},
94 | "source": [
95 | "## *class* `range(`*`stop`*`)`\n",
96 | "This is the most common way I use `range` \n",
97 | "\n",
98 | "Best way to think about using this version of the `range` class is when you want to iterate `n` number of times.\n",
99 | "\n",
100 | "Remembering that the the `range` class refers to its parameter as *`stop`* (that it will literally stop at that number) can help you more intuitively program with this function."
101 | ]
102 | },
103 | {
104 | "cell_type": "code",
105 | "execution_count": 13,
106 | "metadata": {},
107 | "outputs": [
108 | {
109 | "name": "stdout",
110 | "output_type": "stream",
111 | "text": [
112 | "range(0, 2)\n"
113 | ]
114 | }
115 | ],
116 | "source": [
117 | "r = range(2)\n",
118 | "print(r)"
119 | ]
120 | },
121 | {
122 | "cell_type": "code",
123 | "execution_count": 20,
124 | "metadata": {},
125 | "outputs": [
126 | {
127 | "data": {
128 | "text/plain": [
129 | "range"
130 | ]
131 | },
132 | "execution_count": 20,
133 | "metadata": {},
134 | "output_type": "execute_result"
135 | }
136 | ],
137 | "source": [
138 | "type(r)"
139 | ]
140 | },
141 | {
142 | "cell_type": "code",
143 | "execution_count": 16,
144 | "metadata": {},
145 | "outputs": [
146 | {
147 | "data": {
148 | "text/plain": [
149 | "\u001b[0;31mType:\u001b[0m range\n",
150 | "\u001b[0;31mString form:\u001b[0m range(0, 2)\n",
151 | "\u001b[0;31mLength:\u001b[0m 2\n",
152 | "\u001b[0;31mDocstring:\u001b[0m \n",
153 | "range(stop) -> range object\n",
154 | "range(start, stop[, step]) -> range object\n",
155 | "\n",
156 | "Return an object that produces a sequence of integers from start (inclusive)\n",
157 | "to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.\n",
158 | "start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.\n",
159 | "These are exactly the valid indices for a list of 4 elements.\n",
160 | "When step is given, it specifies the increment (or decrement).\n"
161 | ]
162 | },
163 | "metadata": {},
164 | "output_type": "display_data"
165 | }
166 | ],
167 | "source": [
168 | "r?"
169 | ]
170 | },
171 | {
172 | "cell_type": "code",
173 | "execution_count": 22,
174 | "metadata": {},
175 | "outputs": [
176 | {
177 | "name": "stdout",
178 | "output_type": "stream",
179 | "text": [
180 | "0\n",
181 | "1\n"
182 | ]
183 | }
184 | ],
185 | "source": [
186 | "for x in r:\n",
187 | " print(x)"
188 | ]
189 | },
190 | {
191 | "cell_type": "code",
192 | "execution_count": 23,
193 | "metadata": {},
194 | "outputs": [
195 | {
196 | "name": "stdout",
197 | "output_type": "stream",
198 | "text": [
199 | "0\n",
200 | "1\n",
201 | "2\n"
202 | ]
203 | }
204 | ],
205 | "source": [
206 | "for x in range(3):\n",
207 | " print(x)"
208 | ]
209 | },
210 | {
211 | "cell_type": "markdown",
212 | "metadata": {},
213 | "source": [
214 | "Usually I will define `range` in the loop, but you can also just reference an already defined variable of range type"
215 | ]
216 | },
217 | {
218 | "cell_type": "markdown",
219 | "metadata": {},
220 | "source": [
221 | "## *class* `range(`*`stop, stop[, step]`*`)`\n",
222 | "\n",
223 | "I use this version of the function when I want a specific range of values. \n",
224 | "\n",
225 | "For me usually the only difference is I want to start at 1 "
226 | ]
227 | },
228 | {
229 | "cell_type": "code",
230 | "execution_count": 30,
231 | "metadata": {},
232 | "outputs": [
233 | {
234 | "name": "stdout",
235 | "output_type": "stream",
236 | "text": [
237 | "valid number\n"
238 | ]
239 | }
240 | ],
241 | "source": [
242 | "user_number = 12\n",
243 | "valid_numbers = range(1,99)\n",
244 | "if user_number in valid_numbers:\n",
245 | " print('valid number')\n",
246 | "else:\n",
247 | " print('invalid number')"
248 | ]
249 | },
250 | {
251 | "cell_type": "markdown",
252 | "metadata": {},
253 | "source": [
254 | "## Converting from `range` to `list`\n",
255 | "As you can see when printing a range it does not show you the full range of numbers in list form, but we can turn it into a list by doing some simple conversion."
256 | ]
257 | },
258 | {
259 | "cell_type": "code",
260 | "execution_count": 27,
261 | "metadata": {},
262 | "outputs": [
263 | {
264 | "name": "stdout",
265 | "output_type": "stream",
266 | "text": [
267 | "[0, 1, 2, 3, 4]\n"
268 | ]
269 | }
270 | ],
271 | "source": [
272 | "r = list(range(5))\n",
273 | "print(r)"
274 | ]
275 | },
276 | {
277 | "cell_type": "code",
278 | "execution_count": 28,
279 | "metadata": {},
280 | "outputs": [
281 | {
282 | "name": "stdout",
283 | "output_type": "stream",
284 | "text": [
285 | "[0, 1, 2, 3, 4]\n"
286 | ]
287 | }
288 | ],
289 | "source": [
290 | "r = range(5)\n",
291 | "r = list(r)\n",
292 | "print(r)"
293 | ]
294 | }
295 | ],
296 | "metadata": {
297 | "kernelspec": {
298 | "display_name": "Python 3",
299 | "language": "python",
300 | "name": "python3"
301 | },
302 | "language_info": {
303 | "codemirror_mode": {
304 | "name": "ipython",
305 | "version": 3
306 | },
307 | "file_extension": ".py",
308 | "mimetype": "text/x-python",
309 | "name": "python",
310 | "nbconvert_exporter": "python",
311 | "pygments_lexer": "ipython3",
312 | "version": "3.6.6"
313 | }
314 | },
315 | "nbformat": 4,
316 | "nbformat_minor": 2
317 | }
318 |
--------------------------------------------------------------------------------
/reddit_sentiment.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Introduction\n",
8 | "This is an idea I had before after completing this [tutorial]( https://www.learndatasci.com/tutorials/sentiment-analysis-reddit-headlines-pythons-nltk/) on sentiment analysis on reddit headlines \n",
9 | "\n",
10 | "[reddit](https://www.reddit.com) is a forum website where people can create subreddits that are communities based on shared interest \n",
11 | "\n",
12 | "Users post a `submission` to a specific `subreddit` where their visibility is controlled by upvotes and downvotes\n",
13 | "\n",
14 | "Each `submission` has a comment sections where users can `comment` and reply to other users comments\n",
15 | "\n",
16 | "I wanted to be able take the average sentiment score of every `comment` in a `submission` for a variety of reasons.\n",
17 | "\n",
18 | "Sometimes `comment` sections get very negative and it would be interesting to alert the user before they enter the `comment` section. Maybe the positivity of a `comment` section would entice a user to read comments to feel better.\n",
19 | "\n",
20 | "While doing this project I realized that I created an engine that could be used for further analysis to pull entire front pages of a `subreddit` and take the average sentiment of all `submissions` and give that subreddit an average `comment` sentiment score"
21 | ]
22 | },
23 | {
24 | "cell_type": "markdown",
25 | "metadata": {},
26 | "source": [
27 | "# Design ideas I had while creating this\n",
28 | "\n",
29 | "In the program I wanted to have this persisting database in the form of a pandas `DataFrame` \n",
30 | "\n",
31 | "The 2 reasons I used the `DataFrame`\n",
32 | "### 1. Easy to perform data analysis on columns \n",
33 | "with functionality like \n",
34 | "`df['label'].mean()` \n",
35 | "it is very easy to find the average sentiment score for a `submission` or `subreddit` \n",
36 | "#### 2. `DataFrame` format can be written into a database easily"
37 | ]
38 | },
39 | {
40 | "cell_type": "markdown",
41 | "metadata": {},
42 | "source": [
43 | "# Imports"
44 | ]
45 | },
46 | {
47 | "cell_type": "code",
48 | "execution_count": 44,
49 | "metadata": {},
50 | "outputs": [],
51 | "source": [
52 | "from IPython import display\n",
53 | "import math\n",
54 | "from pprint import pprint\n",
55 | "import pandas as pd\n",
56 | "import numpy as np\n",
57 | "import nltk\n",
58 | "import matplotlib.pyplot as plt\n",
59 | "import seaborn as sns\n",
60 | "import praw\n",
61 | "sns.set(style='darkgrid', context='talk', palette='Dark2')\n",
62 | "from nltk.sentiment.vader import SentimentIntensityAnalyzer as SIA"
63 | ]
64 | },
65 | {
66 | "cell_type": "markdown",
67 | "metadata": {},
68 | "source": [
69 | "# Instanstiate the Reddit API and SentimentIntensityAnalyzer"
70 | ]
71 | },
72 | {
73 | "cell_type": "code",
74 | "execution_count": 45,
75 | "metadata": {},
76 | "outputs": [],
77 | "source": [
78 | "# Initializes our reddit account api key\n",
79 | "reddit = praw.Reddit(client_id='',\n",
80 | " client_secret='',\n",
81 | " user_agent='')\n",
82 | "# Initializes pretrainded sentiment model\n",
83 | "sia = SIA()"
84 | ]
85 | },
86 | {
87 | "cell_type": "markdown",
88 | "metadata": {},
89 | "source": [
90 | "# Sentiment Analysis Functions()"
91 | ]
92 | },
93 | {
94 | "cell_type": "code",
95 | "execution_count": 46,
96 | "metadata": {},
97 | "outputs": [],
98 | "source": [
99 | "def calculate_subreddits_sentiment(subreddits):\n",
100 | " \"\"\"\n",
101 | " Input:\n",
102 | " list of subreddit names\n",
103 | " \n",
104 | " Output:\n",
105 | " DataFrame with sentiment analysis for all comments from 25 submissions \n",
106 | " on front page of subreddits passed in by user\n",
107 | " \"\"\"\n",
108 | " subreddit_sentiments = pd.DataFrame()\n",
109 | " for subreddit in subreddits:\n",
110 | " print(f'[compare_subreddits] starting {subreddit} sentiment analysis')\n",
111 | " print('--------------------------------------------------------------')\n",
112 | " subreddit_sentiment = calculate_subreddit_sentiment(subreddit)\n",
113 | " subreddit_sentiments = subreddit_sentiments.append(subreddit_sentiment_df, ignore_index=True)\n",
114 | " \n",
115 | " return subreddit_sentiments"
116 | ]
117 | },
118 | {
119 | "cell_type": "code",
120 | "execution_count": 47,
121 | "metadata": {},
122 | "outputs": [],
123 | "source": [
124 | "def calculate_subreddit_sentiment(subreddit):\n",
125 | " \"\"\"\n",
126 | " Input:\n",
127 | " subreddit\n",
128 | "\n",
129 | " Functionality:\n",
130 | " Collects comment sentiment from the 25 submissions on the front page of a subreddit\n",
131 | " \n",
132 | " Ouput:\n",
133 | " Comment sentiments for 25 posts on the front page of user supplied subreddit\n",
134 | " \n",
135 | " \n",
136 | " \"\"\"\n",
137 | " # Create DataFrame that all submission comment sentiments will be appended into\n",
138 | " submission_sentiments = pd.DataFrame()\n",
139 | " for submission in reddit.subreddit(subreddit).hot(limit=25):\n",
140 | " print(f'[{subreddit}_sentiment]: starting submission {submission}')\n",
141 | " submission_sentiment = calculate_submission_comments_sentiment(submission)\n",
142 | " submission_sentiments = submission_sentiments.append(submission_sentiment, ignore_index=True)\n",
143 | " \n",
144 | " print('--------------------------------------------------------------')\n",
145 | " return submission_sentiments"
146 | ]
147 | },
148 | {
149 | "cell_type": "code",
150 | "execution_count": 48,
151 | "metadata": {},
152 | "outputs": [],
153 | "source": [
154 | "def calculate_submission_comments_sentiment(submission):\n",
155 | " \"\"\"\n",
156 | " Input:\n",
157 | " praw.models.submission instance\n",
158 | " https://praw.readthedocs.io/en/latest/code_overview/models/submission.html?highlight=submission\n",
159 | " \n",
160 | " Functionality:\n",
161 | " Takes submission, parses all comments, gives sentiment score for each comment, and places into DataFrame\n",
162 | " \n",
163 | " Output:\n",
164 | " A pandas DataFrame of {comment, compound sentiment score, negitive sentiment, neutral sentiment, posititve sentiment}\n",
165 | " \"\"\"\n",
166 | " comment_sentiments = pd.DataFrame()\n",
167 | " # Extact all comments from post and find sentiment\n",
168 | " # https://praw.readthedocs.io/en/latest/tutorials/comments.html\n",
169 | " submission.comments.replace_more(limit=None)\n",
170 | " for comment in submission.comments.list():\n",
171 | " comment_sentiment = sia.polarity_scores(comment.body)\n",
172 | " comment_sentiment['comment'] = comment.body\n",
173 | " comment_sentiment['post_id'] = submission.id\n",
174 | " comment_sentiment['subreddit'] = submission.subreddit\n",
175 | " comment_sentiments = comment_sentiments.append(comment_sentiment, ignore_index=True)\n",
176 | " \n",
177 | " comment_sentiments = label_df(comment_sentiments)\n",
178 | " return comment_sentiments"
179 | ]
180 | },
181 | {
182 | "cell_type": "code",
183 | "execution_count": 49,
184 | "metadata": {},
185 | "outputs": [],
186 | "source": [
187 | "def label_df(df):\n",
188 | " \"\"\"\n",
189 | " Input:\n",
190 | " Sentiment score DataFrame from submission_comment_sentiment()\n",
191 | " \n",
192 | " Functionality:\n",
193 | " labels DataFrame based on compound sentiment score\n",
194 | " \n",
195 | " 1 = positive\n",
196 | " 0 = neutral\n",
197 | " -1 = negative\n",
198 | " \n",
199 | " Output:\n",
200 | " labeled Dataframe\n",
201 | " \"\"\"\n",
202 | " #set label to 0 for all posts\n",
203 | " df['label'] = 0\n",
204 | " #set label to 1 where compound is > .2\n",
205 | " df.loc[df['compound'] > 0.2, 'label'] = 1\n",
206 | " #set label to -1 where compound is < .2\n",
207 | " df.loc[df['compound'] < -0.2, 'label'] = -1\n",
208 | " return df"
209 | ]
210 | },
211 | {
212 | "cell_type": "markdown",
213 | "metadata": {},
214 | "source": [
215 | "# Run the code \n",
216 | "politics is a place for political discourse which I thought might have a more negative disposition \n",
217 | "aww is a happy place for animal photos"
218 | ]
219 | },
220 | {
221 | "cell_type": "code",
222 | "execution_count": 50,
223 | "metadata": {},
224 | "outputs": [
225 | {
226 | "name": "stdout",
227 | "output_type": "stream",
228 | "text": [
229 | "[compare_subreddits] starting politics sentiment analysis\n",
230 | "--------------------------------------------------------------\n",
231 | "[politics_sentiment]: starting submission b8kf27\n",
232 | "[politics_sentiment]: starting submission b8np4y\n",
233 | "[politics_sentiment]: starting submission b8loqn\n",
234 | "[politics_sentiment]: starting submission b8mouf\n",
235 | "[politics_sentiment]: starting submission b8nskk\n",
236 | "[politics_sentiment]: starting submission b8lyu3\n",
237 | "[politics_sentiment]: starting submission b8l8ov\n",
238 | "[politics_sentiment]: starting submission b8lmlu\n",
239 | "[politics_sentiment]: starting submission b8mvsh\n",
240 | "[politics_sentiment]: starting submission b8k6rt\n",
241 | "[politics_sentiment]: starting submission b8jeum\n",
242 | "[politics_sentiment]: starting submission b8j1dz\n",
243 | "[politics_sentiment]: starting submission b8mbvm\n",
244 | "[politics_sentiment]: starting submission b8kjgh\n",
245 | "[politics_sentiment]: starting submission b8kuj5\n",
246 | "[politics_sentiment]: starting submission b8jtcu\n",
247 | "[politics_sentiment]: starting submission b8n7ze\n",
248 | "[politics_sentiment]: starting submission b8igkb\n",
249 | "[politics_sentiment]: starting submission b8l0uh\n",
250 | "[politics_sentiment]: starting submission b8owmn\n",
251 | "[politics_sentiment]: starting submission b8o5ix\n",
252 | "[politics_sentiment]: starting submission b8ptjd\n",
253 | "[politics_sentiment]: starting submission b8q3d2\n",
254 | "[politics_sentiment]: starting submission b8m7sw\n",
255 | "[politics_sentiment]: starting submission b8ir9l\n",
256 | "--------------------------------------------------------------\n",
257 | "[compare_subreddits] starting aww sentiment analysis\n",
258 | "--------------------------------------------------------------\n",
259 | "[aww_sentiment]: starting submission b64s2b\n",
260 | "[aww_sentiment]: starting submission b8p3b3\n",
261 | "[aww_sentiment]: starting submission b8m1vm\n",
262 | "[aww_sentiment]: starting submission b8l5ka\n",
263 | "[aww_sentiment]: starting submission b8nef4\n",
264 | "[aww_sentiment]: starting submission b8ok2e\n",
265 | "[aww_sentiment]: starting submission b8ljr5\n",
266 | "[aww_sentiment]: starting submission b8nsby\n",
267 | "[aww_sentiment]: starting submission b8ka83\n",
268 | "[aww_sentiment]: starting submission b8nbiu\n",
269 | "[aww_sentiment]: starting submission b8opuk\n",
270 | "[aww_sentiment]: starting submission b8kbrz\n",
271 | "[aww_sentiment]: starting submission b8n0xi\n",
272 | "[aww_sentiment]: starting submission b8jxg2\n",
273 | "[aww_sentiment]: starting submission b8hv0z\n",
274 | "[aww_sentiment]: starting submission b8keg4\n",
275 | "[aww_sentiment]: starting submission b8o38r\n",
276 | "[aww_sentiment]: starting submission b8ht16\n",
277 | "[aww_sentiment]: starting submission b8jbbl\n",
278 | "[aww_sentiment]: starting submission b8k6oa\n",
279 | "[aww_sentiment]: starting submission b8i31u\n",
280 | "[aww_sentiment]: starting submission b8ka21\n",
281 | "[aww_sentiment]: starting submission b8oe3x\n",
282 | "[aww_sentiment]: starting submission b8h9u1\n",
283 | "[aww_sentiment]: starting submission b8iqir\n",
284 | "--------------------------------------------------------------\n"
285 | ]
286 | }
287 | ],
288 | "source": [
289 | "subreddits = ['politics','aww']\n",
290 | "df = compare_subreddits(subreddits)"
291 | ]
292 | },
293 | {
294 | "cell_type": "markdown",
295 | "metadata": {},
296 | "source": [
297 | "# Politics Analysis Results\n",
298 | "The average label and compound scores show that the average comment sentiment tends to be neutral with a slight advantage towards positive"
299 | ]
300 | },
301 | {
302 | "cell_type": "code",
303 | "execution_count": 51,
304 | "metadata": {},
305 | "outputs": [
306 | {
307 | "data": {
308 | "text/plain": [
309 | "0.03785966683493185"
310 | ]
311 | },
312 | "execution_count": 51,
313 | "metadata": {},
314 | "output_type": "execute_result"
315 | }
316 | ],
317 | "source": [
318 | "df[df['subreddit'] == 'politics']['label'].mean()"
319 | ]
320 | },
321 | {
322 | "cell_type": "code",
323 | "execution_count": 52,
324 | "metadata": {},
325 | "outputs": [
326 | {
327 | "data": {
328 | "text/plain": [
329 | "0.016124520444219966"
330 | ]
331 | },
332 | "execution_count": 52,
333 | "metadata": {},
334 | "output_type": "execute_result"
335 | }
336 | ],
337 | "source": [
338 | "df[df['subreddit'] == 'politics']['compound'].mean()"
339 | ]
340 | },
341 | {
342 | "cell_type": "code",
343 | "execution_count": 62,
344 | "metadata": {},
345 | "outputs": [
346 | {
347 | "data": {
348 | "image/png": "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\nFrmJ2b5Gc/gAAAAASUVORK5CYII=\n",
349 | "text/plain": [
350 | ""
351 | ]
352 | },
353 | "metadata": {},
354 | "output_type": "display_data"
355 | }
356 | ],
357 | "source": [
358 | "politics_df = df[df['subreddit'] == 'politics']\n",
359 | "plt.hist(politics_df['compound'])\n",
360 | "plt.xlabel('Sentiment')\n",
361 | "plt.ylabel('Occurance')\n",
362 | "plt.title('Politics Compound Sentiment Score Histogram')\n",
363 | "plt.show()"
364 | ]
365 | },
366 | {
367 | "cell_type": "code",
368 | "execution_count": 63,
369 | "metadata": {},
370 | "outputs": [
371 | {
372 | "data": {
373 | "image/png": "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\n",
374 | "text/plain": [
375 | ""
376 | ]
377 | },
378 | "metadata": {},
379 | "output_type": "display_data"
380 | }
381 | ],
382 | "source": [
383 | "politics_df = df[df['subreddit'] == 'politics']\n",
384 | "plt.hist(politics_df['label'])\n",
385 | "plt.xlabel('Sentiment')\n",
386 | "plt.ylabel('Occurance')\n",
387 | "plt.title('Politics Label Sentiment Score Histogram')\n",
388 | "plt.show()"
389 | ]
390 | },
391 | {
392 | "cell_type": "markdown",
393 | "metadata": {},
394 | "source": [
395 | "# Aww Analysis Results\n",
396 | "The average label and compound scores show that the average comment sentiment tends to be positive"
397 | ]
398 | },
399 | {
400 | "cell_type": "code",
401 | "execution_count": 54,
402 | "metadata": {},
403 | "outputs": [
404 | {
405 | "data": {
406 | "text/plain": [
407 | "0.3431034482758621"
408 | ]
409 | },
410 | "execution_count": 54,
411 | "metadata": {},
412 | "output_type": "execute_result"
413 | }
414 | ],
415 | "source": [
416 | "df[df['subreddit'] == 'aww']['label'].mean()"
417 | ]
418 | },
419 | {
420 | "cell_type": "code",
421 | "execution_count": 55,
422 | "metadata": {},
423 | "outputs": [
424 | {
425 | "data": {
426 | "text/plain": [
427 | "0.22411637931034437"
428 | ]
429 | },
430 | "execution_count": 55,
431 | "metadata": {},
432 | "output_type": "execute_result"
433 | }
434 | ],
435 | "source": [
436 | "df[df['subreddit'] == 'aww']['compound'].mean()"
437 | ]
438 | },
439 | {
440 | "cell_type": "code",
441 | "execution_count": 66,
442 | "metadata": {},
443 | "outputs": [
444 | {
445 | "data": {
446 | "image/png": "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\nllbbVrmMMmQyGbRUKKtaWjKFf+npmLPaY86Ux+1MNfWZrwYtKjUpKSnBjBkzcPbsWWzYsAFmZmYA\nAH19fdy/f1+ar7i4GDo6OtDT06u2DQCMjIyUWqeZmRFkMtWTamqq3PPT/2HOVMecqY45U0195KtR\nFJX8/HyEhITA0NAQmzdvhqmpqdRmbW0NuVwOZ2dnAIBcLkeHDh2ktkuXLknzyuVymJiYPLVHVCk3\n967KPRVTUyPk599FRYVQfsFmjDmrPeZMedzOVFPXfLVubfzENo0XFSEEJk6cCHNzcyQmJkJXV1eh\nPSAgAGvWrEHXrl2ho6ODVatWITAwUGqbO3cufH198fzzzyMhIQH+/v7QUrJSCCFQm2P6FRUC5eXc\ncFXBnKmOOVMdc6aa+siXxovK0aNHcfDgQejp6cHDw0Oabm9vj6SkJIwYMQI5OTkYMmQIHjx4AH9/\nfwQFBQEA+vTpg6tXryIsLAyFhYXo1asXZsyYoamXQkTU7MmEEM22rN+6dUel+bW1ZWjd2hh5eUXc\nG1JSU8+Z6/YYjaz3alBck82ZJjT17ayh1TVfFhYmT2zjZVqIiEhtWFSIiEhtWFSIiEhtWFSIiEht\nWFSIiEhtWFSIiEhtWFSIiEhtWFSIiEhtWFSIiEhtWFSIiEhtWFSIiEhtWFSIiEhtWFSIiEhtWFSI\niEhtWFSIiEhtWFSIiEhtWFSIiEhtWFSIiEhtWFSIiEhtWFSIiEhtNFJUTpw4AW9vb+lxQUEBJkyY\nAHd3d/j4+CAlJUVqKy0tRVRUFDw8PODl5YUVK1ZIbUIIxMfHo2vXrujSpQvmz5+P8vLyBn0tRET0\nfxq0qAghkJqaiuDgYDx48ECaPmfOHBgaGiIzMxMJCQn47LPPcObMGQDAkiVLcP36dWRkZGDTpk1I\nSUnB7t27AQBJSUn45ZdfkJaWhvT0dBw5cgSbNm1qyJdERESPaNCisnLlSqxfvx7h4eHStLt372LX\nrl2YNGkS9PT04OTkhIEDB0q9lbS0NISFhcHExATt27fHyJEjkZycDADYtm0bxowZA0tLS1hYWCAs\nLExqIyKihqfTkCsbPHgwwsPDcfDgQWna33//DR0dHbRt21aaZmVlhR07dqCgoAA5OTmwsbFRaEtK\nSgIAXLp0qUrbhQsXIISATCZ7ajwymQxaKpRVLS2Zwr/0dMxZ7TFnyuN2ppr6zFeDFhVLS8sq0+7d\n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\n",
447 | "text/plain": [
448 | ""
449 | ]
450 | },
451 | "metadata": {},
452 | "output_type": "display_data"
453 | }
454 | ],
455 | "source": [
456 | "aww_df = df[df['subreddit'] == 'aww']\n",
457 | "plt.hist(aww_df['compound'])\n",
458 | "plt.xlabel('Sentiment')\n",
459 | "plt.ylabel('Occurance')\n",
460 | "plt.title('Aww Compound Sentiment Score Histogram')\n",
461 | "plt.show()"
462 | ]
463 | },
464 | {
465 | "cell_type": "code",
466 | "execution_count": 65,
467 | "metadata": {},
468 | "outputs": [
469 | {
470 | "data": {
471 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZUAAAEhCAYAAAC3AD1YAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4xLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvAOZPmwAAIABJREFUeJzt3XdcFFcfLvBnKdIVRb2vGoMIAY2F\nZgsiKLaggDEaewkEBMWWILFH81oiFlQwigW7xoImEstrwWhiiF1jjF3XHgsgRWSp5/7hdW5WhCw4\nsGx4vp8PH905szO/PTvw7JmdohBCCBAREclAT9sFEBHRvwdDhYiIZMNQISIi2TBUiIhINgwVIiKS\nDUOFqAQq6sGSFbWuiox9VjYYKhVEQUEBPDw80LRpU6SkpGitjgkTJqBPnz5vtYydO3fCwcEB2dnZ\nb7UcBwcHfPfdd8XO8+OPP6Jv375wcnKCs7Mz+vTpg7i4uLdab1G2bNmC5cuXS48HDx6Mzz//vEzW\nVRLXrl3DsGHD/nG+X375BUOHDoWLiwscHR3h5+eH1atXIy8vrxyqLLkTJ07AwcEBN2/efGN727Zt\nER0drdG8rzt9+jTCw8Nlq5X+PwNtF0AvnThxApmZmbCyssKuXbvg7++v7ZIqvM2bN2P27NkIDAzE\nyJEjIYRAYmIipk6dikePHmHkyJGyrm/FihXo1q2b9HjatGkwNDSUdR2lsX//fly6dKnYeY4ePYqQ\nkBD0798fAQEBMDQ0xNmzZ7F48WJcv34d33zzTTlVWzaaNGmCrVu34p133tFo/ri4ONy9e7eMq6qc\nGCoVRHx8PFq2bIl69eph586dDBUNrFq1CoMHD8bYsWOlaR4eHsjLy8OqVaswbNgwVKlSpczWb2dn\nV2bLltuqVavQuXNnfPXVV9I0Nzc3mJmZISIiAqNHj0adOnW0WOHbMTc3h5OTk7bLIHD3V4WQnZ2N\nAwcOoF27dujWrRuuXbuGCxcuAADWrl0LZ2dntV0UPXr0QNeuXaXHBQUFaN26NVavXg0HBwf8/vvv\nUtusWbPg4OCAJ0+eSNNCQ0Pfauj/6NEjhIeHw83NDU2aNIGXlxeWLVtWaL6EhAR06tQJjo6OCA4O\nxr1799Taf/rpJ3z00Udo1qwZOnbsiE2bNpWojpSUlDfuF+/fvz9Gjhyp1mfnzp1D//790bx5c7Rr\n1w7R0dEoKCiQ2r28vLB27VpMmjQJrq6uaNWqFWbMmIHc3Fyp/cGDB1i5ciW8vLwAqO/+erX75dSp\nU+jZsyeaNWuGjz/+GNeuXcP+/fvRpUsXuLi4YMyYMXj+/Lm03oyMDEydOhWtW7eGk5MTQkJC8ODB\nA6k9Ojoa/fv3x86dO9GpUyc0a9YMAwcOxI0bN6T2JUuWICkpCQ4ODjhx4kSJ+qp79+744osvoK+v\nL027ePEiPv30Uzg7O6Ndu3aIiIhATk6O1P7bb7+hX79+Uvu8efPU2r28vLBw4UL07NkTrVq1wu7d\nuzV6D97G67u/njx5glGjRqF169ZwdnaGv78/Ll++DODlLt7vv/8ev//+OxwcHHD//n0AwJ9//gl/\nf3+0aNECbdq0wdSpU5GRkaG2nnXr1sHLywuOjo4IDQ3FmjVrpO3h/v37cHBwwPr16+Hh4QEPDw/c\nuXMHOTk5iIyMRKdOndC0aVO0adMGEyZMkLaDV887fPgwBg4ciObNm8Pb2xsnTpzAqVOn4OvrCycn\nJwQEBKj9HldUDJUKICEhAVlZWfjwww/h4uKCd955Bzt27AAAuLu748WLF9LujfT0dFy7dg23b9+W\nvnu5dOkSUlNT4e3tjZo1a+LkyZPSsk+fPg0AOHv2LAAgPz8fJ0+eRLt27UpVa0FBAQIDA3H79m3M\nmDEDK1euhJubGxYtWoRff/1Vbd6vv/4aw4YNw4IFC3D37l0EBQUhPz8fAPDzzz9jxIgReP/997F0\n6VL07NkTs2bNKlGwtG3bFuvXr8fEiRNx9OhR6ZfU1tYWgYGBMDU1BQBcuXIFQ4cOhaWlJaKjoxEU\nFITY2FjMmzdPbXmv9s9HR0dj8ODB2LhxI7Zv3w4AWLJkCWrVqoUePXpgyZIlRdb05ZdfYtCgQYiK\nikJycjKGDx+O6OhohIeHY8yYMThw4ADWr18v9WVwcDCOHj2KiRMnYv78+Xj69CmGDBmCzMxMaZnX\nrl1DbGwswsLCsHDhQty+fRsTJ04EAHzyySfo3bs3LC0tsXXrVjRp0qTIvjpw4ABGjRqF/fv349mz\nZwCA2rVrY9iwYahduzaAl3/gBg8eDACIjIzE2LFjsX37dixYsAAAcPjwYfj7+8Pa2hpRUVEIDAzE\n5s2bC31IWbVqFbp164ZZs2ahZcuWGr8Hb1JQUIC8vLxCP8WZOHEiHjx4gDlz5iAqKgpZWVkYNmwY\n8vLyMGLECHh6euK9997D1q1bUbt2bVy8eBH9+vWDoaEh5s+fj7CwMCQkJKhts5s3b0ZERAQ++ugj\nREdHQ19fH5GRkYXW/e2332LKlCn44osvYG1tjVmzZiEuLg6hoaGIjY1FYGAgdu/ejZUrV6o9b9Kk\nSejSpQuWLl0KQ0NDhIWFYcqUKQgKCsL06dOl3ZUVniCtCw4OFp999pn0ODIyUri6ugqVSiWEEMLD\nw0OsXLlSCCHE4cOHRYcOHYSrq6s4ePCgEEKI5cuXCx8fHyGEEGFhYSIoKEgIIURGRoZo1KiR8PPz\nE7NmzRJCCHHu3Dnh4OAgkpOT31jL+PHjxSeffFJkrQ8ePBCDBg0SN2/elKYVFBSIFi1aiMWLFwsh\nhNixY4ewt7cXu3fvlua5ceOGcHBwEPv37xdCCNGrVy8REBCgtuyFCxeK1q1bi5ycHCGEEPb29mLz\n5s1F1pKcnCwCAgKEvb29sLe3F40bNxb9+vUT27ZtE/n5+dJ8o0ePFt26dRN5eXnStG3btokmTZqI\npKQkIYQQHTp0KPS6P/nkExEcHCw97tChg5g3b570eNCgQWLs2LFCCCGOHz8u7O3txYYNG6T26Oho\nYW9vL06dOiVN+/TTT0VISIgQQogjR44Ie3t7ce7cOak9LS1NODs7izVr1gghhIiKihL29vbixo0b\n0jybN28W9vb2IiUlRZrHzc2tyH4SQoisrCwRFhYmHBwchL29vXBwcBAfffSRWL16tcjOzpbmmzVr\nlmjbtq3atPXr14t+/foJIYTo0aOH+PTTT9WW/f333wt7e3tx6dKlIvtSk/fgda/6tLifqKgotXlf\n9ZOjo6OIiYmRlqVUKsX8+fNFWlqaEKLwdj5ixAjRtWtXtfpOnTol7O3tpd+zdu3aiRkzZkjtBQUF\nwtfXV3To0EEIIcS9e/eEvb292jYihBCjRo0S8fHxatNCQkLEwIED1Z43Z84cqX3nzp3C3t5e/PDD\nD9K0yZMnC19f3zf2VUXCkYqWPXv2DMeOHUPHjh2Rnp6O9PR0dOjQARkZGThw4ACAl58yT506BQA4\ndeoUWrZsiSZNmkijj8TERLi7uwN4ObI5c+YM8vPzcebMGfznP/9Bly5d1OZt0qQJatSoUap669at\niw0bNsDa2hq3bt1CQkIClixZgry8PGlX0SudOnWS/m9ra4t3330Xf/zxB168eIGLFy9K33+8+nF3\nd8ezZ89w/fp1jWqpUaMGYmNjsWfPHoSFhaFly5a4ePEipkyZgpCQEOkT5qlTp9C2bVsIIaR1tWvX\nDrm5uVK/AEDz5s3Vll+nTh28ePGiRP3z92VYWVkBgNrowdLSUhpRnTx5EpaWlmjatKlUl6mpKZyc\nnNR2Y5mZmcHW1lZ6XLduXQBAVlaWxnUZGxtj/vz5OHToECZNmgQPDw/cvn0bc+bMQb9+/aTXee7c\nOXzwwQdq30UNHjwY3333HTIzM3HlyhV8+OGHasvu1q0bFAoFzpw5I037e72A5u/Bm0RFRSEuLq7Q\nj6WlZZHPcXZ2RnR0NMLCwrBnzx7UrFkTYWFhqFq16hvnP3PmDLp06aK2G7BFixaoVasWzpw5g9u3\nb+Px48fo2LGj1K5QKNClS5dCy3r9u7aoqCj4+vrir7/+wq+//oq1a9fi5s2bhX5fSrLtVGT8ol7L\n9u7di9zcXEyfPh3Tp09Xa9uxYwd8fX3h7u6Or776Cvn5+Th16hT69OmDv/76C4mJiVCpVDh79iyC\ng4MBvAyVzMxMXLp0CSdPnoSrqytcXV2xdOlSZGVlITExsdS7vl7ZunUrFi5ciGfPnqFOnTpwdXWF\ngYGB2j57c3NzGBkZqT2vevXqePLkCdLT0yGEwOzZszF79uxCy3/69GmJ6rGzs4OdnR2GDRuGjIwM\nLFiwAN999x1++ukndOrUCampqVi3bh3WrVtX6Ll/30dtbGys1qanp1ficxnMzMwKTTMxMXnjvKmp\nqUhNTX3jLqtmzZoV+XyFQgEApfo+4p133sHQoUMxdOhQZGdnY9WqVYiKisL27dsxdOhQpKWlFfmB\nIyMjA0II6Q/eK1WqVIG5ubnaH7zX59H0PXgTOzu7QiEFAAYGRf/5WrhwIZYsWYK9e/di9+7dMDIy\ngr+/P8aOHSv139+lp6cXqvnV63j+/Lm0u7B69epq7TVr1iz0nNf77/Tp05g2bRpu3LghfYgwNjYu\ntG29adt5fZvUBQwVLYuPj0fr1q0RGhqqNj0hIQHr16/HgwcP4ObmhszMTJw9exaXLl2Ci4sLHj9+\njJUrVyIxMRH6+vpwdXUF8HIjf/WF8ZkzZ9CjRw84OTlBoVDg+PHjOH/+/FudW3Hy5ElMmzYNYWFh\n6NOnD6pVqwbg5ZFEf/fixQvk5eWp/eInJyfDyckJ5ubmAIAvvvii0PMAwNra+h/r+N///odp06bh\nwIEDUg0AYGFhgalTp2LXrl1QKpXSNB8fH3z00UeFlvPqU782VK1aFfXq1XvjfvKigqg0zp8/j+HD\nh2PNmjVo1KiRNN3IyAihoaHYvXu31Ffm5ubSH9BXnj17hitXrqBp06ZQKBRITk5Wa8/OzkZGRoba\n+/C68n4PLC0tMWXKFEyePBl//PEHduzYgZiYGLz33nvw8fEpNH/VqlULvS7g5TZbrVo16Tun188h\n+6dzyjIyMjB8+HC4u7tjxYoVqFevHgBg7NixePjwYWlfXoXG3V9adPfuXZw/fx4ff/wxWrdurfbz\n6pDi77//Xvp0Exsbi6pVq8LW1hZOTk4oKCjA8uXL0bp1a7XdFe7u7jh27Bj+/PNPtGjRAsbGxmja\ntCliYmJgYmLyVodenj9/HkZGRggKCpL+iFy5cgXJyclqn5wLCgpw/Phx6fGVK1dw7949tGjRAubm\n5rC3t8eDBw/QrFkz6SclJQXR0dEanTRpa2uL1NTUN54c+ejRI6hUKmk3hLOzM27fvq22LgMDAyxa\ntOiNf0iKoqcn76+Ls7Mznjx5AisrK6mupk2bYs2aNYUOenibuqytrZGZmfnGgyCeP3+O5ORkqa+c\nnJzw22+/qR3NtWfPHowYMQJGRkZwcHDA//73P7Vl7Nu3T3o9xb1WOd4DTWRkZMDLywsHDx6EQqFA\n8+bNMX36dJiYmODRo0cACveZi4sLDhw4IO0yBV6OMJ4+fQonJyfUqVMHdevWxeHDh9Wed+TIkWJr\nuXXrFtLT0+Hv7y8Fyqu9C3Id+VbRcKSiRfHx8TA0NJQOSfy7OnXqwMXFBTt37kRoaCjc3d2xdOlS\ndO7cGQBgamqK999/H+fPn1c79wB4GSqrVq2CpaWl9MfC1dUVq1atQteuXdX2G79JUlIS1q5dW2h6\nx44d0axZM6hUKkRERKBDhw64ffs2lixZAoVCobaP38DAQBrR6OnpYf78+WjSpAk6dOgAABg5ciQ+\n//xzmJmZwcPDA/fv35fmqVWr1j/23XvvvYf+/ftj0aJFUCqV6Ny5MywtLXHjxg2sXLkSLVq0gKen\nJwAgJCQEAwcOxMSJE9GtWzekpaVh4cKFMDExgY2NzT+u65WqVavi999/x/nz52U5J6JDhw547733\nEBgYiBEjRqBGjRrYunUrDh06hP79+5eorrS0NBw5cgTOzs6FRgzVq1fHqFGjMH/+fCQlJcHPzw+1\natXC/fv3sWbNGtSqVQs9e/YEAAwdOhTff/89RowYgcGDB+PJkyeIiorCoEGDUKVKFYwaNQojR47E\n+PHj4ePjA6VSiUWLFqFz585qo6DXyfUeaMLCwgI2NjaYPXs2srKyULt2bezduxd5eXlo37691Gd3\n797Fb7/9BmdnZ4SEhGDAgAEYPnw4Bg4ciKSkJCxcuBDNmjVD+/btoaenh5CQEHz99deoVq0anJ2d\nsXv3bvzxxx/FjrRsbGxgamqKxYsX47PPPkNGRgZWr16NJ0+ewMLCQtbXXVEwVLToxx9/xAcffFDk\nl4c+Pj74+uuvcfz4cSlUXu3mAl5+kXjhwoVC35G4urrC1NQUzs7O0v7jli1bYtWqVRp9n/LgwYM3\nnmFtbW2NDh06IDw8HBs2bMDmzZtRt25dDBkyBDdv3lQ7P8bExARffPEF5s6di9TUVHh6emLatGnS\n7rCuXbsiMjISy5Ytw4YNG2BpaSmdM6GpadOmoUmTJti5cycmTJgAlUqFevXqwc/PD8HBwdKnUScn\nJ8TGxmLRokUIDQ2FmZkZ3N3dER4eXqIz4gMDAzF9+nQEBQXht99+0/h5RTE0NJQOq50xYways7Nh\nb2+PZcuWoWXLlhovp1u3btixYwdGjhyJiIgIdO/evdA8QUFBsLa2xubNmzF9+nRkZmaiVq1a6Nix\nI0aNGiXtz7e2tsa6desQERGBUaNGoUaNGhgyZAhCQkIAvDz44tW5MXv27IGVlRUGDRr0j1cvkOs9\n0NTcuXMRERGBiIgIpKen47333sPSpUulD1l9+vTBoUOHMGzYMKxbtw4uLi5Ys2YNFixYgJEjR8LC\nwgKdO3fGuHHjpG22b9++SEtLw8aNG7Fy5Up4enpiwIABaofwv65q1apYvHgx5s2bh5CQEFhZWaFd\nu3bw8/PD7NmzkZqaKvtr1zaFKOk3kUREldCPP/4IFxcXaTcWAISFhUGlUuHbb7/VYmUVC0cqREQa\n2LZtG1avXo3Q0FBYWFjg+PHj2LdvH2JiYrRdWoXCkQoRkQYePXqEOXPm4Pjx43jx4gVsbW0REhKi\ndskkYqgQEZGMeEgxERHJhqFCRESyqdRf1D99mvHPM72BQqGAlZUZkpMzeUtSDbC/Sob9VXLss5J5\n2/6qVavoc2zKdaRy+vRpfPLJJ3B1dUWnTp2wZcsWAEBaWhpCQ0Ph6uqK9u3bS5cbB4CcnBxMmjQJ\nrVq1gpubm9p9O4QQWLBgAdq0aYOWLVti5syZamfElhU9vZdviswnWP9rsb9Khv1VcuyzkinL/iq3\nkUpaWhpGjBiBKVOmwMfHB5cvX4a/vz/effddbNmyBaampkhMTMTVq1cRFBSEZs2aoVGjRli4cCEe\nPnyIhIQEJCcnIyAgAA4ODvDy8sKmTZtw5MgRxMfHQ6FQIDg4GJs3b5buB0FEROWr3HL94cOH8PT0\nhJ+fH/T09NCkSRO0bt0aZ8+exaFDhzB69GgYGRmhefPm8PHxkUYr8fHxCA4OhoWFBRo0aIBBgwZh\n27ZtAIBdu3Zh6NChqF27NmrVqoXg4GCpjYiIyl+5jVQaN26sdpe3tLQ0nD59Gg4ODjAwMED9+vWl\nNhsbGxw4cABpaWlISkpSuz+BjY2NdGG8W7duFWq7ceMGhBBvvLz160o7/NPTU6j9S8Vjf5UM+6vk\n2GclU5b9pZUv6jMyMhASEiKNVl7dXvUVY2NjqFQq6QKFf78M+Ks24OVNiv5+vwETExMUFBQgJyen\n0L083sTKykyj8CmKpWXh+x9Q0dhfJcP+Kjn2WcmURX+Ve6jcu3cPISEhqF+/PhYtWoSbN29KIfGK\nSqWCqampFBgqlUq6B8erNuBlwPz9MulZWVkwMDDQKFAAIDk5s9QjFUtLM6SmZqKggEea/BP2V8mw\nv0qOfVYyb9tfNWqYF9lWrqHy559/IjAwEH5+fhg/fjz09PRgbW2NvLw8PHz4ULqEtFKphJ2dHSwt\nLWFlZQWlUindYU2pVEp3gbO1tYVSqYSjo6PU1rBhQ43rEULgbQ4WKygQyM/nBqwp9lfJsL9Kjn1W\nMmXRX+X2RX1SUhICAwPh7++PiRMnSpclNzc3R8eOHbFgwQJkZWXhwoUL2L17N3x9fQEAfn5+iI6O\nRmpqKm7fvo2NGzeiR48eUltsbCwePXqEpKQkLF++XGojIqLyV24jlbi4OKSkpGDZsmVq55oMGTIE\nM2bMwLRp0+Dp6QlTU1OEh4dLo4+xY8di9uzZ8Pb2hkKhwJAhQ+Dt7Q0AGDBgAJKSktC7d2/k5ubC\n19dXumMiERGVv0p9QcnSnlGvr69AjRrmSEl5zqG2BthfJcP+Kjn2Wcm8bX8Vd0Z9pb5MCxGRNjnv\nnqW1dd/3n1Mmy+VFDYiISDYMFSIikg1DhYiIZMNQISIi2TBUiIhINgwVIiKSDUOFiIhkw1AhIiLZ\nMFSIiEg2DBUiIpINQ4WIiGTDUCEiItkwVIiISDYMFSIikg1DhYiIZMNQISIi2TBUiIhINgwVIiKS\nDUOFiIhkw1AhIiLZMFSIiEg2DBUiIpINQ4WIiGTDUCEiItkwVIiISDYMFSIikg1DhYiIZMNQISIi\n2TBUiIhINgwVIiKSDUOFiIhkw1AhIiLZMFSIiEg2DBUiIpINQ4WIiGTDUCEiItkwVIiISDYMFSIi\nkg1DhYiIZMNQISIi2TBUiIhINgbaLoCICntnzQStrfucz2StrZt0n1ZGKhcuXIC7u7va48aNG8PZ\n2Vn6iYmJAQAIIbBgwQK0adMGLVu2xMyZM5Gfny89d+3atWjXrh1cXFwwbtw4vHjxotxfDxERvVSu\noSKEQFxcHAICApCbmytNv3LlCjw8PHDu3DnpJyQkBACwadMmHDlyBPHx8di7dy/Onj2LzZs3AwB+\n+uknxMbGYv369Th69CjS0tIQFRVVni+JiIj+plxDJSYmBuvXr5cC45VLly6hUaNGb3zOrl27MHTo\nUNSuXRu1atVCcHAwtm3bJrX17t0bNjY2sLCwwJgxYxAXF6c2kiEiovJTrt+p9OrVCyEhITh58qTa\n9MuXL6NKlSrw8vJCQUEBvL298fnnn6NKlSq4desW7OzspHltbGxw48YNCCFw69YtdO7cWa0tIyMD\njx8/Rt26df+xHoVCAb1SxKqenkLtXyoe+6tktN1P+vq69z5xGyudsuivcg2V2rVrv3F69erV0bp1\na/Tt2xfJyckYM2YMoqKiMG7cOGRlZcHY2Fia18TEBAUFBcjJyXljGwBkZWVpVI+VlRkUitJ3qqWl\nWamfWxmxv3RDjRrm2i6h1LiNlUxZ9FeFOPrr1ZfyAGBqaorg4GBERkZi3LhxMDY2RnZ2ttSelZUF\nAwMDGBkZvbENAMzMNOuo5OTMUo9ULC3NkJqaiYICUfIFVDLsr5LR9qftlJTnWl1/aXAbK53S9ldx\nHzy0HippaWmIiYlBaGgozM1fFpqdnQ0jIyMAgK2tLZRKJRwdHQEASqUSDRs2lNpu3bolLUupVMLC\nwqLIEdHrhBB4m69fCgoE8vO5AWuK/aUbdPk94jZWMmXRX1o/+dHCwgIHDx7EkiVLkJubizt37iAm\nJgYff/wxAMDPzw+xsbF49OgRkpKSsHz5cvTo0UNq27p1K65fv47nz58jKioKvr6+0CvN8IOIiN6a\n1kcqenp6iImJwcyZM9GmTRsYGxujb9++GDp0KABgwIABSEpKQu/evZGbmwtfX1/4+/sDALy8vHD/\n/n0EBwcjPT0dnp6e+PLLL7X5coiIKjWFEKLSjhWfPs0o1fP09RWoUcMcKSnPOdTWAPurZPT1FWi+\na6bW1q+LZ9Tr6jbmvHuW1tZ9339OqfurVi2LItu4n4iIiGTDUCEiItkwVIiISDYMFSIikg1DhYiI\nZMNQISIi2TBUiIhINgwVIiKSDUOFiIhkw1AhIiLZMFSIiEg2DBUiIpJNiUPl8ePHOH78OFQqFZKS\nksqiJiIi0lEah8qLFy/w+eefw9PTEwEBAXj69Cm++uorDBgwACkpKWVZIxER6QiNQ2XevHl49OgR\n9u3bJ92VMSwsDNnZ2Zg9e3aZFUhERLpD41BJSEjAxIkTYWNjI02ztbXF119/jV9++aVMiiMiIt2i\ncag8f/5cuoe82gL09JCXlydrUUREpJs0DhV3d3fExMQgPz9fmvbs2TPMmzcPbdu2LZPiiIhIt2gc\nKlOmTMHt27fxwQcfQKVSITAwEO3bt0daWhomT9a9248SEZH8DDSdsXbt2ti2bRuOHz+OmzdvIi8v\nD7a2tmjbti0UCkVZ1khERDpC41ABgP3796NKlSoYOHAgAGDq1KlQqVTo1KlTmRRHRES6RePdX2vW\nrMGECROQmpoqTatatSrGjx+PLVu2lElxRESkWzQOlQ0bNiAyMhI9e/aUpoWHhyMiIgKxsbFlUhwR\nEekWjUPl2bNnsLa2LjTdzs4OT548kbUoIiLSTRqHiqOjI2JjY9UOKRZCYP369Xj//ffLpDgiItIt\nGn9RP2HCBHz66ac4duwYGjduDAC4evUqcnJysGLFijIrkIiIdIfGodKoUSPs27cPe/fuxc2bN2Fo\naAhPT0/4+vq+8Ux7IiKqfEp0SHH16tWlw4mJiIhep3Go3L17F/Pnz8fFixeRm5sLIYRa+7Fjx2Qv\njoiIdIvGofLVV1/h8ePH8Pf35+4uIiJ6I41D5cKFC1i/fj2aNm1alvUQEZEO0/iQ4tq1ayMnJ6cs\nayEiIh2n8UglLCwMX3/9NUaOHAlra2sYGhqqtf/95l1ERFQ5aRwqo0aNUvsXABQKBYQQUCgUuHz5\nsvzVERGRTtE4VBISEsqyDiIi+hfQOFTq1atXZNu9e/dkKYaIiHSbxqFy/fp1zJkzBzdu3FC7/ldO\nTg4yMjK4+4uIiDQ/+mvatGnIzMzEyJEjkZ6ejuHDh8PPzw/Z2dmYM2dOWdZIREQ6QuORyp9//onv\nvvsO77//Pnbs2AFbW1sMHDgQ9evXR1xcHHr06FGWdRIRkQ7QeKSip6eHatWqAXh5+PCVK1cAAB4e\nHrh69WrZVEdERDpF41Bp2rTP68neAAAXBUlEQVQptm3bBgBo3LgxfvnlFwDArVu3oKen8WKIiOhf\nTOPdX+PGjcOwYcNQrVo19OrVCytXrkSXLl3w9OlT9OrVqyxrJCIiHaFxqDg4OODw4cPIyspCtWrV\nsHPnThw4cADVq1eHt7d3WdZIREQ6QuP9Vr6+vrh79y5q1qwJAKhVqxYGDhyIbt26QaFQlGilFy5c\ngLu7u/Q4LS0NoaGhcHV1Rfv27bF9+3apLScnB5MmTUKrVq3g5uaGZcuWSW1CCCxYsABt2rRBy5Yt\nMXPmTLXDnYmIqHxpHCq5ublvvTIhBOLi4hAQEKC2vKlTp8LU1BSJiYmIiorC/PnzpQMBFi5ciIcP\nHyIhIQGbN2/G9u3bcfjwYQDApk2bcOTIEcTHx2Pv3r04e/YsNm/e/NZ1EhFR6Wi8+8vHxwcBAQHo\n3r076tevD2NjY7X2vn37/uMyYmJisG/fPoSEhGDlypUAgMzMTBw6dAj79++HkZERmjdvDh8fH2zf\nvh1Tp05FfHw85s+fDwsLC1hYWGDQoEHYtm0bvLy8sGvXLgwdOhS1a9cGAAQHB2PJkiUYPHhwSfqA\niIhkonGo7N27FyYmJtIo4e8UCoVGodKrVy+EhITg5MmT0rQ7d+7AwMAA9evXl6bZ2NjgwIEDSEtL\nQ1JSEuzs7NTaNm3aBODlkWevt924cUO6yCUREZUvjUPlTWFSUq9GFH/34sWLQqMeY2NjqFQqZGVl\nAQBMTEwKtQFAVlaW2nNNTExQUFCAnJwcGBkZ/WM9CoUCpTkaWk9PofYvFY/9VTLa7id9fd17n7iN\nlU5Z9JfGoXLq1Kli21u2bFmqAkxMTKSQeEWlUsHU1FQKDJVKJd3C+FUb8DJgsrOzpedlZWXBwMBA\no0ABACsrs7ca0VhampX6uZUR+0s31Kihu7cL5zZWMmXRXxqHSlHfUxgaGqJatWo4duxYqQqwtrZG\nXl4eHj58iLp16wIAlEol7OzsYGlpCSsrKyiVSumoM6VSCVtbWwCAra0tlEolHB0dpbaGDRtqvO7k\n5MxSj1QsLc2QmpqJggJR8gVUMuyvktH2p+2UlOdaXX9pcBsrndL2V3EfPEp0j/q/y8vLw927dzF7\n9myNvk8pirm5OTp27IgFCxZg5syZuH79Onbv3o0VK1YAAPz8/BAdHY2oqCikpqZi48aNCA8Pl9pi\nY2PRpk0bGBgYYPny5SW6BpkQAm9zBHJBgUB+PjdgTbG/dIMuv0fcxkqmLPpL41CpUqVKoceNGjXC\npEmTMGLECHTv3r3URcyYMQPTpk2Dp6cnTE1NER4eLo0+xo4di9mzZ8Pb2xsKhQJDhgyRTrYcMGAA\nkpKS0Lt3b+Tm5sLX1xf+/v6lroOIiN6OQgjxVjF19uxZfPbZZzh37pxcNZWbp08zSvU8fX0FatQw\nR0rKc34q0gD7q2T09RVovmum1tZ/zmey1tZdWrq6jTnvnqW1dd/3n1Pq/qpVy6LINo1HKpGRkYWm\nZWRkYPfu3WjXrl2JiyIion8fjUPl9ZGIQqGAoaEhBg4ciICAANkLIyIi3aNxqGzYsKHQtOfPn0uH\n+hIREWl8QG1KSgpCQkIQFRUlTfvwww8RGhqKtLS0MimOiIh0i8ahMn36dDx//lztKK/Y2Fikp6dj\n1iztfdlEREQVh8a7vxITE7F161bpxEPg5T1WpkyZgiFDhpRJcUREpFs0HqkYGRkhJSWl0PTMzExZ\nCyIiIt2lcah069YNU6ZMwS+//IJnz57h2bNnSExMxLRp0/Dhhx+WZY1ERKQjNN79FR4ejvT0dAwf\nPly6u6Kenh569+6NCRMmlFmBRESkO0p0mZaIiAhMnToVSqUShoaGqF+/PszMeFVQIiJ6SeNQUalU\nmDdvHurXr49PP/0UwMtdYu7u7hg3blyha4MREVHlo/F3KjNmzMDx48fRrFkzaVp4eDgSExMxd+7c\nMimOiIh0i8ahkpCQgHnz5sHV1VWa1qFDB8yePRt79+4tk+KIiEi3aBwqL+89UvjmI4aGhmp3XyQi\nospL41Bp3749ZsyYgVu3bknT7ty5g1mzZsHT07NMiiMiIt2icahMnjwZRkZG6N69O5ydneHs7Iyu\nXbvC2NgYU6ZMKcsaiYhIR2h89Nfjx4/h5+eHtm3bQl9fH8bGxnBzc1O7bAsREVVu/xgqSqUSkyZN\nwrlz52BsbAxzc3M8e/YMBQUFcHR0xJw5c9CgQYNyKJWIiCq6Ynd/PX78GIMHD4aFhQW2b9+O8+fP\n49ixY/j999+xZcsWmJqaYtCgQXjy5El51UtERBVYsaGybNkyNGnSBCtWrFA7P8XAwACOjo5YvXo1\nHB0dsWzZsjIvlIiIKr5iQ+Xnn39GUFBQsQsIDAzEkSNH5KyJiIh0VLGhkpSUhHr16hW7gP/85z94\n9uyZrEUREZFuKjZU6tSpgytXrhS7gCtXrvxj8BARUeVQbKh4e3tj4cKFePHixRvbMzIyEBkZCT8/\nvzIpjoiIdEuxoRIcHAwDAwP07NkTmzZtwsWLF3Hv3j2cOXMGa9euhbe3NywsLODv719e9RIRUQVW\n7HkqJiYm2LRpE6KiorBo0SJkZGRAoVBACAFLS0v06dMHoaGhvOw9EREB0ODkRxMTE4wfPx7h4eFQ\nKpVIS0tDtWrV0KBBA+jr65dHjUREpCM0vkyLnp4eL8lCRETF0viCkkRERP+EoUJERLJhqBARkWwY\nKkREJBuGChERyYahQkREsmGoEBGRbBgqREQkG4YKERHJhqFCRESyYagQEZFsGCpERCQbhgoREclG\n46sUk7p31kzQ2rrP+UzW2rqJiIrDkQoREcmmwoTKqlWr0LRpUzg7O0s/p0+fRlpaGkJDQ+Hq6or2\n7dtj+/bt0nNycnIwadIktGrVCm5ubli2bJkWXwEREVWY3V+XL1/G559/js8++0xt+ujRo2FqaorE\nxERcvXoVQUFBaNasGRo1aoSFCxfi4cOHSEhIQHJyMgICAuDg4AAvLy8tvQoiosqtwoxULl++jMaN\nG6tNy8zMxKFDhzB69GgYGRmhefPm8PHxkUYr8fHxCA4OhoWFBRo0aIBBgwZh27Zt2iifiIhQQUIl\nKysLt2/fxvr169G2bVt4e3sjLi4Od+7cgYGBAerXry/Na2Njg+vXryMtLQ1JSUmws7Mr1EZERNpR\nIXZ/JSUlwcXFBf3790dUVBQuXLiAkJAQ+Pv7w9jYWG1eY2NjqFQqZGVlAQBMTEwKtWlKoVBArxSx\nqqenKPmTZKSvr931l9Sr/tJ2v+kKbfeTrm1fALex0iqL/qoQoVK/fn1s3LhRetyiRQv06NEDp0+f\nLhQSKpUKpqamUtioVCqYm5urtWnKysoMCoXubYQ1aphru4RSsbQ003YJpAFd3b4AbmMlVRb9VSFC\n5c8//8Svv/6KYcOGSdOys7NRp04d5OXl4eHDh6hbty4AQKlUws7ODpaWlrCysoJSqUTNmjWlNltb\nW43Xm5ycqZMjlZSU51pdf0np6SlgaWmG1NRMFBQIbZdT4XH7KjluY6VT2v4q7oNHhQgVU1NTLFmy\nBO+++y66dOmCEydOYM+ePdi4cSMyMjKwYMECzJw5E9evX8fu3buxYsUKAICfnx+io6MRFRWF1NRU\nbNy4EeHh4RqvVwiB/PyyelVlJz9fN39pCgqEztZemejye8RtrGTKor8qxBf1NjY2WLRoEb799lu4\nuLhg+vTp+Oabb9CkSRPMmDEDeXl58PT0xOjRoxEeHg5HR0cAwNixY9GgQQN4e3tjwIAB6NOnD7y9\nvbX8aoiIKq8KMVIBAC8vrzeeX2JpaYnFixe/8TnGxsb473//i//+979lXR4REWmgQoxUiIjo34Gh\nQkREsmGoEBGRbBgqREQkG4YKERHJhqFCRESyYagQEZFsGCpERCQbhgoREcmGoUJERLJhqBARkWwY\nKkREJBuGChERyYahQkREsmGoEBGRbBgqREQkG4YKERHJhqFCRESyYagQEZFsGCpERCQbhgoREcmG\noUJERLJhqBARkWwYKkREJBuGChERyYahQkREsmGoEBGRbBgqREQkG4YKERHJhqFCRESyYagQEZFs\nGCpERCQbhgoREcmGoUJERLJhqBARkWwYKkREJBuGChERyYahQkREsmGoEBGRbBgqREQkG4YKERHJ\nhqFCRESyYagQEZFsdD5ULl26hN69e8PJyQk9evTA+fPntV0SEVGlpdOhkp2djZCQEHz88cc4deoU\nBg8ejJEjRyInJ0fbpRERVUo6HSrHjx+Hnp4eBgwYAENDQ/Tu3RvVq1fHTz/9pO3SiIgqJZ0OFaVS\nCVtbW7VpNjY2uH79upYqIiKq3Ay0XcDbePHiBUxMTNSmGRsbQ6VSafR8hUIBvVLEqp6eouRPkpG+\nvnbXX1Kv+kvb/aYrtN1PurZ9AdzGSqss+kunQ8XExKRQgKhUKpiammr0/Jo1zUu97vv+c0r93MrK\n0tJM2yXoDG5fpaNr25i23+ey6C+d3v3VsGFDKJVKtWlKpRJ2dnZaqoiIqHLT6VD54IMPkJOTgw0b\nNiA3NxdxcXFISkqCu7u7tksjIqqUFEIIoe0i3saVK1cwffp0XL16FdbW1pg+fTqcnJy0XRYRUaWk\n86FCREQVh07v/iIiooqFoUJERLJhqBARkWwYKkREJBuGSgnNnDkTERERRbbn5ORg0qRJaNWqFdzc\n3LBs2bJyrK7iWLt2Ldq1awcXFxeMGzcOL168eON8Fy5cQOPGjeHs7Cz9xMTElHO12qHpFbY17ct/\nO037q3v37nB0dJS2p+7du5dzpRXLhQsXij3NYvfu3ejYsSOcnZ0RHByMpKSkt1uhII2kpKSI8ePH\nC3t7ezFnzpwi55szZ44YOnSoSE9PF0qlUnTo0EEkJCSUY6Xad/jwYeHu7i5u3bol0tPTRWBgoPjm\nm2/eOO/WrVvFsGHDyrlC7VOpVKJdu3Zi06ZNIicnR2zfvl20bdtWZGdnq81Xkr78N9O0v7KyskTj\nxo1FcnKyliqtOAoKCsT27duFq6uraNWq1RvnuXz5snBxcRHnz58XWVlZYtKkSWLkyJFvtV6OVDQ0\nYMAA6Ovro2vXrsXOFx8fj+DgYFhYWKBBgwYYNGgQtm3bVk5VVgy7du1C7969YWNjAwsLC4wZMwZx\ncXHIz88vNO+lS5fQqFEjLVSpXZpeYbskfflvpml/Xbt2DTVr1kSNGjW0VGnFERMTg/Xr1yMkJKTI\neX788Ud07NgRjo6OMDY2xrhx45CQkIDk5ORSr5eh8v/k5eUhPT290M/z588BvNwFMWvWrGKvK5aW\nloakpCS1y8T8W6+aXFx/3bp1q1AfZGRk4PHjx4WWc/nyZZw9exZeXl5o3749IiIiKsX9cDS9wnZJ\n+vLfTNP+unTpEgwMDNC3b1+0adMGAQEBuHnzZnmWWmH06tULu3btQrNmzYqc5/Xtq3r16rCwsMCt\nW7dKvV6dvqCknE6ePAl/f/9C0+vVq4fDhw/j//yf//OPy8jKygIAtSsnl+SqybqkuP7S19eHsbGx\nNO1Vf7zqn7+rXr06Wrdujb59+yI5ORljxoxBVFQUxo0bV3bFVwCaXmE7KytL4778NyvJFcmbNWuG\n8PBw1KxZE0uXLkVQUBD27t2r1o+VQe3atf9xnte3L+DlNvY22xdD5f9xc3PD1atX32oZr94clUoF\nc3Nz6f+aXjVZlxTXX76+vsjOzpYev9pAzcwKXxH171/Km5qaIjg4GJGRkf/6UNH0CtvGxsYa9+W/\nmab91a9fP/Tr1096/Pnnn2PTpk24fPkynJ2dy6VWXVLUB5m3+ZvF3V8ysrS0hJWVldqVk980bP+3\ns7W1VRs+K5VKWFhYFPrklJaWhoiICGkXI/DyFtFGRkblVqu2aHqFbU378t9O0/7aunUrEhMTpcf5\n+fnIy8urFNtUadja2qr1a0pKCtLS0t7qbxZDRWZ+fn6Ijo5Gamoqbt++jY0bN6JHjx7aLqtc+fn5\nYevWrbh+/TqeP3+OqKgo+Pr6Qu+1O6JZWFjg4MGDWLJkCXJzc3Hnzh3ExMTg448/1lLl5UfTK2xr\n2pf/dpr215MnTzBr1iz89ddfUKlUmDNnDho2bFgpDwbRhI+PDw4cOIDTp08jOzsbkZGR8PDwQPXq\n1Uu/0Lc6dqwSGj9+fKFDip2cnMSpU6eEEC8PaZw6dapo06aN+OCDD8SyZcu0UabWrVu3TnTo0EG4\nurqKL774Qrx48UIIIcSDBw+Ek5OTePDggRBCiOvXr4uhQ4cKFxcX4ebmJhYvXiwKCgq0WXq5uXz5\nsujbt69wcnISPXr0EOfOnRNCCPHZZ5+pbTdF9WVlo0l/5eTkiNmzZ4u2bdsKJycnERQUJG1rldXx\n48fVDimeOnWqmDp1qvR4z549okuXLsLZ2VkEBQWJpKSkt1ofr1JMRESyqVxjaCIiKlMMFSIikg1D\nhYiIZMNQISIi2TBUiIhINgwVIiKSDUOFqBh5eXmIiYlB165d0bRpU7i5ueHLL7/EgwcPZFl+ZmYm\n4uLipMeDBw/G/PnzZVn229ZCVBo8T4WoGHPnzkVCQgImT56Mhg0bIikpCdHR0VAqldizZ0+hixyW\n1JIlS/Dzzz9Lt0dITU2FoaGhVq7t9XotRKXBkQpRMXbs2IHRo0fDw8MD77zzDpycnLB48WI8efIE\nR48efevlv/6ZztLSUmsXi+TnS5IDr1JMVAyFQoHExER07doVBgYvf13Mzc3x448/olatWgBeBs/y\n5cvx+PFj2NnZISwsDG5ubgCACRMmwMzMDBkZGTh48CCqV6+Ovn37Ijg4GDt37sSSJUsAAA4ODrh6\n9SoGDx4MR0dHjBs3DtHR0bh58ybq1q2LLVu2wNTUFGFhYahevTpmzZqF5ORkdOzYEd98841Um5y1\nEJUGRypExfD390dcXBzat2+PiRMn4ocffkBKSgpsbGxgbm6Oo0ePYu7cuQgLC0N8fDx69OiB4OBg\ntT/KW7duRf369bFz50707t0bkZGRuHLlCrp164aAgAA0adIEx44de+P6Dx06hLy8PPzwww/o2rUr\npk+fjqVLl2LhwoWYN28e9u3bhwMHDgBAmddCpAmGClExgoODsWjRIjRs2BDx8fEYP348PDw8EBER\nASEEVqxYgaCgIHTt2hXW1tYYMmQIunTpgvXr10vLaNCgAUaNGgUbGxuMGDEClpaWuHjxIoyNjWFq\nagoDAwNp1PM6MzMzjB8/Hu+++y769+8PlUqF4cOHo2nTpujYsSMaN26MGzduAECZ10KkCe7+IvoH\n3t7e8Pb2xvPnz3H8+HH88MMPWL16NerUqYMbN27gwoUL+Pbbb6X5c3Nz0bx5c+lxgwYN1JZnZmaG\nvLw8jdb96k6awP+/CVz9+vWldmNjY+n2y2VdC5EmGCpERbhy5Qq2bduGr776CsDL71I6deqETp06\nYcSIEfj111+Rn5+PL7/8Eh4eHmrPrVKlivR/Q0PDQsvW9EvxV9+V/J1CoXjjvGVdC5EmuPuLqAgF\nBQXYtGkTTp48WajN3NwcNWrUgK2tLR4+fAhra2vpZ8eOHTh48KBG6ygqIEqjItVClRdDhagI77//\nPjp37oyxY8di+/btuHv3Li5duoQVK1bg4MGDGDJkCAIDA7Fp0yZs27YNd+/exdq1a7Fy5cpCu5mK\nYmpqiqSkJNy7d++t661ItVDlxVAhKkZkZCQGDBiAtWvXwtfXFwMHDsSJEyewdu1aNG7cGJ07d8bk\nyZOxatUqdOvWDVu3bsXcuXML7YIqSpcuXWBgYAAfHx88ffr0rWqtSLVQ5cUz6omISDYcqRARkWwY\nKkREJBuGChERyYahQkREsmGoEBGRbBgqREQkG4YKERHJhqFCRESyYagQEZFs/i+j9JxIWS5CKQAA\nAABJRU5ErkJggg==\n",
472 | "text/plain": [
473 | ""
474 | ]
475 | },
476 | "metadata": {},
477 | "output_type": "display_data"
478 | }
479 | ],
480 | "source": [
481 | "plt.hist(aww_df['label'])\n",
482 | "plt.xlabel('Sentiment')\n",
483 | "plt.ylabel('Occurance')\n",
484 | "plt.title('Aww Label Sentiment Score Histogram')\n",
485 | "plt.show()"
486 | ]
487 | },
488 | {
489 | "cell_type": "markdown",
490 | "metadata": {},
491 | "source": [
492 | "# How can this be used?\n",
493 | "### 1. Display sentiment score for each post as a browser addon \n",
494 | "This allows users to see sentiment before they go into the comment section and gives them a better idea of the mood and discourse \n",
495 | "### 2. Display sentiment score for each subreddit at the top as a browser addon\n",
496 | "### 3. Perform large scale analysis on sentiment across subreddits \n",
497 | " \n",
498 | "Overall all the functions have been made modularly and can be applied to the ideas I have set forward, but can also be used in the creation of new analysis later"
499 | ]
500 | }
501 | ],
502 | "metadata": {
503 | "kernelspec": {
504 | "display_name": "Python 3",
505 | "language": "python",
506 | "name": "python3"
507 | },
508 | "language_info": {
509 | "codemirror_mode": {
510 | "name": "ipython",
511 | "version": 3
512 | },
513 | "file_extension": ".py",
514 | "mimetype": "text/x-python",
515 | "name": "python",
516 | "nbconvert_exporter": "python",
517 | "pygments_lexer": "ipython3",
518 | "version": "3.6.8"
519 | }
520 | },
521 | "nbformat": 4,
522 | "nbformat_minor": 2
523 | }
524 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/style2.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/style3.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/supreme_bot/.ipynb_checkpoints/Bot-checkpoint.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# How to make a Supreme Bot"
8 | ]
9 | },
10 | {
11 | "cell_type": "markdown",
12 | "metadata": {},
13 | "source": [
14 | "2 main things to understand\n",
15 | "* session-user-cart-item relationships\n",
16 | "* How to use HTTP post requests and bypass the HTTPOnly system using headers"
17 | ]
18 | },
19 | {
20 | "cell_type": "markdown",
21 | "metadata": {},
22 | "source": [
23 | "---\n",
24 | "# session-user-cart-item relationships\n",
25 | "___"
26 | ]
27 | },
28 | {
29 | "cell_type": "markdown",
30 | "metadata": {},
31 | "source": [
32 | "## Session\n",
33 | "First thing to do is create a new session"
34 | ]
35 | },
36 | {
37 | "cell_type": "code",
38 | "execution_count": 2,
39 | "metadata": {},
40 | "outputs": [],
41 | "source": [
42 | "import requests\n",
43 | "session = requests.Session()"
44 | ]
45 | },
46 | {
47 | "cell_type": "markdown",
48 | "metadata": {},
49 | "source": [
50 | "An important thing to inspect and change is the session headers \n",
51 | "I have not found any reason to believe they are able to check this, but its best you change the `User-Agent` field"
52 | ]
53 | },
54 | {
55 | "cell_type": "code",
56 | "execution_count": 3,
57 | "metadata": {},
58 | "outputs": [
59 | {
60 | "data": {
61 | "text/plain": [
62 | "{'User-Agent': 'python-requests/2.14.2', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}"
63 | ]
64 | },
65 | "execution_count": 3,
66 | "metadata": {},
67 | "output_type": "execute_result"
68 | }
69 | ],
70 | "source": [
71 | "session.headers"
72 | ]
73 | },
74 | {
75 | "cell_type": "code",
76 | "execution_count": 4,
77 | "metadata": {},
78 | "outputs": [],
79 | "source": [
80 | "session.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:64.0) Gecko/20100101 Firefox/64.0'"
81 | ]
82 | },
83 | {
84 | "cell_type": "code",
85 | "execution_count": 5,
86 | "metadata": {},
87 | "outputs": [
88 | {
89 | "data": {
90 | "text/plain": [
91 | "{'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}"
92 | ]
93 | },
94 | "execution_count": 5,
95 | "metadata": {},
96 | "output_type": "execute_result"
97 | }
98 | ],
99 | "source": [
100 | "session.headers"
101 | ]
102 | },
103 | {
104 | "cell_type": "markdown",
105 | "metadata": {},
106 | "source": [
107 | "## User\n",
108 | "Each user will have their own session \n",
109 | "Each user will have their own cart \n",
110 | "It is import to tie all of these together by consistently using the same session for all GET and POST requests "
111 | ]
112 | },
113 | {
114 | "cell_type": "markdown",
115 | "metadata": {},
116 | "source": [
117 | "## Adding items to cart"
118 | ]
119 | },
120 | {
121 | "cell_type": "markdown",
122 | "metadata": {},
123 | "source": [
124 | "You will need to use the the `add` endpoint example like this https://www.supremenewyork.com/shop/{item_code}/add \n",
125 | "With form data and proper headers \n",
126 | "Its all about replicating what your browser is doing as much as possible\n",
127 | " \n",
128 | "\n",
129 | "How to find the {item_code}? \n",
130 | "Have a look around on an item page by finding where the {item_code} from the url exists on the webpage "
131 | ]
132 | },
133 | {
134 | "cell_type": "markdown",
135 | "metadata": {},
136 | "source": [
137 | "## How to use the Network tab to solve this problem\n",
138 | "The process will be this throughout the project. \n",
139 | "\n",
140 | "1. You need to inspect the headers and form data to see what is being passed. \n",
141 | "
\n",
142 | "2. You need to find where that data exists on the web page \n",
143 | "(See how I took the st value from the form data and search where it was in the webpage)\n",
144 | "
\n",
145 | "3. Create functions to scrape that data from the webpage\n",
146 | "4. Replicate those request header and form data packets with your POST request\n",
147 | "
\n",
148 | "
\n",
149 | "5. Read response headers to see how you performed and continue logically off that \n",
150 | "(Specifically the 'set-cookie' from add to cart and 'queued' from checkout)\n",
151 | "
"
152 | ]
153 | },
154 | {
155 | "cell_type": "markdown",
156 | "metadata": {},
157 | "source": [
158 | "---\n",
159 | "# How to beat HTTPOnly\n",
160 | "---\n",
161 | "From a high level there are several things you need to nail down that interweave with \n",
162 | " \n",
163 | "* Request Headers\n",
164 | " * X-CSRF code\n",
165 | " * cookie\n",
166 | " * cart\n",
167 | " * pure_cart\n",
168 | " * \\_supreme_sess\n",
169 | "* Response Headers\n",
170 | " * Taking the cookie returned and placing it into the next post request\n",
171 | "* Checkout form data\n",
172 | " * Solving a captcha and placing that into the form data for each checkout"
173 | ]
174 | },
175 | {
176 | "cell_type": "markdown",
177 | "metadata": {},
178 | "source": [
179 | "## X-CSRF Code\n",
180 | "I think this is why you need to use the same session across all of the GET and POST requests \n",
181 | "so you get the proper X-CSRF code into the header. \n",
182 | " \n",
183 | "Just scrape this from the item page you want to add to cart and your checkout page \n",
184 | " \n",
185 | "
"
186 | ]
187 | },
188 | {
189 | "cell_type": "markdown",
190 | "metadata": {},
191 | "source": [
192 | "## Cookie parts\n",
193 | "There a a couple of parts of the cookie that need to be separately created then assembled\n",
194 | "* \\_supreme_sess\n",
195 | "* cart\n",
196 | "* pure_cart\n",
197 | "* request_method\n",
198 | "\n",
199 | "cart and pure_cart are encoded. Use https://www.urldecoder.org/ to start figuring out what's going on and reverse engineer it. \n",
200 | "\n",
201 | "request_method seems to be the HTTP request you made. I just hardcode it Post because why would your bot be deleting anything. \n",
202 | "\n",
203 | "pure_cart is finicky I would suggest including it but it doesnt always return in the response headers and isn't needed in the request headers. I would 100% put it in the POST checkout. \n",
204 | "\n",
205 | "Throw all of these in one cookie named`['set-cookie']` separated by commas\n"
206 | ]
207 | },
208 | {
209 | "cell_type": "markdown",
210 | "metadata": {},
211 | "source": [
212 | "## \\_supreme_sess pass off\n",
213 | "Through my testing on incognito mode I discovered you don't need to send any pookies ever and don't need to send any cookies on the first add to cart\n",
214 | "\n",
215 | "Here is a write up of the process. \n",
216 | "\n",
217 | "1 Add to Cart No cookie\n",
218 | "1 add to cart 200 and cookie = response.headers['cookie']\n",
219 | "2 Add to Cart 1 cookie\n",
220 | "2 200 and cookie = response.headers['cookie']\n",
221 | "3 Add to Cart 2 cookie\n",
222 | "3 200 and cookie = response.headers['cookie']\n",
223 | ".\n",
224 | ".\n",
225 | ".\n",
226 | "Nth Add to Cart N-1 cookie\n",
227 | "Nth 200 and cookie = response.headers['cookie']\n",
228 | " \n",
229 | "I also show how this process works through images\n",
230 | "\n",
231 | "
\n",
232 | " \n",
233 | "But you do need to take the response header (didn't get the whole header)\n",
234 | " \n",
235 | "
\n",
236 | " \n",
237 | "And Take the set-cookie and put back in the next request header\n",
238 | " \n",
239 | "
\n",
240 | " \n",
241 | "That's what the website does so make your application do the same thing too. It took me $450 to figure this out so be thankful. This is only 1 element of the cookie"
242 | ]
243 | },
244 | {
245 | "cell_type": "markdown",
246 | "metadata": {},
247 | "source": [
248 | "## Solving Captchas\n",
249 | "I use http://www.deathbycaptcha.com/user/login, but you can really use any captcha solver. I almost forgot to write about this because of how simple this is. \n",
250 | "\n",
251 | "For every checkout you need a g-captcha-repsonse code that is less then 120 seconds old. Just put it into your checkout form data. There is plenty of info to learn from googling how the captcha system works"
252 | ]
253 | },
254 | {
255 | "cell_type": "markdown",
256 | "metadata": {},
257 | "source": [
258 | "## Threading\n",
259 | "Threading is a huge issue I am unqualified to talk about but just think all this shit has to work at the same time like an orchestra. Good thing Rudy and I were in band together."
260 | ]
261 | },
262 | {
263 | "cell_type": "markdown",
264 | "metadata": {},
265 | "source": [
266 | "## Tips\n",
267 | "\n",
268 | "Overall process\n",
269 | "Get item page-->Scrape item page for values--> Post Add item to cart--> Scrape Post response--> Post Checkout\n",
270 | "\n",
271 | "Lots of webscraping\n",
272 | "\n",
273 | "Time is always important. Either time of the day or how long something has been going or existed\n",
274 | "\n",
275 | "Program this like the supreme site is doing to crash"
276 | ]
277 | }
278 | ],
279 | "metadata": {
280 | "kernelspec": {
281 | "display_name": "Python 3",
282 | "language": "python",
283 | "name": "python3"
284 | },
285 | "language_info": {
286 | "codemirror_mode": {
287 | "name": "ipython",
288 | "version": 3
289 | },
290 | "file_extension": ".py",
291 | "mimetype": "text/x-python",
292 | "name": "python",
293 | "nbconvert_exporter": "python",
294 | "pygments_lexer": "ipython3",
295 | "version": "3.6.6"
296 | }
297 | },
298 | "nbformat": 4,
299 | "nbformat_minor": 2
300 | }
301 |
--------------------------------------------------------------------------------
/supreme_bot/Bot.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# How to make a Supreme Bot"
8 | ]
9 | },
10 | {
11 | "cell_type": "markdown",
12 | "metadata": {},
13 | "source": [
14 | "2 main things to understand\n",
15 | "* session-user-cart-item relationships\n",
16 | "* How to use HTTP post requests and bypass the HTTPOnly system using headers"
17 | ]
18 | },
19 | {
20 | "cell_type": "markdown",
21 | "metadata": {},
22 | "source": [
23 | "---\n",
24 | "# session-user-cart-item relationships\n",
25 | "___"
26 | ]
27 | },
28 | {
29 | "cell_type": "markdown",
30 | "metadata": {},
31 | "source": [
32 | "## Session\n",
33 | "First thing to do is create a new session"
34 | ]
35 | },
36 | {
37 | "cell_type": "code",
38 | "execution_count": 2,
39 | "metadata": {},
40 | "outputs": [],
41 | "source": [
42 | "import requests\n",
43 | "session = requests.Session()"
44 | ]
45 | },
46 | {
47 | "cell_type": "markdown",
48 | "metadata": {},
49 | "source": [
50 | "An important thing to inspect and change is the session headers \n",
51 | "I have not found any reason to believe they are able to check this, but its best you change the `User-Agent` field"
52 | ]
53 | },
54 | {
55 | "cell_type": "code",
56 | "execution_count": 3,
57 | "metadata": {},
58 | "outputs": [
59 | {
60 | "data": {
61 | "text/plain": [
62 | "{'User-Agent': 'python-requests/2.14.2', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}"
63 | ]
64 | },
65 | "execution_count": 3,
66 | "metadata": {},
67 | "output_type": "execute_result"
68 | }
69 | ],
70 | "source": [
71 | "session.headers"
72 | ]
73 | },
74 | {
75 | "cell_type": "code",
76 | "execution_count": 4,
77 | "metadata": {},
78 | "outputs": [],
79 | "source": [
80 | "session.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:64.0) Gecko/20100101 Firefox/64.0'"
81 | ]
82 | },
83 | {
84 | "cell_type": "code",
85 | "execution_count": 5,
86 | "metadata": {},
87 | "outputs": [
88 | {
89 | "data": {
90 | "text/plain": [
91 | "{'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}"
92 | ]
93 | },
94 | "execution_count": 5,
95 | "metadata": {},
96 | "output_type": "execute_result"
97 | }
98 | ],
99 | "source": [
100 | "session.headers"
101 | ]
102 | },
103 | {
104 | "cell_type": "markdown",
105 | "metadata": {},
106 | "source": [
107 | "## User\n",
108 | "Each user will have their own session \n",
109 | "Each user will have their own cart \n",
110 | "It is import to tie all of these together by consistently using the same session for all GET and POST requests "
111 | ]
112 | },
113 | {
114 | "cell_type": "markdown",
115 | "metadata": {},
116 | "source": [
117 | "## Adding items to cart"
118 | ]
119 | },
120 | {
121 | "cell_type": "markdown",
122 | "metadata": {},
123 | "source": [
124 | "You will need to use the the `add` endpoint example like this https://www.supremenewyork.com/shop/{item_code}/add \n",
125 | "With form data and proper headers \n",
126 | "Its all about replicating what your browser is doing as much as possible\n",
127 | " \n",
128 | "\n",
129 | "How to find the {item_code}? \n",
130 | "Have a look around on an item page by finding where the {item_code} from the url exists on the webpage "
131 | ]
132 | },
133 | {
134 | "cell_type": "markdown",
135 | "metadata": {},
136 | "source": [
137 | "## How to use the Network tab to solve this problem\n",
138 | "The process will be this throughout the project. \n",
139 | "\n",
140 | "1. You need to inspect the headers and form data to see what is being passed. \n",
141 | "
\n",
142 | "2. You need to find where that data exists on the web page \n",
143 | "(See how I took the st value from the form data and search where it was in the webpage)\n",
144 | "
\n",
145 | "3. Create functions to scrape that data from the webpage\n",
146 | "4. Replicate those request header and form data packets with your POST request\n",
147 | "
\n",
148 | "
\n",
149 | "5. Read response headers to see how you performed and continue logically off that \n",
150 | "(Specifically the 'set-cookie' from add to cart and 'queued' from checkout)\n",
151 | "
"
152 | ]
153 | },
154 | {
155 | "cell_type": "markdown",
156 | "metadata": {},
157 | "source": [
158 | "---\n",
159 | "# How to beat HTTPOnly\n",
160 | "---\n",
161 | "From a high level there are several things you need to nail down that interweave with \n",
162 | " \n",
163 | "* Request Headers\n",
164 | " * X-CSRF code\n",
165 | " * cookie\n",
166 | " * cart\n",
167 | " * pure_cart\n",
168 | " * \\_supreme_sess\n",
169 | "* Response Headers\n",
170 | " * Taking the cookie returned and placing it into the next post request\n",
171 | "* Checkout form data\n",
172 | " * Solving a captcha and placing that into the form data for each checkout"
173 | ]
174 | },
175 | {
176 | "cell_type": "markdown",
177 | "metadata": {},
178 | "source": [
179 | "## X-CSRF Code\n",
180 | "I think this is why you need to use the same session across all of the GET and POST requests \n",
181 | "so you get the proper X-CSRF code into the header. \n",
182 | " \n",
183 | "Just scrape this from the item page you want to add to cart and your checkout page \n",
184 | " \n",
185 | "
"
186 | ]
187 | },
188 | {
189 | "cell_type": "markdown",
190 | "metadata": {},
191 | "source": [
192 | "## Cookie parts\n",
193 | "There a a couple of parts of the cookie that need to be separately created then assembled\n",
194 | "* \\_supreme_sess\n",
195 | "* cart\n",
196 | "* pure_cart\n",
197 | "* request_method\n",
198 | "\n",
199 | "cart and pure_cart are encoded. Use https://www.urldecoder.org/ to start figuring out what's going on and reverse engineer it. \n",
200 | "\n",
201 | "request_method seems to be the HTTP request you made. I just hardcode it Post because why would your bot be deleting anything. \n",
202 | "\n",
203 | "pure_cart is finicky I would suggest including it but it doesnt always return in the response headers and isn't needed in the request headers. I would 100% put it in the POST checkout. \n",
204 | "\n",
205 | "Throw all of these in one cookie named`['set-cookie']` separated by commas\n"
206 | ]
207 | },
208 | {
209 | "cell_type": "markdown",
210 | "metadata": {},
211 | "source": [
212 | "## \\_supreme_sess pass off\n",
213 | "Through my testing on incognito mode I discovered you don't need to send any pookies ever and don't need to send any cookies on the first add to cart\n",
214 | "\n",
215 | "Here is a write up of the process. \n",
216 | "\n",
217 | "1 Add to Cart No cookie \n",
218 | "1 add to cart 200 and cookie = response.headers['cookie'] \n",
219 | "2 Add to Cart 1 cookie \n",
220 | "2 200 and cookie = response.headers['cookie'] \n",
221 | "3 Add to Cart 2 cookie \n",
222 | "3 200 and cookie = response.headers['cookie'] \n",
223 | ". \n",
224 | ". \n",
225 | ". \n",
226 | "Nth Add to Cart N-1 cookie \n",
227 | "Nth 200 and cookie = response.headers['cookie'] \n",
228 | " \n",
229 | "I also show how this process works through images\n",
230 | "\n",
231 | "
\n",
232 | " \n",
233 | "But you do need to take the response header (didn't get the whole header)\n",
234 | " \n",
235 | "
\n",
236 | " \n",
237 | "And Take the set-cookie and put back in the next request header\n",
238 | " \n",
239 | "
\n",
240 | " \n",
241 | "That's what the website does so make your application do the same thing too. It took me $450 to figure this out so be thankful. This is only 1 element of the cookie"
242 | ]
243 | },
244 | {
245 | "cell_type": "markdown",
246 | "metadata": {},
247 | "source": [
248 | "## Solving Captchas\n",
249 | "I use http://www.deathbycaptcha.com/user/login, but you can really use any captcha solver. I almost forgot to write about this because of how simple this is. \n",
250 | "\n",
251 | "For every checkout you need a g-captcha-repsonse code that is less then 120 seconds old. Just put it into your checkout form data. There is plenty of info to learn from googling how the captcha system works"
252 | ]
253 | },
254 | {
255 | "cell_type": "markdown",
256 | "metadata": {},
257 | "source": [
258 | "## Threading\n",
259 | "Threading is a huge issue I am unqualified to talk about but just think all this shit has to work at the same time like an orchestra. Good thing Rudy and I were in band together."
260 | ]
261 | },
262 | {
263 | "cell_type": "markdown",
264 | "metadata": {},
265 | "source": [
266 | "## Tips\n",
267 | "\n",
268 | "Overall process\n",
269 | "Get item page-->Scrape item page for values--> Post Add item to cart--> Scrape Post response--> Post Checkout\n",
270 | "\n",
271 | "Lots of webscraping\n",
272 | "\n",
273 | "Time is always important. Either time of the day or how long something has been going or existed\n",
274 | "\n",
275 | "Program this like the supreme site is doing to crash"
276 | ]
277 | }
278 | ],
279 | "metadata": {
280 | "kernelspec": {
281 | "display_name": "Python 3",
282 | "language": "python",
283 | "name": "python3"
284 | },
285 | "language_info": {
286 | "codemirror_mode": {
287 | "name": "ipython",
288 | "version": 3
289 | },
290 | "file_extension": ".py",
291 | "mimetype": "text/x-python",
292 | "name": "python",
293 | "nbconvert_exporter": "python",
294 | "pygments_lexer": "ipython3",
295 | "version": "3.6.6"
296 | }
297 | },
298 | "nbformat": 4,
299 | "nbformat_minor": 2
300 | }
301 |
--------------------------------------------------------------------------------
/supreme_bot/csrf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rglenn415/RGupyter/74d1aff35bd291e784c6e9511ea719d3033a7737/supreme_bot/csrf.png
--------------------------------------------------------------------------------
/supreme_bot/form_data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rglenn415/RGupyter/74d1aff35bd291e784c6e9511ea719d3033a7737/supreme_bot/form_data.png
--------------------------------------------------------------------------------
/supreme_bot/form_data_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rglenn415/RGupyter/74d1aff35bd291e784c6e9511ea719d3033a7737/supreme_bot/form_data_close.png
--------------------------------------------------------------------------------
/supreme_bot/found_element.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rglenn415/RGupyter/74d1aff35bd291e784c6e9511ea719d3033a7737/supreme_bot/found_element.png
--------------------------------------------------------------------------------
/supreme_bot/header_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rglenn415/RGupyter/74d1aff35bd291e784c6e9511ea719d3033a7737/supreme_bot/header_example.png
--------------------------------------------------------------------------------
/supreme_bot/remove_cart_request_incognito.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rglenn415/RGupyter/74d1aff35bd291e784c6e9511ea719d3033a7737/supreme_bot/remove_cart_request_incognito.png
--------------------------------------------------------------------------------
/supreme_bot/request_incognito.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rglenn415/RGupyter/74d1aff35bd291e784c6e9511ea719d3033a7737/supreme_bot/request_incognito.png
--------------------------------------------------------------------------------
/supreme_bot/response_incognito.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rglenn415/RGupyter/74d1aff35bd291e784c6e9511ea719d3033a7737/supreme_bot/response_incognito.png
--------------------------------------------------------------------------------
/supreme_bot/set_cookie_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rglenn415/RGupyter/74d1aff35bd291e784c6e9511ea719d3033a7737/supreme_bot/set_cookie_close.png
--------------------------------------------------------------------------------
/time.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Python time packages\n",
8 | "\n",
9 | "My relationship with time packages are strange because I love `time`, but constantly\n",
10 | "get annoyed with `datetime` \n",
11 | "\n",
12 | "Understanding when and why you should use each packaged is important, but it is also important to use both together at times\n",
13 | "\n",
14 | "Quickly read about both: \n",
15 | "[time](https://docs.python.org/3.7/library/time.html) \n",
16 | "[datetime](https://docs.python.org/3/library/datetime.html)\n",
17 | "\n",
18 | "## First import dependencies\n",
19 | "#### these "
20 | ]
21 | },
22 | {
23 | "cell_type": "code",
24 | "execution_count": 18,
25 | "metadata": {},
26 | "outputs": [],
27 | "source": [
28 | "import datetime\n",
29 | "import time"
30 | ]
31 | },
32 | {
33 | "cell_type": "markdown",
34 | "metadata": {},
35 | "source": [
36 | "## Let's play with the basics of time\n",
37 | "Off the top of my head the 2 functions I use the most are"
38 | ]
39 | },
40 | {
41 | "cell_type": "markdown",
42 | "metadata": {},
43 | "source": [
44 | "# `time.sleep()`\n",
45 | "###### run it"
46 | ]
47 | },
48 | {
49 | "cell_type": "code",
50 | "execution_count": null,
51 | "metadata": {},
52 | "outputs": [],
53 | "source": [
54 | "time.sleep(10)\n",
55 | "print('that took a while right?')"
56 | ]
57 | },
58 | {
59 | "cell_type": "markdown",
60 | "metadata": {},
61 | "source": [
62 | "### `time.sleep(secs)`\n",
63 | "\n",
64 | "(this was taken from the [time documentation](https://docs.python.org/3.7/library/time.html#module-time) with some extra bold styling by me. **bold = important take aways**)\n",
65 | "\n",
66 | "**Suspend execution of the calling thread for the given number of seconds**. The argument **may be a floating point number** to indicate a more precise sleep time. The actual suspension time may be less than that requested because any caught signal will terminate the sleep() following execution of that signal’s catching routine. Also, the suspension time may be longer than requested by an arbitrary amount because of the scheduling of other activity in the system.\n",
67 | "\n",
68 | "### More uses:"
69 | ]
70 | },
71 | {
72 | "cell_type": "markdown",
73 | "metadata": {},
74 | "source": [
75 | "I use `time.sleep()` when I want to give the action some time to breathe \n",
76 | "\n",
77 | "I often scrape a website until some condition is met and `time.sleep()` to make sure that I am not accidentally ddosing the server. `time.sleep()` is a responsible function to drop in a loop to make sure you don't go too crazy\n",
78 | "\n",
79 | "`time.sleep()` could be used to sleep for 30 minutes or 8 hours and can help you control frequency a function is completed or repeated at"
80 | ]
81 | },
82 | {
83 | "cell_type": "code",
84 | "execution_count": null,
85 | "metadata": {},
86 | "outputs": [],
87 | "source": [
88 | "x = 0\n",
89 | "\n",
90 | "while x < 5:\n",
91 | " print(f'Current x value: {x}')\n",
92 | " x += 1\n",
93 | " time.sleep(2)\n",
94 | " \n",
95 | "print('\\nout of the while loop')"
96 | ]
97 | },
98 | {
99 | "cell_type": "markdown",
100 | "metadata": {},
101 | "source": [
102 | "# `time.time()`\n",
103 | "###### run it"
104 | ]
105 | },
106 | {
107 | "cell_type": "code",
108 | "execution_count": null,
109 | "metadata": {},
110 | "outputs": [],
111 | "source": [
112 | "time.time()"
113 | ]
114 | },
115 | {
116 | "cell_type": "markdown",
117 | "metadata": {},
118 | "source": [
119 | "### `time.time() → float`\n",
120 | "\n",
121 | "(this was taken from the [time documentation](https://docs.python.org/3.7/library/time.html#module-time) with some extra bold styling by me. **bold = important take aways**)\n",
122 | "\n",
123 | "Return the time in **seconds** since the **epoch** as a floating point number. The specific date of the epoch and the handling of leap seconds is platform dependent. On Windows and most Unix systems, the epoch is January 1, 1970, 00:00:00 (UTC) and leap seconds are not counted towards the time in seconds since the epoch. This is commonly referred to as Unix time. To find out what the epoch is on a given platform, look at gmtime(0).\n",
124 | "\n",
125 | "Note that even though the time is always returned as a floating point number, not all systems provide time with a better precision than 1 second. While this function normally returns non-decreasing values, it can return a lower value than a previous call if the system clock has been set back between the two calls.\n",
126 | "\n",
127 | "**Ways to improve formatting** \n",
128 | "The number returned by time() may be converted into a more common time format (i.e. year, month, day, hour, etc…) in UTC by passing it to gmtime() function or in local time by passing it to the localtime() function. In both cases a struct_time object is returned, from which the components of the calendar date may be accessed as attributes."
129 | ]
130 | },
131 | {
132 | "cell_type": "markdown",
133 | "metadata": {},
134 | "source": [
135 | "## SO WHAT?\n",
136 | "The biggest takeaways are: \n",
137 | "`time.time()` has **no** initial relationship to date (an advantage of `datetime`) \n",
138 | "`time.time()` returns the time in **seconds** since the **epoch** as a floating point number"
139 | ]
140 | },
141 | {
142 | "cell_type": "markdown",
143 | "metadata": {},
144 | "source": [
145 | "## My DO'S of `time.time()`\n",
146 | "I often turn to `time.time()` for simple time basic conditional logic when data related to the date (year, month and such) is not needed.\n",
147 | "\n"
148 | ]
149 | },
150 | {
151 | "cell_type": "code",
152 | "execution_count": null,
153 | "metadata": {},
154 | "outputs": [],
155 | "source": [
156 | "start = time.time()\n",
157 | "time.sleep(5)\n",
158 | "end = time.time()\n",
159 | "print(f'That took {end - start} seconds')"
160 | ]
161 | },
162 | {
163 | "cell_type": "markdown",
164 | "metadata": {},
165 | "source": [
166 | "I usually end up keeping the math pretty low (under 1 minute) \n",
167 | "It's hard to convert 3600 seconds into minutes instantly \n",
168 | "If you do use this for times that would be \n",
169 | "hours or minutes apart, I would suggest commenting what the seconds \n",
170 | "are equal to and what is the reason behind the comparison"
171 | ]
172 | },
173 | {
174 | "cell_type": "code",
175 | "execution_count": null,
176 | "metadata": {},
177 | "outputs": [],
178 | "source": [
179 | "# There are many ways you could do this\n",
180 | "# 60 minutes or 1 hour = 3600 seconds\n",
181 | "\n",
182 | "# Making sure that the main() has been running for an hour\n",
183 | "# this makes sure that the data is ready\n",
184 | "if time_difference > 3600:\n",
185 | " print(f'transaction complete done in {time_difference}')\n",
186 | " return"
187 | ]
188 | },
189 | {
190 | "cell_type": "markdown",
191 | "metadata": {},
192 | "source": [
193 | "I find my self doing loops like this where \n",
194 | "I initialize a **starting time** then use that starting time to make comparisons \n",
195 | "against the **current time** and record how long an action took to complete"
196 | ]
197 | },
198 | {
199 | "cell_type": "markdown",
200 | "metadata": {},
201 | "source": [
202 | "## My DON'TS of `time.time()`\n",
203 | "I avoid `time.time()` when I am storing date in a database as an attribute.\n",
204 | " \n",
205 | "`datetime.datetime()` has much better built in getter functions that do a lot of work to access different formats of date, time, what day of the week it is, and what month it is.\n",
206 | "\n",
207 | "A informational quote I found at the top of the [`datetime.datetime()` documentation](https://docs.python.org/3/library/datetime.html) : \n",
208 | "\n",
209 | "\"While date and time arithmetic is supported, the focus of the implementation is on efficient attribute extraction for output formatting and manipulation.\"\n",
210 | "\n",
211 | "### `time based arithmetic = time`\n",
212 | "### `time based attribute extraction = datetime`"
213 | ]
214 | },
215 | {
216 | "cell_type": "markdown",
217 | "metadata": {},
218 | "source": [
219 | "# `datetime.datetime()`\n",
220 | "Let's start with `datetime` examples and then go into more detail"
221 | ]
222 | },
223 | {
224 | "cell_type": "markdown",
225 | "metadata": {},
226 | "source": [
227 | "## How to get current time?"
228 | ]
229 | },
230 | {
231 | "cell_type": "code",
232 | "execution_count": null,
233 | "metadata": {},
234 | "outputs": [],
235 | "source": [
236 | "datetime.datetime.today()"
237 | ]
238 | },
239 | {
240 | "cell_type": "code",
241 | "execution_count": null,
242 | "metadata": {},
243 | "outputs": [],
244 | "source": [
245 | "datetime.datetime.now()"
246 | ]
247 | },
248 | {
249 | "cell_type": "markdown",
250 | "metadata": {},
251 | "source": [
252 | "*`class`* `datetime.datetime` \n",
253 | "A combination of a date and a time. \n",
254 | "Attributes: year, month, day, hour, minute, second, microsecond, and tzinfo."
255 | ]
256 | },
257 | {
258 | "cell_type": "markdown",
259 | "metadata": {},
260 | "source": [
261 | "## How will `datetime` objects print?\n",
262 | "\n",
263 | "for classes the function `__str__()` decides how the object will interacted when called for a print statement\n",
264 | "\n",
265 | "`datetime.datetime.__str__()` \n",
266 | "For a datetime instance d, str(d) is equivalent to d.isoformat(' ')\n",
267 | "\n",
268 | "`datetime.isoformat(sep='T', timespec='auto')` \n",
269 | "Return a string representing the date and time in ISO 8601 format, YYYY-MM-DDTHH:MM:SS.ffffff or, if microsecond is 0, YYYY-MM-DDTHH:MM:SS"
270 | ]
271 | },
272 | {
273 | "cell_type": "code",
274 | "execution_count": null,
275 | "metadata": {},
276 | "outputs": [],
277 | "source": [
278 | "print(datetime.datetime.now())"
279 | ]
280 | },
281 | {
282 | "cell_type": "markdown",
283 | "metadata": {},
284 | "source": [
285 | "Basicly, if you print `datetime.datetime()` the `datetime` package will format a more human readable version of the date and time"
286 | ]
287 | },
288 | {
289 | "cell_type": "markdown",
290 | "metadata": {},
291 | "source": [
292 | "## `datetime.datetime()` constructor"
293 | ]
294 | },
295 | {
296 | "cell_type": "code",
297 | "execution_count": null,
298 | "metadata": {},
299 | "outputs": [],
300 | "source": [
301 | "christmas_day = datetime.datetime(2019,12,25)\n",
302 | "# .date() will access just the date of the datetime.datetime object\n",
303 | "print(f'christmas day is {christmas_day.date()}')\n",
304 | "\n",
305 | "christmas_dinner = datetime.datetime(2019,12,25,15,30)\n",
306 | "print(f'christmas dinner is at {christmas_dinner}')"
307 | ]
308 | },
309 | {
310 | "cell_type": "markdown",
311 | "metadata": {},
312 | "source": [
313 | "## `datetime` feature extraction\n"
314 | ]
315 | },
316 | {
317 | "cell_type": "code",
318 | "execution_count": null,
319 | "metadata": {},
320 | "outputs": [],
321 | "source": [
322 | "#for only the date\n",
323 | "print(datetime.datetime.today().date())\n",
324 | "\n",
325 | "#for the time only\n",
326 | "print(datetime.datetime.today().time())\n",
327 | "\n",
328 | "# for the day of the week\n",
329 | "# 0 is monday 6 is sunday\n",
330 | "print(datetime.datetime.today().weekday())"
331 | ]
332 | },
333 | {
334 | "cell_type": "code",
335 | "execution_count": null,
336 | "metadata": {},
337 | "outputs": [],
338 | "source": [
339 | "datetime.datetime.today().time()"
340 | ]
341 | },
342 | {
343 | "cell_type": "code",
344 | "execution_count": null,
345 | "metadata": {},
346 | "outputs": [],
347 | "source": [
348 | "print(datetime.datetime.today().time())"
349 | ]
350 | },
351 | {
352 | "cell_type": "markdown",
353 | "metadata": {},
354 | "source": [
355 | "You can access any of the `` attributes (read-only):\n",
356 | "```python\n",
357 | "datetime.year\n",
358 | "Between MINYEAR and MAXYEAR inclusive.\n",
359 | "\n",
360 | "datetime.month\n",
361 | "Between 1 and 12 inclusive.\n",
362 | "\n",
363 | "datetime.day\n",
364 | "Between 1 and the number of days in the given month of the given year.\n",
365 | "\n",
366 | "datetime.hour\n",
367 | "In range(24).\n",
368 | "\n",
369 | "datetime.minute\n",
370 | "In range(60).\n",
371 | "\n",
372 | "datetime.second\n",
373 | "In range(60).\n",
374 | "\n",
375 | "datetime.microsecond\n",
376 | "In range(1000000).\n",
377 | "\n",
378 | "datetime.tzinfo\n",
379 | "The object passed as the tzinfo argument to the datetime constructor, or None if none was passed.\n",
380 | "```"
381 | ]
382 | },
383 | {
384 | "cell_type": "markdown",
385 | "metadata": {},
386 | "source": [
387 | "## `datetime.timedelta()`\n",
388 | "\n",
389 | "(this was taken from the [datetime documentation](https://docs.python.org/3/library/datetime.html#module-datetime) with some extra bold styling by me. **bold = important take aways**)\n",
390 | "\n",
391 | "A timedelta object represents a **duration, the difference between two dates or times.**\n",
392 | "\n",
393 | "class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0) \n",
394 | "All arguments are optional and default to 0. Arguments may be integers or floats, and **may be positive or negative.** \n",
395 | "\n",
396 | "Only days, seconds and microseconds are stored internally. Arguments are converted to those units:\n",
397 | "\n",
398 | "A millisecond is converted to 1000 microseconds. \n",
399 | "A minute is converted to 60 seconds. \n",
400 | "An hour is converted to 3600 seconds. \n",
401 | "A week is converted to 7 days. \n",
402 | "and days, seconds and microseconds are then normalized so that the representation is unique, with"
403 | ]
404 | },
405 | {
406 | "cell_type": "markdown",
407 | "metadata": {},
408 | "source": [
409 | "### When do you see `timedelta`\n",
410 | "I run into the `timedelta` type when doing time based arithmatic in `datetime`. \n",
411 | "\n",
412 | "This is something I suggested against, but you will need to do sometimes if you need to compare across day, months or years."
413 | ]
414 | },
415 | {
416 | "cell_type": "code",
417 | "execution_count": null,
418 | "metadata": {},
419 | "outputs": [],
420 | "source": [
421 | "old = datetime.datetime.now()\n",
422 | "time.sleep(3)\n",
423 | "new = datetime.datetime.now()\n",
424 | "\n",
425 | "time_diff = new - old\n",
426 | "print(time_diff)\n",
427 | "print(type(time_diff))"
428 | ]
429 | },
430 | {
431 | "cell_type": "markdown",
432 | "metadata": {},
433 | "source": [
434 | "### same implemenation in `time`"
435 | ]
436 | },
437 | {
438 | "cell_type": "code",
439 | "execution_count": null,
440 | "metadata": {},
441 | "outputs": [],
442 | "source": [
443 | "old = time.time()\n",
444 | "time.sleep(3)\n",
445 | "new = time.time()\n",
446 | "\n",
447 | "time_diff = new - old\n",
448 | "print(time_diff)\n",
449 | "print(type(time_diff))"
450 | ]
451 | },
452 | {
453 | "cell_type": "markdown",
454 | "metadata": {},
455 | "source": [
456 | "## What are the big takeaways from `time` and `datetime`?\n",
457 | "When covering the `time` package I focused more on how you can use time to help you functions\n",
458 | "\n",
459 | "When covering the `datetime` package I focused more on how to access the multitude tools of the package most of which handle formatting what part of the date you want.\n",
460 | "\n",
461 | "the `datetime` package becomes more powerful when you start using it to power conditional statements and super useful for formatting `datetime` information to record when events occurred and then put that information into a database\n"
462 | ]
463 | },
464 | {
465 | "cell_type": "markdown",
466 | "metadata": {},
467 | "source": [
468 | "## How to use both `time` and `datetime` together?\n",
469 | "I will preview some code where time data is added to a database from my upcoming supreme bot project \n",
470 | "# 🤫🤫🤫🤫🤫🤫\n",
471 | "# 🤭🤭🤭🤭🤭🤭\n",
472 | "# 😤😤😤😤😤😤\n",
473 | "\n",
474 | "This is function occurs when this custom created thread is `thead.start()`ed"
475 | ]
476 | },
477 | {
478 | "cell_type": "code",
479 | "execution_count": null,
480 | "metadata": {},
481 | "outputs": [],
482 | "source": [
483 | "def run(self):\n",
484 | " \"\"\"\n",
485 | " Run Condition:\n",
486 | " This Function runs when the instance of the\n",
487 | " thread is started (thread.start() in create_threads())\n",
488 | "\n",
489 | " Functionality:\n",
490 | " Thread solves a captcha and\n",
491 | " pushes captcha text to sorted_captchas if solved correctly\n",
492 | " \"\"\"\n",
493 | " start = time.time()\n",
494 | "\n",
495 | " # solves captcha and out puts google captcha response value\n",
496 | " captcha = get_captcha()\n",
497 | "\n",
498 | " elapsed = start - time.time()\n",
499 | " print(f'captcha thread{self.id} complete - {elapsed}s\\n')\n",
500 | "\n",
501 | " # Add captcha data to csv\n",
502 | " # This will be used for future analysis\n",
503 | " with open('captcha.csv','a') as csvfile:\n",
504 | " row = {'captcha':captcha.captcha,\n",
505 | " 'text': captcha.text, \n",
506 | " 'time': datetime.datetime.today().time(), \n",
507 | " 'date': datetime.datetime.today().date(),\n",
508 | " 'weekday': datetime.datetime.today().weekday(), \n",
509 | " 'elapsed': elapsed}\n",
510 | "\n",
511 | " fieldnames = ['captcha', 'text', 'time','date', 'weekday', 'elapsed']\n",
512 | " captcha_csv = csv.DictWriter(csvfile,fieldnames)\n",
513 | " captcha_csv.writerow(row)"
514 | ]
515 | },
516 | {
517 | "cell_type": "markdown",
518 | "metadata": {},
519 | "source": [
520 | "Here `time` is used for time arithmetic because `datetime.timedelta` is super annoying to use and format correctly.\n",
521 | "\n",
522 | "Then I use `datetime` to grab date related attributes for the database. These functions return in a very pretty format and I trust this package to handle this more than me sclicing string and placing into the database.\n",
523 | "\n",
524 | "Could I use only `datetime`? \n",
525 | "Yes.\n",
526 | "\n",
527 | "I try to avoid performing too much time based arithmetic with `datetime` because it can get tricky, but in the future I might try it out to see how it can work just using 1 time package."
528 | ]
529 | },
530 | {
531 | "cell_type": "markdown",
532 | "metadata": {},
533 | "source": [
534 | "# Novel Ideas"
535 | ]
536 | },
537 | {
538 | "cell_type": "markdown",
539 | "metadata": {},
540 | "source": [
541 | "### Does calling `time.time()` and `datetime.datetime` get repetitive?\n",
542 | "I was playing around with how to import the package and will give my thoughts on\n",
543 | "what is the best format\n",
544 | "\n",
545 | "Since these packages are called the same way I will just do all the examples with `time`"
546 | ]
547 | },
548 | {
549 | "cell_type": "code",
550 | "execution_count": null,
551 | "metadata": {},
552 | "outputs": [],
553 | "source": [
554 | "from time import time\n",
555 | "print(time())\n",
556 | "time"
557 | ]
558 | },
559 | {
560 | "cell_type": "markdown",
561 | "metadata": {},
562 | "source": [
563 | "This example above would be annoying because when you refer to `time` now it is `time.time()`. This would be dangerous because you would not be able to access other `time` functions"
564 | ]
565 | },
566 | {
567 | "cell_type": "code",
568 | "execution_count": null,
569 | "metadata": {},
570 | "outputs": [],
571 | "source": [
572 | "import time as t\n",
573 | "print(t.time())\n",
574 | "t"
575 | ]
576 | },
577 | {
578 | "cell_type": "markdown",
579 | "metadata": {},
580 | "source": [
581 | "This is a little better because `t` is now `time` so other functions can be accessed like `t.clock()`\n",
582 | "\n",
583 | "But I would still advise against it because `t` has low informational value and not already widely used so it would confuse future readers of your code.\n",
584 | "\n",
585 | "I think of examples such as for popular import statement abbreviations: \n",
586 | "```python\n",
587 | "import pandas as pd\n",
588 | "import numpy as np\n",
589 | "```\n",
590 | "\n",
591 | "`time` and `timedelta` both are missing a high informational value 2 letter abbreviation so I would advise against using any other naming convention\n",
592 | "\n",
593 | "But damn does calling `time.time()` and `datetime.datetime.today()` get annoying to look at."
594 | ]
595 | },
596 | {
597 | "cell_type": "markdown",
598 | "metadata": {},
599 | "source": [
600 | "# That's it\n",
601 | "Hopefully you enjoyed my breakdown of the `time` and `datetime` packages and will walk away with more than just details about each package, but their **strengths** and *weaknesses*"
602 | ]
603 | }
604 | ],
605 | "metadata": {
606 | "kernelspec": {
607 | "display_name": "Python 3",
608 | "language": "python",
609 | "name": "python3"
610 | },
611 | "language_info": {
612 | "codemirror_mode": {
613 | "name": "ipython",
614 | "version": 3
615 | },
616 | "file_extension": ".py",
617 | "mimetype": "text/x-python",
618 | "name": "python",
619 | "nbconvert_exporter": "python",
620 | "pygments_lexer": "ipython3",
621 | "version": "3.6.6"
622 | }
623 | },
624 | "nbformat": 4,
625 | "nbformat_minor": 2
626 | }
627 |
--------------------------------------------------------------------------------