<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: joseph</title>
    <description>The latest articles on DEV Community by joseph (@jsphwllng).</description>
    <link>https://dev.to/jsphwllng</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F432893%2Fb75a8cb5-8ad2-4974-8f9c-75305dac75b4.png</url>
      <title>DEV Community: joseph</title>
      <link>https://dev.to/jsphwllng</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jsphwllng"/>
    <language>en</language>
    <item>
      <title>Monitor your internet with python</title>
      <dc:creator>joseph</dc:creator>
      <pubDate>Fri, 23 Oct 2020 11:32:42 +0000</pubDate>
      <link>https://dev.to/jsphwllng/monitor-your-internet-with-python-3pp8</link>
      <guid>https://dev.to/jsphwllng/monitor-your-internet-with-python-3pp8</guid>
      <description>&lt;p&gt;I live in Germany and Germany is known for its diversity. The people are diverse, the culture is diverse and the quality of internet connections are equally as diverse. Having spoken to my internet provider who insisted I had no problems with my internet connection I decided to write a program to monitor my upload and download speed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;

&lt;p&gt;We will be using two cool packages in python namely &lt;code&gt;speedtest&lt;/code&gt; and &lt;code&gt;matplotlib&lt;/code&gt;. &lt;code&gt;speedtest&lt;/code&gt; will provide us with the information about our internet connection and &lt;code&gt;matplotlib&lt;/code&gt; will allow us to generate graphs based on this information.&lt;/p&gt;

&lt;p&gt;Whether you're in a &lt;a href="https://docs.python.org/3/tutorial/venv.html" rel="noopener noreferrer"&gt;virtual environment&lt;/a&gt; or not using one you will have to install speedtest and matplotlib.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;matplotlib
pip &lt;span class="nb"&gt;install &lt;/span&gt;speedtest-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will also be using a few built in python packages &lt;code&gt;datetime&lt;/code&gt; and &lt;code&gt;csv&lt;/code&gt;. CSV (or comma separated values) are a quick way of storing data. We will be using this to store the information about our internet speeds and then using matplotlib to make this information visual.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gathering data
&lt;/h3&gt;

&lt;p&gt;Create a python file called &lt;code&gt;monitor.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;monitor.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and let's put the following code on the inside&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;speedtest&lt;/span&gt;
&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;speedtest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Speedtest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and we should be greeted by the following output before hitting &lt;code&gt;ctrl + C&lt;/code&gt; to get out of this infinite loop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;75020309.22943133 24381170.373616524
105192450.00822952 40653433.153288215
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So by creating a new instance of speedtest as s and testing the upload and download speed we are given the upload and download speed in bits per second. To convert this to megabits per second (Mb/s) we can do the following to include the time of the test too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;speedtest&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;speedtest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Speedtest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%H:%M:%S&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;downspeed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1048576&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;upspeed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1048576&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;time: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, downspeed: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;downspeed&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; Mb/s, upspeed: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;upspeed&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; Mb/s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which yields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;time: 12:44:15, downspeed: 95.04 Mb/s, upspeed: 32.85 Mb/s
time: 12:44:35, downspeed: 99.46 Mb/s, upspeed: 38.76 Mb/s
time: 12:44:56, downspeed: 100.59 Mb/s, upspeed: 38.94 Mb/s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will move on to recording this in a CSV file. CSVs are large text files which values separated by commas. Here is an example of one of mine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;time,downspeed,upspeed
12:17:01,100.05,38.28
12:17:21,100.53,37.85
12:17:42,74.87,25.92
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We start with a header row then have the information split up. We can think about this like an excel sheet:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fupoqadpj8vh4se02u4om.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fupoqadpj8vh4se02u4om.png" alt="a table with the same information as the code block above"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In order to record into a csv file in python we need to import the CSV package and 'open' a CSV file (if one doesn't exist it will create one).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;speedtest&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;

