<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/cheer-up-black-metal-cats-bubblegum-puppies/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://www.masalmon.eu/2018/01/04/bubblegumpuppies/"> Maëlle</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>Do you know the <a rel="nofollow" href="https://twitter.com/evilbmcats" target="_blank">Black Metal Cats Twitter account</a>? As explained <a rel="nofollow" href="https://nerdist.com/cats-twitter-heavy-metal-lyrics/" target="_blank">in this great introduction</a>, it “combines kitties with heavy metal lyrics”. I know the account because I follow <a rel="nofollow" href="https://twitter.com/sckottie" target="_blank">Scott Chamberlain</a> who retweets them a lot, which I enjoy as far as one can enjoy such a dark mood. Speaking of which, I decided to try and transform Black Metal Cat tweets into something more positive… The <a rel="nofollow" href="https://twitter.com/cheerful_doggos" target="_blank">Bubblegum Puppies</a> were born!</p>
<p><span></span></p>
<h1>Getting Black Metal Cats tweets</h1>
<p>It won’t come as a surprise for the loyal readers of this blog that I just had to use <code>rtweet</code>. I kept only original standalone tweets and removed the picture link from the tweet.</p>
<div>
<div>
<pre><code><span>black_tweets</span><span> </span><span>&lt;-</span><span> </span><span>rtweet</span><span>::</span><span>get_timeline</span><span>(</span><span>&quot;evilbmcats&quot;</span><span>)</span><span>
</span><span>black_tweets</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>filter</span><span>(</span><span>black_tweets</span><span>,</span><span> </span><span>is.na</span><span>(</span><span>reply_to_user_id</span><span>),</span><span> </span><span>!</span><span>is_retweet</span><span>,</span><span> </span><span>!</span><span>is_quote</span><span>)</span><span>
</span><span>black_tweets</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>select</span><span>(</span><span>black_tweets</span><span>,</span><span> </span><span>text</span><span>,</span><span> </span><span>created_at</span><span>,</span><span> </span><span>status_id</span><span>)</span><span>
</span><span>black_tweets</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>mutate</span><span>(</span><span>black_tweets</span><span>,</span><span> </span><span>text</span><span> </span><span>=</span><span> </span><span>stringr</span><span>::</span><span>str_replace</span><span>(</span><span>text</span><span>,</span><span> </span><span>&quot;https.*&quot;</span><span>,</span><span> </span><span>&quot;&quot;</span><span>))</span><span>
</span><span>readr</span><span>::</span><span>write_csv</span><span>(</span><span>black_tweets</span><span>,</span><span> </span><span>path</span><span> </span><span>=</span><span> </span><span>&quot;data/2018-01-03-bubblegumpuppies_cats.csv&quot;</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p>Now that the dark material is ready, let’s sweeten it…</p>
<h1>Modifying the tweet text</h1>
<p>Black Metal Cats tweet heavy metal lyrics so as you can imagine, they’re sad. How to make them happy while keeping the text similar enough to the original one? And this without too much effort? My simplistic strategy was to identify negative words via sentiment analysis and to replace them with positive words.</p>
<p><em>Note, had I not wanted to stay close to the original tweet, I could have just chosen lyrics picked from <a rel="nofollow" href="https://www.rdocumentation.org/packages/billboard/versions/0.1.0/topics/lyrics?tap_a=5644-dce66f&tap_s=10907-287229" target="_blank">this dataset</a> for instance, and filtered them by sentiment via the sentimentr package.</em></p>
<h2>Finding negative words</h2>
<p>I computed sentiment using <code>tidytext</code> copy-pasting code from <a rel="nofollow" href="http://www.masalmon.eu/2017/10/02/guardian-experience/" target="_blank">this post of mine</a>.</p>
<div>
<div>
<pre><code><span>library</span><span>(</span><span>&quot;tidytext&quot;</span><span>)</span><span>
</span><span>library</span><span>(</span><span>&quot;magrittr&quot;</span><span>)</span><span>
</span><span>bing</span><span> </span><span>&lt;-</span><span> </span><span>get_sentiments</span><span>(</span><span>&quot;bing&quot;</span><span>)</span><span>
</span><span>sentiment</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>select</span><span>(</span><span>black_tweets</span><span>,</span><span> </span><span>text</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>dplyr</span><span>::</span><span>mutate</span><span>(</span><span>saved_text</span><span> </span><span>=</span><span> </span><span>text</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>unnest_tokens</span><span>(</span><span>word</span><span>,</span><span> </span><span>text</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>dplyr</span><span>::</span><span>inner_join</span><span>(</span><span>bing</span><span>,</span><span> </span><span>by</span><span> </span><span>=</span><span> </span><span>&quot;word&quot;</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>dplyr</span><span>::</span><span>filter</span><span>(</span><span>sentiment</span><span> </span><span>==</span><span> </span><span>&quot;negative&quot;</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p>It was a bit disappointing since out of the 97 only 63 were represented in that data.frame. But well, this shall do! I just looked rapidly at some non included tweets.</p>
<div>
<div>
<pre><code><span>dplyr</span><span>::</span><span>filter</span><span>(</span><span>black_tweets</span><span>,</span><span> </span><span>!</span><span>text</span><span> </span><span>%in%</span><span> </span><span>sentiment</span><span>$</span><span>saved_text</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>head</span><span>()</span><span> </span><span>%>%</span><span>
</span><span>knitr</span><span>::</span><span>kable</span><span>()</span><span>
</span></code></pre>
</div>
</div>
<table>
<thead>
<tr>
<th>text</th>
<th>created_at</th>
<th>status_id</th>
</tr>
</thead>
<tbody>
<tr>
<td>Black covfefe cats.</td>
<td>2017-12-29 21:01:06</td>
<td>946848575446663168</td>
</tr>
<tr>
<td>Black coffee cats.</td>
<td>2017-12-28 00:15:48</td>
<td>946172798203916288</td>
</tr>
<tr>
<td>Say goodbye to the light.</td>
<td>2017-12-26 15:50:00</td>
<td>945683121336344576</td>
</tr>
<tr>
<td>The storm will never end.</td>
<td>2017-12-23 15:49:00</td>
<td>944595705204678656</td>
</tr>
<tr>
<td>Satan, your time has come. This world must end.</td>
<td>2017-12-18 22:36:00</td>
<td>942886191107575808</td>
</tr>
<tr>
<td>Timely.</td>
<td>2017-12-13 00:43:30</td>
<td>940743951287504896</td>
</tr>
</tbody>
</table>
<p>Ok so some of them are probably negative tweets that the <a rel="nofollow" href="https://cran.r-project.org/web/packages/sentimentr/README.html" target="_blank"><code>sentimentr</code> package</a> would help detect but that do not contain negative words.</p>
<h2>Replacing words</h2>
<p>I seriously considered using the <a rel="nofollow" href="https://cran.r-project.org/web/packages/wordnet/index.html" target="_blank"><code>wordnet</code> package</a> because of this <a rel="nofollow" href="https://stackoverflow.com/questions/19360107/getting-antonyms-using-the-r-wordnet-package" target="_blank">Stack Overflow question “Getting antonyms using the <code>wordnet</code> package”</a> but I was not brave enough, my strength failed me in front of the Java needs of that package.</p>
<p>I decided to use <code>praise</code> to get positive words, and <code>cleanNLP</code> (as in <a rel="nofollow" href="http://www.masalmon.eu/2017/12/05/badderb/" target="_blank">this post</a>) to try and identify correctly negative words as adjective or verbs for instance in order to be able to replace them. The right annotation for that is a <em>token</em>.</p>
<div>
<div>
<pre><code><span>library</span><span>(</span><span>&quot;cleanNLP&quot;</span><span>)</span><span>
</span><span>#init_spaCy()</span><span>
</span><span>get_token_with_text</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>x</span><span>){</span><span>
</span><span>obj</span><span> </span><span>&lt;-</span><span> </span><span>run_annotators</span><span>(</span><span>x</span><span>,</span><span> </span><span>as_strings</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span>
</span><span>entities</span><span> </span><span>&lt;-</span><span> </span><span>get_token</span><span>(</span><span>obj</span><span>)</span><span>
</span><span>entities</span><span>$</span><span>text</span><span> </span><span>&lt;-</span><span> </span><span>x</span><span>
</span><span>entities</span><span>
</span><span>}</span><span>
</span><span>possibly_get_tokens</span><span> </span><span>&lt;-</span><span> </span><span>purrr</span><span>::</span><span>possibly</span><span>(</span><span>get_token_with_text</span><span>,</span><span>
</span><span>otherwise</span><span> </span><span>=</span><span> </span><span>NULL</span><span>)</span><span>
</span><span>tokens</span><span> </span><span>&lt;-</span><span> </span><span>purrr</span><span>::</span><span>map_df</span><span>(</span><span>sentiment</span><span>$</span><span>saved_text</span><span>,</span><span> </span><span>possibly_get_tokens</span><span>)</span><span>
</span><span>head</span><span>(</span><span>tokens</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>knitr</span><span>::</span><span>kable</span><span>()</span><span>
</span></code></pre>
</div>
</div>
<table>
<tbody>
<tr>
<td> </td>
</tr>
<tr>
<td> </td>
</tr>
<tr>
<td> </td>
</tr>
<tr>
<td> </td>
</tr>
</tbody>
</table>
<p>Once here, I joined sentiment and tokens.</p>
<div>
<div>
<pre><code><span>tokens</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>mutate</span><span>(</span><span>tokens</span><span>,</span><span> </span><span>word</span><span> </span><span>=</span><span> </span><span>enc2native</span><span>(</span><span>word</span><span>))</span><span>
</span><span>tokens</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>mutate</span><span>(</span><span>tokens</span><span>,</span><span> </span><span>word</span><span> </span><span>=</span><span> </span><span>tolower</span><span>(</span><span>word</span><span>))</span><span>
</span><span>tokens</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>left_join</span><span>(</span><span>sentiment</span><span>,</span><span> </span><span>tokens</span><span>,</span><span> </span><span>by</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>&quot;saved_text&quot;</span><span> </span><span>=</span><span> </span><span>&quot;text&quot;</span><span>,</span><span> </span><span>&quot;word&quot;</span><span>))</span><span>
</span><span>head</span><span>(</span><span>tokens</span><span>)</span><span> </span><span>%>%</span><span> </span><span>knitr</span><span>::</span><span>kable</span><span>()</span><span>
</span></code></pre>
</div>
</div>
<table>
<thead>
<tr>
<th>saved_text</th>
<th>word</th>
<th>sentiment</th>
<th>id</th>
<th>sid</th>
<th>tid</th>
<th>lemma</th>
<th>upos</th>
<th>pos</th>
<th>cid</th>
</tr>
</thead>
<tbody>
<tr>
<td>We are the creatures you fear.</td>
<td>fear</td>
<td>negative</td>
<td>1</td>
<td>1</td>
<td>6</td>
<td>fear</td>
<td>VERB</td>
<td>VBP</td>
<td>25</td>
</tr>
<tr>
<td>In darkness we walk.</td>
<td>darkness</td>
<td>negative</td>
<td>1</td>
<td>1</td>
<td>2</td>
<td>darkness</td>
<td>NOUN</td>
<td>NN</td>
<td>3</td>
</tr>
<tr>
<td>Standing tall, side by side, we shall build thy throne upon the burning ashes.</td>
<td>burning</td>
<td>negative</td>
<td>1</td>
<td>1</td>
<td>15</td>
<td>burn</td>
<td>VERB</td>
<td>VBG</td>
<td>64</td>
</tr>
<tr>
<td>This is the dawn of the infernal reign.</td>
<td>infernal</td>
<td>negative</td>
<td>1</td>
<td>1</td>
<td>7</td>
<td>infernal</td>
<td>ADJ</td>
<td>JJ</td>
<td>24</td>
</tr>
<tr>
<td>A breath of the past so distant and so unreal. A soul condemned to haunt a frozen burial ground.</td>
<td>condemned</td>
<td>negative</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>condemn</td>
<td>VERB</td>
<td>VBD</td>
<td>54</td>
</tr>
<tr>
<td>A breath of the past so distant and so unreal. A soul condemned to haunt a frozen burial ground.</td>
<td>condemned</td>
<td>negative</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>condemn</td>
<td>VERB</td>
<td>VBD</td>
<td>54</td>
</tr>
</tbody>
</table>
<p>The <code>praise</code> package provides adjectives that I’ll use to replace adjectives and to add an exclamation at the beginning of each text. Nouns, present and preterit verbs will be replaced with love/loves/loved because hey, this is pop music inspiration. I’ll lose capital letters and won’t bother too much, puppies probably do not care either. What I prepare below is what Hilary Parker called a dictionary table <a rel="nofollow" href="https://twitter.com/hspter/status/948646331677118465" target="_blank">in this tweet</a>. <code>VBZ</code> is for instance a verb in the present form like “haunts”.</p>
<div>
<div>
<pre><code><span>modifiers</span><span> </span><span>&lt;-</span><span> </span><span>tibble</span><span>::</span><span>tibble</span><span>(</span><span>pos</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span> </span><span>&quot;NN&quot;</span><span>,</span><span> </span><span>&quot;VBG&quot;</span><span>,</span><span> </span><span>&quot;JJ&quot;</span><span>,</span><span> </span><span>&quot;VBD&quot;</span><span>,</span><span> </span><span>&quot;VB&quot;</span><span>,</span><span> </span><span>&quot;NNS&quot;</span><span>,</span><span> </span><span>&quot;VBP&quot;</span><span>,</span><span> </span><span>&quot;VBN&quot;</span><span>,</span><span> </span><span>&quot;NNP&quot;</span><span>,</span><span> </span><span>&quot;VBZ&quot;</span><span>),</span><span>
</span><span>modifier</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>&quot;love&quot;</span><span>,</span><span> </span><span>&quot;${adjective}&quot;</span><span>,</span><span> </span><span>&quot;${adjective}&quot;</span><span>,</span><span>
</span><span>&quot;loved&quot;</span><span>,</span><span> </span><span>&quot;love&quot;</span><span>,</span><span> </span><span>&quot;lovers&quot;</span><span>,</span><span>
</span><span>&quot;love&quot;</span><span>,</span><span> </span><span>&quot;${adjective}&quot;</span><span>,</span><span>
</span><span>&quot;love&quot;</span><span>,</span><span> </span><span>&quot;loves&quot;</span><span>))</span><span>
</span><span>knitr</span><span>::</span><span>kable</span><span>(</span><span>modifiers</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<table>
<thead>
<tr>
<th>pos</th>
<th>modifier</th>
</tr>
</thead>
<tbody>
<tr>
<td>NN</td>
<td>love</td>
</tr>
<tr>
<td>VBG</td>
<td>${adjective}</td>
</tr>
<tr>
<td>JJ</td>
<td>${adjective}</td>
</tr>
<tr>
<td>VBD</td>
<td>loved</td>
</tr>
<tr>
<td>VB</td>
<td>love</td>
</tr>
<tr>
<td>NNS</td>
<td>lovers</td>
</tr>
<tr>
<td>VBP</td>
<td>love</td>
</tr>
<tr>
<td>VBN</td>
<td>${adjective}</td>
</tr>
<tr>
<td>NNP</td>
<td>love</td>
</tr>
<tr>
<td>VBZ</td>
<td>loves</td>
</tr>
</tbody>
</table>
<p>Now let’s get to work on the sweetening of the texts at last! Some occurrences of “hate” and “evil” remained, and I removed them by hand.</p>
<div>
<div>
<pre><code><span># praise has some randomness, let's make it reproducible</span><span>
</span><span>set.seed</span><span>(</span><span>42</span><span>)</span><span>
</span><span>modifiable_tweets</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>left_join</span><span>(</span><span>tokens</span><span>,</span><span> </span><span>black_tweets</span><span>,</span><span> </span><span>by</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>&quot;saved_text&quot;</span><span> </span><span>=</span><span> </span><span>&quot;text&quot;</span><span>))</span><span>
</span><span>modifiable_tweets</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>left_join</span><span>(</span><span>modifiable_tweets</span><span>,</span><span> </span><span>modifiers</span><span>,</span><span> </span><span>by</span><span> </span><span>=</span><span> </span><span>&quot;pos&quot;</span><span>)</span><span>
</span><span># for easier use with map</span><span>
</span><span>replace_all</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>pattern</span><span>,</span><span> </span><span>replacement</span><span>,</span><span> </span><span>x</span><span>){</span><span>
</span><span>stringr</span><span>::</span><span>str_replace_all</span><span>(</span><span>x</span><span>,</span><span> </span><span>pattern</span><span> </span><span>=</span><span> </span><span>pattern</span><span>,</span><span>
</span><span>replacement</span><span> </span><span>=</span><span> </span><span>replacement</span><span>)</span><span>
</span><span>}</span><span>
</span><span>modified_tweets</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>group_by</span><span>(</span><span>modifiable_tweets</span><span>,</span><span> </span><span>saved_text</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>dplyr</span><span>::</span><span>summarize</span><span>(</span><span>praise_template</span><span> </span><span>=</span><span> </span><span>purrr</span><span>::</span><span>map2_chr</span><span>(</span><span>word</span><span>,</span><span> </span><span>modifier</span><span>,</span><span> </span><span>replace_all</span><span>,</span><span>
</span><span>x</span><span> </span><span>=</span><span> </span><span>tolower</span><span>(</span><span>saved_text</span><span>[</span><span>1</span><span>]))[</span><span>1</span><span>],</span><span>
</span><span>praise_template</span><span> </span><span>=</span><span> </span><span>paste</span><span>(</span><span>&quot;${exclamation}!&quot;</span><span>,</span><span> </span><span>praise_template</span><span>),</span><span>
</span><span>praise_template</span><span> </span><span>=</span><span> </span><span>stringr</span><span>::</span><span>str_replace_all</span><span>(</span><span>praise_template</span><span>,</span><span>
</span><span>&quot;hate&quot;</span><span>,</span><span> </span><span>&quot;love&quot;</span><span>),</span><span>
</span><span>praise_template</span><span> </span><span>=</span><span> </span><span>stringr</span><span>::</span><span>str_replace_all</span><span>(</span><span>praise_template</span><span>,</span><span>
</span><span>&quot;evil&quot;</span><span>,</span><span> </span><span>&quot;love&quot;</span><span>),</span><span>
</span><span>new_text</span><span> </span><span>=</span><span> </span><span>praise</span><span>::</span><span>praise</span><span>(</span><span>praise_template</span><span>))</span><span> </span><span>modified_tweets</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>select</span><span>(</span><span>modified_tweets</span><span>,</span><span> </span><span>saved_text</span><span>,</span><span> </span><span>new_text</span><span>)</span><span>
</span><span>puppies_and_cats</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>left_join</span><span>(</span><span>modified_tweets</span><span>,</span><span> </span><span>black_tweets</span><span>,</span><span> </span><span>by</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>&quot;saved_text&quot;</span><span> </span><span>=</span><span> </span><span>&quot;text&quot;</span><span>))</span><span>
</span><span>head</span><span>(</span><span>puppies_and_cats</span><span>)</span><span> </span><span>%>%</span><span> </span><span>knitr</span><span>::</span><span>kable</span><span>()</span><span>
</span></code></pre>
</div>
</div>
<table>
<thead>
<tr>
<th>saved_text</th>
<th>new_text</th>
<th>created_at</th>
<th>status_id</th>
</tr>
</thead>
<tbody>
<tr>
<td>A breath of the past so distant and so unreal. A soul condemned to haunt a frozen burial ground.</td>
<td>yikes! a breath of the past so distant and so unreal. a soul loved to haunt a frozen burial ground.</td>
<td>2017-12-28 20:35:00</td>
<td>946479619020115968</td>
</tr>
<tr>
<td>Be very afraid.</td>
<td>yippie! be very fine.</td>
<td>2017-11-18 21:02:00</td>
<td>931990900523307008</td>
</tr>
<tr>
<td>Beware of the cat.</td>
<td>yay! love of the cat.</td>
<td>2017-12-11 14:54:02</td>
<td>940233218204172288</td>
</tr>
<tr>
<td>Beware the legions of Satan, they’re ready for attack!</td>
<td>ole! love the legions of satan, they’re ready for attack!</td>
<td>2017-12-05 22:48:00</td>
<td>938178169399422976</td>
</tr>
<tr>
<td>Born by the nothingness into eternal blasphemy.</td>
<td>mm! born by the nothingness into eternal love.</td>
<td>2017-12-03 04:15:01</td>
<td>937173299448221696</td>
</tr>
<tr>
<td>Born on a day of curses and damnation, I was doomed to hate.</td>
<td>whoa! born on a day of lovers and damnation, i was doomed to love.</td>
<td>2017-12-04 21:40:01</td>
<td>937798672347226113</td>
</tr>
</tbody>
</table>
<p>So although some new lyrics do not look that cheerful, they’re at least grammatically correct.</p>
<h1>Modifying the picture</h1>
<p>I recently discovered <a rel="nofollow" href="https://www.pexels.com/" target="_blank">Pexels</a>, a website with CC-0 pictures, that I even learnt to scrape for an unpublished (yet) project. So many photographs you can use and modify for free without any attribution! Quite cool, really. To scrape the page I first had to scroll down to get enough pictures, which I did following <a rel="nofollow" href="https://stackoverflow.com/questions/29861117/r-rvest-scraping-a-dynamic-ecommerce-page" target="_blank">this Stack Overflow thread</a> with <code>RSelenium</code>. I tried using <code>seleniumPipes</code> instead but had trouble setting up the server and not too much time to dwell on that.</p>
<p>Yes, you got it right, the code below automatically downloads pics of puppies into your laptop. Happy New Year.</p>
<div>
<div>
<pre><code><span>library</span><span>(</span><span>&quot;rvest&quot;</span><span>)</span><span>
</span><span>library</span><span>(</span><span>&quot;RSelenium&quot;</span><span>)</span><span>
</span><span>library</span><span>(</span><span>&quot;magrittr&quot;</span><span>)</span><span>
</span><span># https://stackoverflow.com/questions/29861117/r-rvest-scraping-a-dynamic-ecommerce-page</span><span>
</span><span>rD</span><span> </span><span>&lt;-</span><span> </span><span>rsDriver</span><span>()</span><span>
</span><span>remDr</span><span> </span><span>&lt;-</span><span> </span><span>rD</span><span>[[</span><span>&quot;client&quot;</span><span>]]</span><span>
</span><span># open the webpage</span><span>
</span><span>remDr</span><span>$</span><span>navigate</span><span>(</span><span>&quot;https://www.pexels.com/search/puppies/&quot;</span><span>)</span><span>
</span><span># scroll down</span><span>
</span><span>for</span><span>(</span><span>i</span><span> </span><span>in</span><span> </span><span>1</span><span>:</span><span>30</span><span>){</span><span> </span><span>remDr</span><span>$</span><span>executeScript</span><span>(</span><span>paste</span><span>(</span><span>&quot;scroll(0,&quot;</span><span>,</span><span>i</span><span>*</span><span>10000</span><span>,</span><span>&quot;);&quot;</span><span>),</span><span>
</span><span>args</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>&quot;dummy&quot;</span><span>))</span><span>
</span><span># be nice and wait</span><span>
</span><span>Sys.sleep</span><span>(</span><span>1</span><span>)</span><span> </span><span>}</span><span>
</span><span>page_content</span><span> </span><span>&lt;-</span><span> </span><span>remDr</span><span>$</span><span>getPageSource</span><span>()</span><span> </span><span>remDr</span><span>$</span><span>close</span><span>()</span><span>
</span><span># functiosn for getting the pic links</span><span>
</span><span>get_link_from_src</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>node</span><span>){</span><span>
</span><span>xml2</span><span>::</span><span>xml_attrs</span><span>(</span><span>node</span><span>)[</span><span>&quot;src&quot;</span><span>]</span><span> </span><span>%>%</span><span>
</span><span>as.character</span><span>()</span><span> </span><span>%>%</span><span>
</span><span>stringr</span><span>::</span><span>str_replace</span><span>(</span><span>&quot;\\?h.*&quot;</span><span>,</span><span> </span><span>&quot;&quot;</span><span>)</span><span>
</span><span>}</span><span>
</span><span>xtract_pic_links</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>source</span><span>)</span><span> </span><span>{</span><span>
</span><span>css</span><span> </span><span>&lt;-</span><span> </span><span>'.photo-item__img'</span><span>
</span><span>read_html</span><span>(</span><span>source</span><span>[[</span><span>1</span><span>]])</span><span> </span><span>%>%</span><span>
</span><span>html_nodes</span><span>(</span><span>css</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>purrr</span><span>::</span><span>map_chr</span><span>(</span><span>get_link_from_src</span><span>)</span><span> </span><span>}</span><span>
</span><span>links</span><span> </span><span>&lt;-</span><span> </span><span>xtract_pic_links</span><span>(</span><span>page_content</span><span>)</span><span>
</span><span>links</span><span> </span><span>&lt;-</span><span> </span><span>links</span><span>[</span><span>1</span><span>:</span><span>nrow</span><span>(</span><span>puppies_and_cats</span><span>)]</span><span>
</span><span># save</span><span>
</span><span>dir.create</span><span>(</span><span>&quot;data/puppies&quot;</span><span>)</span><span>
</span><span>save_pic</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>url</span><span>,</span><span> </span><span>name</span><span>){</span><span>
</span><span>Sys.sleep</span><span>(</span><span>1</span><span>)</span><span>
</span><span>name</span><span> </span><span>&lt;-</span><span> </span><span>paste0</span><span>(</span><span>&quot;puppy&quot;</span><span>,</span><span> </span><span>name</span><span>,</span><span> </span><span>&quot;.png&quot;</span><span>)</span><span>
</span><span>try</span><span>(</span><span>magick</span><span>::</span><span>image_read</span><span>(</span><span>url</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>magick</span><span>::</span><span>image_write</span><span>(</span><span>paste0</span><span>(</span><span>&quot;data/puppies/&quot;</span><span>,</span><span> </span><span>name</span><span>)),</span><span>
</span><span>silent</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span>
</span><span>}</span><span>
</span><span>purrr</span><span>::</span><span>walk2</span><span>(</span><span>links</span><span>,</span><span> </span><span>1</span><span>:</span><span>nrow</span><span>(</span><span>puppies_and_cats</span><span>),</span><span> </span><span>save_pic</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p>I took a moment to browse the 66 pics. Carpe diem, carpe canes (I learnt Latin for 6 years as a teen(ager) and had to check the plural of <em>canem</em>…).</p>
<p>The pics were a bit too big so I resized them.</p>
<div>
<div>
<pre><code><span>resize</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>pic</span><span>){</span><span>
</span><span>magick</span><span>::</span><span>image_read</span><span>(</span><span>pic</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>magick</span><span>::</span><span>image_resize</span><span>(</span><span>&quot;300x300&quot;</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>magick</span><span>::</span><span>image_write</span><span>(</span><span>pic</span><span>)</span><span>
</span><span>}</span><span>
</span><span>purrr</span><span>::</span><span>walk</span><span>(</span><span>dir</span><span>(</span><span>&quot;data/puppies/&quot;</span><span>,</span><span> </span><span>full.names</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>),</span><span> </span><span>resize</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<h1>Tweeting the cheerful tweets – DON’T DO IT LIKE I DID!</h1>
<p>I created <a rel="nofollow" href="https://twitter.com/cheerful_doggos" target="_blank">a Twitter account for the Bubblegum Puppies</a> so that they could interact with the Black Metal Cats in their natural environment. I was asked by Scott whether I’d make a bot out of my idea and I don’t intend to especially since my simplistic strategy can only answer tweets with negative words detected, but I’d be glad to let someone adopt the account, especially since I did not educate my puppies well to begin with as you see below! <a rel="nofollow" href="https://www.wjakethompson.com/post/tidyverse-tweets/" target="_blank">Here</a> is a tutorial for making a Twitter bot with <code>rtweet</code>. In the meantime, I simply decided to tweet the answers I had created… without enough thinking.</p>
<p><em>Note: It has been a long since I last obtained Twitter access tokens, so I refered to <a rel="nofollow" href="http://rtweet.info/articles/auth.html" target="_blank">the vignette</a>.</em></p>
<p>Then I wrote the code to send replies, an important point being that you need to mention the username you answer to in your tweet otherwise the <code>in_reply_to_status_id</code> argument is ignored. It was a dangerous code because it sent too many replies, which made it a spam bot… Don’t do that. So if you ever need an example of a very stupid spammer, think of me. Lesson learnt, I’ll never be that reckless again, because I do not want to spam anyone.</p>
<div>
<div>
<pre><code><span>post_a_reply</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>df</span><span>,</span><span> </span><span>pic</span><span>){</span><span>
</span><span>rtweet</span><span>::</span><span>post_tweet</span><span>(</span><span>paste</span><span>(</span><span>&quot;@evilbmcats&quot;</span><span>,</span><span> </span><span>df</span><span>$</span><span>new_text</span><span>),</span><span> </span><span>in_reply_to_status_id</span><span> </span><span>=</span><span> </span><span>df</span><span>$</span><span>status_id</span><span>,</span><span>
</span><span>media</span><span> </span><span>=</span><span> </span><span>pic</span><span>)</span><span>
</span><span>Sys.sleep</span><span>(</span><span>1</span><span>)</span><span>
</span><span>}</span><span>
</span><span>pics</span><span> </span><span>&lt;-</span><span> </span><span>dir</span><span>(</span><span>&quot;data/puppies/&quot;</span><span>,</span><span> </span><span>full.names</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span>
</span><span>purrr</span><span>::</span><span>walk2</span><span>(</span><span>split</span><span>(</span><span>puppies_and_cats</span><span>,</span><span> </span><span>puppies_and_cats</span><span>$</span><span>status_id</span><span>),</span><span> </span><span>pics</span><span>,</span><span>
</span><span>post_a_reply</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p>So how would I use the tweets if I could do it again? Well, I’d post them with a faaar bigger delay. And I think the account would be fun as a bot which’d reply only when the cats account tweets again. That way the puppies would be cute, not cute and annoying. Live and learn! Thanks to Bob Rudis to encourage me to post this!</p>
<h1>Ending with some cuteness</h1>
<p>And now, because I do not want you to think I’m now as depressed as a Black Metal Cat, I’ll end this post by showing you a few replies thanks to the brand new <code>rtweet::tweet_shot</code> function added in the dev version of <code>rtweet</code> by <a rel="nofollow" href="https://twitter.com/hrbrmstr?lang=en" target="_blank">Bob Rudis</a> after he saw my <a rel="nofollow" href="http://www.masalmon.eu/2017/12/30/best9of2017/" target="_blank">#best9of2017 post</a>. I resorted to saving the files and add the Markdown code to show them by hand but in a normal Rmd, not in a website, the images (<code>magick</code> objects) actually render very well. <a rel="nofollow" href="https://twitter.com/cheerful_doggos/with_replies" target="_blank">Head to Twitter</a> to see the rest!</p>
<div>
<div>
<pre><code><span>save_one_tweet</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>status_id</span><span>){</span><span>
</span><span>rtweet</span><span>::</span><span>tweet_shot</span><span>(</span><span>status_id</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>magick</span><span>::</span><span>image_write</span><span>(</span><span>paste0</span><span>(</span><span>&quot;data/2018-01-04-&quot;</span><span>,</span><span>
</span><span>status_id</span><span>,</span><span> </span><span>&quot;.png&quot;</span><span>))</span><span>
</span><span>}</span><span>
</span><span>c</span><span>(</span><span>&quot;948942337912328192&quot;</span><span>,</span><span>
</span><span>&quot;948942293272334336&quot;</span><span>,</span><span>
</span><span>&quot;948942240713531392&quot;</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>purrr</span><span>::</span><span>walk</span><span>(</span><span>save_one_tweet</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p><img alt="" src="https://i0.wp.com/raw.githubusercontent.com/maelle/maelle.github.io/master/_source/data/2018-01-04-948942337912328192.png?w=456&ssl=1" data-recalc-dims="1"></p>
<p><img alt="" src="https://i2.wp.com/raw.githubusercontent.com/maelle/maelle.github.io/master/_source/data/2018-01-04-948942293272334336.png?w=456&ssl=1" data-recalc-dims="1"></p>
<p><img alt="" src="https://i2.wp.com/raw.githubusercontent.com/maelle/maelle.github.io/master/_source/data/2018-01-04-948942240713531392.png?w=456&ssl=1" data-recalc-dims="1"></p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://www.masalmon.eu/2018/01/04/bubblegumpuppies/"> Maëlle</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/IDXzUzEKB9s" height="1"></a></div>