&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;speedtest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Speedtest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;test.csv&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;speedcsv&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;csv_writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DictWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;speedcsv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="n"&gt;fieldnames&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;time&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;downspeed&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;upspeed&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;csv_writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeheader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%H:%M:%S&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;downspeed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1048576&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;upspeed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1048576&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;csv_writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writerow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;time&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;downspeed&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;downspeed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;upspeed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;upspeed&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So while you let this code run for 4-5 minutes we can discuss what is going on. Line 7 &lt;code&gt;with open&lt;/code&gt; essentiallly creates a csv file with the name &lt;code&gt;test.csv&lt;/code&gt; with the headers &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;downspeed&lt;/code&gt; and &lt;code&gt;upspeed&lt;/code&gt; and writers them into the csv. Then the loop begins and every time a test is performed by speedtest it writes a new row into the csv with the time, download speed and upload speed we specified before. So let's go and look at that now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;time,downspeed,upspeed
12:51:16,99.29,38.66
12:51:37,100.67,38.79
12:51:57,99.7,38.79
12:52:17,92.89,31.99
12:52:38,99.4,38.96
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cool now we are gathering information and storing it in a csv. You could do all sorts of clever stuff with the filename like name it today's date using &lt;code&gt;datetime&lt;/code&gt; but for now I will keep it as test.&lt;/p&gt;

&lt;p&gt;You could also set up a check to see if a certain amount of time has passed and to stop the application after that but I will leave that up to your own creativity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visualising the data
&lt;/h3&gt;

&lt;p&gt;Let's make another python file to generate the graph of our internet connection. This is where we will use matplotlib.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;make_graph.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;matplotlib.ticker&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ticker&lt;/span&gt;
&lt;span class="n"&gt;times&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;download&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;upload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The easiest way to generate a graph is by using an array. In order to populate our arrays we will have to iterate through our new csv file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;test.csv&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;csvfile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;plots&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csvfile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delimiter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csvfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;plots&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;times&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
        &lt;span class="n"&gt;download&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
        &lt;span class="n"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;download&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;['12:51:16', '12:51:37', '12:51:57', '12:52:17', '12:52:38']
 [99.29, 100.67, 99.7, 92.89, 99.4]
 [38.66, 38.79, 38.79, 31.99, 38.96]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now we are parsing our data! The next(csvfile) essentially skipss the row of headers (that were for our benefit only, not python's). Now we come on to using matplotlib which I am by no standards and expert on. &lt;a href="https://matplotlib.org" rel="noopener noreferrer"&gt;Their documentation&lt;/a&gt; is &lt;em&gt;extensive&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;download&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;download&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;upload&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xlabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;time&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;speed in Mb/s&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;internet speed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;savefig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;test_graph.jpg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bbox_inches&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tight&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code tells matplotlib or &lt;code&gt;plt&lt;/code&gt; to create a figure with the lines labelled 'download' and 'upload' to be plotted against their respective arrays. So for every item in the download and and time array a mark will be made on the graph against it. Finally the x and y axis get labels and the graph gets saved. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1n9w54gko2qcaqc4cadd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1n9w54gko2qcaqc4cadd.jpg" alt="A graph generated by python - showing a varying upload and download speed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Potential improvements
&lt;/h3&gt;

&lt;p&gt;This is a short form of a project I recently finished which contains automated uploads to a cloud platform, schedules itself daily does some annotations of the lowest download speed. I initially made it to complain to my internet provider however I know that it will be like showing a graph to a brick wall.&lt;/p&gt;

&lt;p&gt;If you have any questions about this tutorial please don't hesitate to reach out to me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/jsphWllng" rel="noopener noreferrer"&gt;@jsphwllng&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>What is your go-to Emoji on tech twitter? </title>
      <dc:creator>joseph</dc:creator>
      <pubDate>Fri, 18 Sep 2020 23:09:02 +0000</pubDate>
      <link>https://dev.to/jsphwllng/what-is-your-go-to-emoji-on-tech-twitter-2bbo</link>
      <guid>https://dev.to/jsphwllng/what-is-your-go-to-emoji-on-tech-twitter-2bbo</guid>
      <description>

</description>
      <category>discuss</category>
      <category>twitter</category>
      <category>tech</category>
    </item>
    <item>
      <title>Creating a webscraping twitter bot in Python.</title>
      <dc:creator>joseph</dc:creator>
      <pubDate>Thu, 17 Sep 2020 14:45:15 +0000</pubDate>
      <link>https://dev.to/jsphwllng/creating-a-webscraping-twitter-bot-in-python-366b</link>
      <guid>https://dev.to/jsphwllng/creating-a-webscraping-twitter-bot-in-python-366b</guid>
      <description>&lt;p&gt;Let's look at building a twitter bot that scrapes information from one part of the web and then spits it out on twitter. There are a few good examples if you want to generate ideas for a twitter bot such as &lt;a href="https://twitter.com/bbcbweaking?lang=en"&gt;@bbcbweaking&lt;/a&gt;, &lt;a href="https://twitter.com/poem_exe"&gt;@poemexe&lt;/a&gt; and my own &lt;a href="https://twitter.com/rnghaiku"&gt;@rnghaiku&lt;/a&gt;. In this example we will write something that simply finds the first dev.to post and tweets the title.&lt;/p&gt;

&lt;p&gt;Requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Text editor&lt;/li&gt;
&lt;li&gt;Browser&lt;/li&gt;
&lt;li&gt;Patience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before we write even a line of code we need to download two &lt;strong&gt;incredibly&lt;/strong&gt; powerful modules namely: &lt;a href="https://www.crummy.com/software/BeautifulSoup/bs4/doc/"&gt;beautifulsoup&lt;/a&gt; and &lt;a href="https://www.tweepy.org/"&gt;tweepy&lt;/a&gt;. Beautifulsoup will handle the webscraping and tweepy will handle the twitter API requests. &lt;/p&gt;

&lt;h1&gt;
  
  
  Webscraping
&lt;/h1&gt;

&lt;p&gt;Webscraping is one of the most powerful tools that a coder has and it's the first thing I look to do in each language that I touch. we will be using &lt;a href="https://www.crummy.com/software/BeautifulSoup/bs4/doc/"&gt;beautifulsoup&lt;/a&gt; for this and you can install it from your terminal with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install beautifulsoup4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a new .py document and add the following lines to the top in order to import all the functions that beautifulsoup (which I will refer to now as bs4) has for us:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import requests
from bs4 import BeautifulSoup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You now need to define the page you want bs4 to open which you can do like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;page = reqeusts.get("http://dev.to")
soup = BeautifulSoup(page.content, "html.parser")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to test that bs4 is doing it's job you can simply print the content of this page to see what we have&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;print(soup)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uq4nxYAo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gtivzrfrotip7dkw5lqt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uq4nxYAo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gtivzrfrotip7dkw5lqt.png" alt="A lot of HTML code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we are loading ALL the html from the dev.to which is neither readable nor tweetable. We now need to refine our search using the built in "find" function from bs4. In order to find the titles of each post we need to dive into the HTML of dev.to. We can do this by either reading all the HTML (boring, long, painful) or simply use your favourite web browser to do the same.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_LDE-UMF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7fufyveu8ibqwqpew2dy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_LDE-UMF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7fufyveu8ibqwqpew2dy.png" alt='Clicking "inspect element"'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QpUt-wHz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/e2s0lfb0w9g7lfvv6nau.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QpUt-wHz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/e2s0lfb0w9g7lfvv6nau.jpg" alt="The HTML DOM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see in the DOM above that each title is buried under several HTML classes and ids. In order to get to these we're going to have to dig through the elements in order to return an array of titles. We can do it like this and I will explain later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from bs4 import BeautifulSoup
import requests

page = requests.get("http://dev.to")
soup = BeautifulSoup(page.content, "html.parser")
home = soup.find(class_="articles-list crayons-layout__content")
posts = home.find_all(class_="crayons-story__indentation")

for post in posts:
    title = post.find("h2", class_="crayons-story__title")
    print(title.text.strip())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now lets go through each line of code in order.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;page = requests.get("http://dev.to")
soup = BeautifulSoup(page.content, "html.parser")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These open the HTML page and returns the result as a &lt;code&gt;bs4.BeautifulSoup&lt;/code&gt; object. We can then find objects within this soup of HTML with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;home = soup.find(class_="articles-list crayons-layout__content")
posts = home.find_all(class_="crayons-story__indentation")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you look at the DOM above the red coloured section refers to everything inside the "home" variable and the posts is everything inside the green. The posts is now an array (or a &lt;code&gt;bs4.element.ResultSet&lt;/code&gt;) that we can iterate through as follows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for post in posts:
    title = post.find("h2", class_="crayons-story__title")
    print(title.text.strip())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For every post in the list of posts we search for the h2 with the class of &lt;code&gt;crayons-story__title&lt;/code&gt; and print the stripped title for it. This is the purple section of the highlighted DOM. If everything goes correctly you should see a list of posts like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CXEMe4fx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/e8nbaff5ky5vp767elw4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CXEMe4fx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/e8nbaff5ky5vp767elw4.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But obviously we only want the first one of these so we can just do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;top_post = posts[0].find("h2", class_="crayons-story__title").text.strip()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which in my case returns the &lt;code&gt;Stop Using React&lt;/code&gt; post. For selecting other elements such as &lt;code&gt;&amp;lt;a href="foo"&amp;gt;&lt;/code&gt; tags please check out this tutorial from &lt;a href="http://www.compjour.org/warmups/govt-text-releases/collect-lists-of-obama-press-briefings/"&gt;compjour&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Anyway now we have something that we want to tweet (which can be any string or even images) we can now look at tweeting.&lt;/p&gt;

&lt;h1&gt;
  
  
  Tweeting
&lt;/h1&gt;

&lt;p&gt;For this we will use &lt;a href="https://www.tweepy.org/"&gt;tweepy&lt;/a&gt; whose documentation is equally as strong and useful as bs4's and I recommend that you check out. Install in the usual way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install tweepy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and on the top of your python document don't forget to include tweepy&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import tweepy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and now we need to set up a twitter app for your bot to operate in. You can do this by going &lt;a href="https://developer.twitter.com/en/apps"&gt;here&lt;/a&gt; and creating an app and filling in the simple form, confirm your email then you will have to wait for your developer application to be confirmed. In the meantime, before we get our API keys, we can do some more work on the tweet we want to send.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from bs4 import BeautifulSoup
import tweepy
import requests

def scrape():
    page = requests.get("http://dev.to")
    soup = BeautifulSoup(page.content, "html.parser")
    home = soup.find(class_="articles-list crayons-layout__content")
    posts = home.find_all(class_="crayons-story__indention")
    top_post = posts[0].find("h2", class_="crayons-story__title").text.strip()


    tweet(top_post)

def tweet(top_post):
    consumer_key = "#"
    consumer_secret = "#"
    access_token = "#"
    access_token_secret = "#"
    auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
    auth.set_access_token(access_token, access_token_secret)
    api = tweepy.API(auth)
    api.update_status(top_post)

scrape()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's a lot going on here so let's slowly go through it. The tweet function that we wrote will take one argument of 'top post' which is what we figured out in the scrape section. The &lt;code&gt;consumer_key&lt;/code&gt;, &lt;code&gt;consumer_secret&lt;/code&gt;, &lt;code&gt;access_token&lt;/code&gt; and &lt;code&gt;access_token_secret&lt;/code&gt; are all API keys provided to us by twitter and should be some long, unreadable string. To learn what these tokens actually do I would recommend that you check out the &lt;a href="http://docs.tweepy.org/en/latest/api.html"&gt;tweepy documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once you receive the email confirming your API keys be sure to copy them into your function so they function as expected.&lt;/p&gt;

&lt;p&gt;Once all of this has been completed we can host our bot on AWS or my personal recommendation &lt;a href="https://dashboard.heroku.com/"&gt;heroku&lt;/a&gt;. For a good guide on hosting a bot on heroku &lt;a href="https://dev.to/emcain/how-to-set-up-a-twitter-bot-with-python-and-heroku-1n39"&gt;please check out this great article from data_bae&lt;/a&gt;. Now just run your app and let's see what you get!&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--xdiqwLiu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1305919308028153863/ftsz6Qvv_normal.jpg" alt="joseph 🍇 profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        joseph 🍇
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="comment-mentioned-user" href="https://dev.to/jsphwllng"&gt;@jsphwllng&lt;/a&gt;

      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P4t6ys1m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Stop Using React
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      14:39 PM - 17 Sep 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1306603585954869248" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="/assets/twitter-reply-action.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1306603585954869248" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="/assets/twitter-retweet-action.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      0
      &lt;a href="https://twitter.com/intent/like?tweet_id=1306603585954869248" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="/assets/twitter-like-action.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
      0
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;I, of course, advocate using React as I have the hopes of getting a job in Berlin where React is dominating the job market so I will have some explaining to do in my twitter later. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you have any questions about this article or my bad syntax please message me at &lt;a href="https://twitter.com/jsphWllng"&gt;@jsphwllng&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>python</category>
      <category>twitter</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Reflections on a bootcamp.</title>
      <dc:creator>joseph</dc:creator>
      <pubDate>Wed, 16 Sep 2020 16:36:24 +0000</pubDate>
      <link>https://dev.to/jsphwllng/reflections-on-a-coding-bootcamp-3p64</link>
      <guid>https://dev.to/jsphwllng/reflections-on-a-coding-bootcamp-3p64</guid>
      <description>&lt;p&gt;I recently completed a 9 week Full Stack Development bootcamp in Berlin and I have some thoughts on the whole process and hopefully I can help some people decide whether or not it is for them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The before
&lt;/h2&gt;

&lt;p&gt;I self-studied coding, before the bootcamp, in my spare time. Coding was and continues to be one of my hobbies. It's satisfying, results &lt;em&gt;can&lt;/em&gt; come quick especially with languages like Python and Ruby. I decided to elevate my hobby into a career after a few boring career ventures into Project Management and Legal Consultancy. My coding level before the bootcamp was not strong in any sense of the word. I was comfortable with datatypes in Python, I could iterate over an array and I was happy enough to copy code. I applied to this bootcamp after a friend of a friend had completed it.&lt;/p&gt;

&lt;p&gt;For me attending a bootcamp was a big gamble. I knew I had the capacity to become a strong coder if I could dedicate a year or more to teaching myself however the prospect of being accelerated by a school convinced me to leave my Project Management position and try and enter the Tech World. &lt;/p&gt;

&lt;p&gt;I had a month and a half between my job ending and my enrollment in the bootcamp and during this time I fixated on completing as much of the pre-reading and working on a few small projects of my own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Applying
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F35tataoyx51gbe03zhcf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F35tataoyx51gbe03zhcf.png" alt="An image showing various emails from bootcamps in Berlin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The entry bar for coding camps is simply time and money. I applied to a number of bootcamps in Berlin before settling on one and each of the bootcamps had similar entry requirements. Generally consisting of 50 hours of work on one of the various online studying platforms (freecodecamp, codecademy, etc.) with a focus on the language of choice. My bootcamp focused on Ruby which is an incredibly simple language to use and then some closing thoughts on HTML, CSS and Javascript. Aside from being able to complete the pre-course work there is obviously the cost. This bootcamp in Berlin cost ~€6000. &lt;/p&gt;

&lt;p&gt;Luckily, for me, the German Government was able to fund my tuition however a large portion of the people on the bootcamp were self-funded and, surprisingly to me, there was very little difference in the attitude between the two groups of people. &lt;/p&gt;

&lt;p&gt;It was obvious, even from the start, that some people were attending the bootcamp to transition careers and others were there simply for "something to do" during the COVID situation where numerous companies in Berlin had let their staff go on &lt;a href="https://en.wikipedia.org/wiki/Short-time_working#Germany" rel="noopener noreferrer"&gt;Kurzarbeit&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The first week
&lt;/h2&gt;

&lt;p&gt;The atmosphere at the coding bootcamp was very interesting. A large mix of ages and genders (but very ethnically homogeneous) getting together to learn. It had been over 5 years since I had left any form of educational establishment whereas some people were joining directly from university and others had full careers that they had been able to take a leave of absence from to code. &lt;/p&gt;

&lt;p&gt;The first day, in which we were setting up our laptops (to UNIX systems) was a foreshadow of some things to come. We were shown basic git commands that the students would repeat with little understanding if they had not seen them before. Problems often arose with git among the students, most of which had to be solved by teachers or those with experience in version management. &lt;/p&gt;

&lt;p&gt;From the second day onward we used Ruby. In the short-term Ruby seemed like the most sensible "native" language for new students. I had used Python prior to the bootcamp and I would rank Python as slightly more complex than Ruby in its syntax. For new coders Ruby is, I think, a good gateway into coding. However when more complicated syntax was introduced with JavaScript some of the students struggled as they had been used to the simplicity of Ruby. &lt;/p&gt;

&lt;p&gt;Each day during the first 7 weeks of the bootcamp we were given between 2 and 6 challenges to solve. If you have used Hackerrank or Codewars then you are familiar with the style of the challenges: you are told to create, more times than not, a function/method that takes an input and then outputs something as a result. Below you can see a typical challenge/answer combo&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Specs&lt;/p&gt;

&lt;p&gt;Write a method array_to_hash which takes an Array as an argument&lt;br&gt;
and returns a Hash.&lt;br&gt;
    If no block is given, then the hash keys should just be integer indexes of elements in the array, converted as Strings.&lt;br&gt;
   If a block is given, call it passing the array index and use what’s returned as the hash key.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def array_to_hash(array)
  hash = {}                                      
  array.each_with_index do |item, index|           
    key = block_given? ? yield(index) : index.to_s 
    hash[key] = item                               
  end
  return hash                                     
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During our time completing these challenges we had access to the Teaching Assistants, contactable by raising a ticket, who would assist in the problem. The code was exponential in the fact that the previous days code would build the foundations of the next's. &lt;/p&gt;

&lt;p&gt;The challenge system was a very good way of building upon the knowledge we were given in our 2 hour morning lecture. The morning lecture would introduce the concepts of any given day (for example the first day would be a focus on strings, the second arrays) before letting us loose on the challenges. &lt;/p&gt;

&lt;p&gt;As we had completed the prep work prior to the bootcamp the first two weeks of the bootcamp felt, to me, slightly redundant. We were repeating code that we had studied not too long ago. In this regard I would not consider bootcamps to be any better than Hackerrank or FreeCodeCamp where you could simply read a tutorial and then continue coding on your own. Where my bootcamp, and I presume all coding bootcamps, excel is the environment that you are in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coding by committee
&lt;/h2&gt;

&lt;p&gt;Each morning the inbuilt system would assign you a buddy. Your role with your buddy that day would be to discuss the code, help troubleshoot each other's problems and to generally build up a friendly environment within the bootcamp which would become crucial in the later weeks.&lt;/p&gt;

&lt;p&gt;It was obvious from the first couple of weeks who the stand-out coders were in our batch. More often than not these coders were people who had prior experience coding. The buddy system, for these more experienced people, was a hindrance in terms of the actual coding but in terms of the social skills it proved invaluable. I know, personally, I could have completed the challenges each day in a fraction of the time if I was left on my own however, having now spoken to recruiters and engineers alike, it is equally as important to have strong teaching skills if you want to enter the tech world. By having to explain &lt;em&gt;how&lt;/em&gt; or &lt;em&gt;why&lt;/em&gt; code works helped my own understanding sometimes but more importantly it let me learn how to teach.&lt;/p&gt;

&lt;p&gt;The times that this group-think coding really had an impact was a lot more casual. Sitting with friends and complaining about the challenges, discussing workarounds to get the output to be correct or simply deleting the test spec file was where we built out network and where the real learning happened. Showing code to my contemporaries and having them laugh at my incorrect variable names or debugging together helped me learn how write readable code and how to write shorter code. This is not something you can teach in a lecture. &lt;/p&gt;

&lt;h2&gt;
  
  
  Copying and pasting
&lt;/h2&gt;

&lt;p&gt;Day 0 copying and pasting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Open a terminal and type this, replacing the email with yours (the same one you used to create your GitHub account). It will prompt for information. Just press enter until it asks for a passphrase.

mkdir -p ~/.ssh &amp;amp;&amp;amp; ssh-keygen -t ed25519 -o -a 100 -f ~/.ssh/id_ed25519 -C "TYPE_YOUR_EMAIL@HERE.com"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Day -1 copying and pasting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Setup

To setup a favicon, you can use Rails' favicon_link_tag helper.

Best practice:

    Resize your logo image in 32x32
    Upload it in a favicon generator, this will generate a favicon.ico file
    Add it to your app/assets/images folder
    Place your favicon_link_tag in your layout's &amp;lt;head&amp;gt;:

&amp;lt;!-- app/views/layouts/application.html.erb --&amp;gt;
&amp;lt;%= favicon_link_tag %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One of my main criticism with the bootcamp format, and maybe this is actually a criticism of coding in general, is that we learned &lt;strong&gt;just enough&lt;/strong&gt; to code. From the first day we were almost blindly pasting things into the console without much real understanding of what we were doing. Even at the last day as we were deploying our final product that we were just copying and pasting things into the terminal to satisfy some tests. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Obviously&lt;/strong&gt; this is how you have to do it in a bootcamp environment because I can't imagine explaining how a compiler works to a group of students who only learned how an if/else statements works less than 8 weeks prior. &lt;/p&gt;

&lt;p&gt;My main criticism, however, was the lack of education on how to continue learning. For 9 weeks the students at the bootcamp followed a very structured set of lectures, challenges and tests however now that I am two weeks outside the bootcamp system it has been an interesting transition into learning how to make my own projects, learn new concepts and overall maintain the pace that the bootcamp had set up. &lt;/p&gt;

&lt;p&gt;I understand that this is how the majority of education goes, for example when I was studying my bachelors I wasn't exactly prepared to self study in the legal world however I think with tech there is some exception. The tech world is largely self-taught and reading things like documentation is a legitimate skill that you need to develop. The bootcamp felt like its end goal was to get students through the bootcamp and not necessarily produce self-reliant coders. &lt;/p&gt;

&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;

&lt;p&gt;I realise that I should maybe give some insight into what we were actually taught as this will allow me to accelerate this diary entry into the interesting final weeks of the bootcamp. The bootcamp's modules are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ruby&lt;/strong&gt; (2 and a half weeks ending with basic OOP)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Databases&lt;/strong&gt; (1 week starting with SQL before ending on PostgreSQL)&lt;/li&gt;
&lt;li&gt;**Front end (1 and a half weeks covering HTML, JS and CSS)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rails&lt;/strong&gt; (2 weeks of building webapps ranging from simple websites to an AIRBNB clone)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project weeks&lt;/strong&gt; (2 weeks of building our own project)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before we move onto the project week it is worth discussing how each of these modules went as I believe the pacing and order could be slightly improved. &lt;/p&gt;

&lt;h3&gt;
  
  
  Ruby
&lt;/h3&gt;

&lt;p&gt;The pacing that the Ruby module was taught I largely can't argue with. I personally thought that the challenges were a &lt;em&gt;bit&lt;/em&gt; simple however that is more of a reflection on myself than it is the course. &lt;/p&gt;

&lt;h3&gt;
  
  
  Databases
&lt;/h3&gt;

&lt;p&gt;Databases were the area I, personally, struggled with the most. This is where I got the most insight into how the TAs operate and the insight that they give. The teaching staff at the bootcamp, including the TAs, are stellar. TAs are assigned each day based on their strengths and very rarely did I have a call with someone where I felt that they hadn't contributed somehow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Front end
&lt;/h3&gt;

&lt;p&gt;I would like to see Javascript be the first language that we are taught in the bootcamp. The beauty of Ruby relies on its simplicity and it's easy to read nature but this isn't fully appreciated until you touch on other languages. What surprised me about the order of teaching is we started off with the simpler language. &lt;/p&gt;

&lt;p&gt;I think that having a week of Javascript learning how to iterate over arrays and all the unusual complexities that Javascript presents would be a shock to the system that the tonic of Ruby would be welcome. &lt;/p&gt;

&lt;h3&gt;
  
  
  Rails
&lt;/h3&gt;

&lt;p&gt;I personally think for a topic as complicated and wide-reaching as Rails, or any framework for that matter, this bootcamp did a surprisingly good job at teaching. My criticism in this area, which I think might be a critique of the whole construct of bootcamps is the reliance on copying and pasting that I spoke about before.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project week
&lt;/h2&gt;

&lt;p&gt;This is the real meat and potatoes of the bootcamp. Project week is the last 2 weeks of the bootcamp and is the first real insight into the developer life. There is no real guidelines to follow and you just have to produce something with the knowledge that you gain during the previous 7 weeks. It is a stressful, chaotic time where a group of four students, with one student acting as the &lt;em&gt;lead developer&lt;/em&gt; have to work together. In the previous 7 weeks we were simply satisfying tests and then you are let loose.&lt;/p&gt;

&lt;p&gt;You are forced to learn how to work as a team, to use code that you hadn't ever seen before and I should really write another piece on this. Generally it was a fantastic experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Was a coding a good experience? Yes, it was incredible.&lt;/strong&gt; I grew as a coder, I grew as a person and I have come away from it with an insight into a world that I wouldn't otherwise have. &lt;strong&gt;Is it for everyone?&lt;/strong&gt; I'm not so sure. I think the people who got the most out of the bootcamp are the ones who have a clear mindset about what they want to get out of it. Some people were hoping to change industry, others wanted to be able to project manage in a group of coders. I feel like those who got the least out of the experience were the people who just signed up to learn something.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Will a coding bootcamp hold up in allowing me to get a job in the real world?&lt;/strong&gt; I don't know yet. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you have any questions about coding bootcamps feel free to reach out to me &lt;a href="https://twitter.com/jsphWllng" rel="noopener noreferrer"&gt;@jsphWllng&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>career</category>
      <category>beginners</category>
      <category>rails</category>
      <category>ruby</category>
    </item>
  </channel>
</rss>
