A Stitch in TWiME Saves Nine

A few people have asked how I assemble each week's "This Week in Math Ed" (TWiME) post, so here's my explainer. It's a good time for me to do this, as this weekend I finally found a way to automate some things.

The Data

For the "Math Ed Said" section of TWiME, I list each day's most-shared post from my list of 1600+ math educators on Twitter. I've been curating this list for years, and by keeping it open in Tweetdeck right next to my timeline it's allowed me to keep my following list smaller and more subject-diverse, while still seeing a big chunk of what math teachers might be talking about in the list. Right now 228 people subscribe to this list, and I do try to keep it curated by only adding people if I see they frequently tweet about math ed. I occasionally have to remove someone if I notice their interests have gone elsewhere.

For the "Research Notes" section of TWiME, I simply have a bookmarks folder with 30+ journals in it. Each week, Chrome questions my sanity with this:

Opening many tabs in Chrome
Opening many tabs in Chrome


From there, I look through every latest journal issue. Most of the time I can recognize if it hasn't been updated since the previous week. If it's new, I open every article page in preparation for inclusion in TWiME.

For the "Math Ed in the News" section, I added a "math education" topic to Google News and personalized Google News to show me an above-average number of math ed stories.

For anything else, it's something I've come across on my own or had emailed to me, as is the case with much of my Colorado news.

My Tools

TWiME, in its current form, is largely possible due to Nuzzel. Nuzzel does the hard work of watching my Twitter list and tracking what gets shared. Nuzzel does have a newsletter feature, but I've never found those kinds of things very popular or attractive.

Nuzzel
Nuzzel


For most of my writing destined for the web, I use Draft. If you've ever thought, "I wish I had something like Google Docs, but simpler, that let me write in Markdown, and could freeze revisions of my writing in time to compare with later," then you're looking for Draft. I can convert Markdown to HTML with Draft, or with any number of other tools.

Draft
Draft


Making links in Markdown is easier than in HTML:

[This is my Twitter profile](https://twitter.com/MathEdnet)

Typing these out was pretty tedious, so the "Copy as Markdown" Chrome extension has been a great timesaver.

Links in TWiME, One at a Time

I try to set aside most of my Fridays for assembling each TWiME, with most of that time spent reading. Still, with around 100 links in each TWiME post, I end up doing this over and over and over:

Copying links from Nuzzel
Copying links from Nuzzel


There's no keyboard shortcut in Copy as Markdown for this, but I can quickly paste in Draft with CTRL+v to produce a Markdown-formatted link:

[John Golden](http://twitter.com/mathhombre)

I've done it this way almost since the beginning. It's tedious. After months of meaning to find a better way, I finally spent the time that will save me time.

Links in TWiME, Saving Time

Instead of getting TWiME out on Friday, I started exploring how I might automate the "shared by" links in the "Math Ed Said" section. First, I checked out the Nuzzel source and found this:

Nuzzel HTML source
Nuzzel HTML source


There's a ton of whitespace in the Nuzzel HTML, but that's no big deal. The big deal is the "externalUserLink" class, which I could search for to isolate the links to Twitter profiles. I started by saving the source into a text file and using simple cat and grep Linux commands:

johnson@flatiron:~/Documents/MathEdnet$ cat nuzzel-source.txt | grep "externalUserLink"
<a class="externalUserLink" target="_blank" href="http://twitter.com/klsilverman">Kirsten Silverman</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/mr_stadel">Andrew Stadel</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/mathhombre">John Golden</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/mathycathy">Cathy Yenca </a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/saravdwerf">Sara VanDerWerf</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/jenblinzler">Jennifer Blinzler</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/jensilvermath">Jen Silverman</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/jensilvermath">Jen Silverman</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/ddmeyer">Dan Meyer</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/NancyTerryMath">Nancy Terry</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/mathhombre">John Golden</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/BridgetDunbar">Bridget Dunbar</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/AllisonPeet">Allison Peet</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/bstockus">Brian Bushart</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/BeckyAfghani">Rebecca Afghani</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/laura_wagenman">Laura Wagenman</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/WIMathCouncil">WMC - WI MathCouncil</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/TCM_at_NCTM">TCM - NCTM</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/KristinFrang">Kristin Frang</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/MathCoachCorner">Donna Boucher</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/jody_guarino">Jody Guarino</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/MathMinds">Kristin Gray</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/NancyTerryMath">Nancy Terry</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/MatthewMaddux">Egan J Chernoff</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/quantgal67">Laurie Hailer</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/ilana_horn">Ilana Horn</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/maanow">MAA</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/CmonMattTHINK">Matt Enlow</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/bkdidact">Andrew Gael</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/pmacoun">Phil Macoun</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/NancyTerryMath">Nancy Terry</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/Vanes63">Vanessa Garcia</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/bstockus">Brian Bushart</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/ryan_psmith">Ryan Smith</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/geogebra">GeoGebra</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/ProfNoodlearms">TJ Hitchman</a>
<a class="externalUserLink" target="_blank" href="http://twitter.com/j_lanier">Justin Lanier</a

Bingo! That gave me all the "shared by" links on the entire page, and I could manually pick out the ones that matched the most-shared story. Unfortunately, the links aren't in Markdown, and I don't need the class and target parameters in my links. I've done a lot of scripting in Bash and could probably figure out how to do the reformatting, but something told me this was an opportunity to push myself to get more Python experience.

Switching to Python meant I needed equivalent tools for things like grep and cut, which I found explained on Stack Overflow. I've read files line-by-line in Python before, so I could reuse those lines of code from previous projects. Then a thought struck me: Instead of saving the Nuzzel HTML source as a file, how difficult would it be for the script to grab the source itself?

Answer: Really easy. Like "add a library and two lines of code" easy. It's handled by the urllib2 Python module. Before long, I had a script that asked me for a date, fetched the page, then parsed line-by-line looking for storyTitle and externalUserLink with some if statements:

#!/usr/bin/python
import os, sys, string, urllib2

base = "http://nuzzel.com/MathEdnet/mathed?sort=friends&when="
date = raw_input('Enter date, Nuzzel-style: ')
url = base+date

f = urllib2.urlopen(url)

for line in f:
    if "storyTitle" in line:
        url = line.split('"')[7]
        title = line.split('>')[2]
        title = title.split('<')[0]
        print "\n"
        print "**Date**: "+"["+title+"]"+"("+url+")"+"\n\n"+"*Shared by:",
    if "externalUserLink" in line:
        url = line.split('"')[3]
        name = line.split('>')[1]
        name = name.split('<')[0]
        print "["+name+"]"+"("+url+"),",

In 21 lines, I ask for the date, construct the URL, get the source, then find/isolate/format both the story title and the shared-by links. The split command cuts the line into pieces, with me telling it which piece I want. (I'm so glad Nuzzel is consistent with its formatting!) When the script is run, I get this output:

johnson@flatiron:~/Documents/MathEdnet$ bin/sharers.py 
Enter date, Nuzzel-style: 10212016

**Date**: [Marcellus the Giant](http://blog.mrmeyer.com/2016/marcellus-the-giant/)

*Shared by: [Kirsten Silverman](http://twitter.com/klsilverman), [Andrew Stadel](http://twitter.com/mr_stadel), [John Golden](http://twitter.com/mathhombre), [Cathy Yenca ](http://twitter.com/mathycathy), [Sara VanDerWerf](http://twitter.com/saravdwerf), [Jennifer Blinzler](http://twitter.com/jenblinzler), [Jen Silverman](http://twitter.com/jensilvermath), [Jen Silverman](http://twitter.com/jensilvermath), [Dan Meyer](http://twitter.com/ddmeyer), [Nancy Terry](http://twitter.com/NancyTerryMath), 

**Date**: [Math with Bad Drawings](http://bstockus.wordpress.com/2016/10/20/math-with-bad-drawings/)

*Shared by: [John Golden](http://twitter.com/mathhombre), [Bridget Dunbar](http://twitter.com/BridgetDunbar), [Allison Peet](http://twitter.com/AllisonPeet), [Brian Bushart](http://twitter.com/bstockus), [Rebecca Afghani](http://twitter.com/BeckyAfghani), [Laura Wagenman](http://twitter.com/laura_wagenman), 

**Date**: [Addictive Game for Practicing Combinations for Ten](http://www.mathcoachscorner.com/2014/10/addictive-game-for-practicing-combinations-for-ten/)

*Shared by: [WMC - WI MathCouncil](http://twitter.com/WIMathCouncil), [TCM - NCTM](http://twitter.com/TCM_at_NCTM), [Kristin Frang](http://twitter.com/KristinFrang), [Donna Boucher](http://twitter.com/MathCoachCorner), 

**Date**: [Story Not Available At This Time](http://www.teachingchannel.org/blog/2016/10/21/illustrative-mathematics-collaborate/)

*Shared by: [Jody Guarino](http://twitter.com/jody_guarino), [Kristin Gray](http://twitter.com/MathMinds), [Nancy Terry](http://twitter.com/NancyTerryMath), 

**Date**: [Turns Out, Counting on Your Fingers Makes You Smarter](http://www.wsj.com/articles/turns-out-counting-on-your-fingers-makes-you-smarter-1477065563)

*Shared by: [Egan J Chernoff](http://twitter.com/MatthewMaddux), [Laurie Hailer](http://twitter.com/quantgal67), [Ilana Horn](http://twitter.com/ilana_horn), 

**Date**: [Do You Love or Hate Math and Science?](http://www.quantamagazine.org/20161020-science-math-education-survey)

*Shared by: [MAA](http://twitter.com/maanow), [Matt Enlow](http://twitter.com/CmonMattTHINK), [Andrew Gael](http://twitter.com/bkdidact), 

**Date**: [Top 10 Tools for Creating Digital Quizzes](http://www.educatorstechnology.com/2016/10/top-10-tools-for-creating-digital.html)

*Shared by: [Phil Macoun](http://twitter.com/pmacoun), [Nancy Terry](http://twitter.com/NancyTerryMath), 

**Date**: [#ShadowCon16](http://bstockus.wordpress.com/shadowcon16/)

*Shared by: [Vanessa Garcia](http://twitter.com/Vanes63), [Brian Bushart](http://twitter.com/bstockus), 

**Date**: [Cat Maze](http://www.geogebra.org/m/Z3bry2pG)

*Shared by: [Ryan Smith](http://twitter.com/ryan_psmith), [GeoGebra](http://twitter.com/geogebra), 

**Date**: [Master of Liberal Arts - MALA - Graduate Program](http://www.sjc.edu/academic-programs/graduate/masters-liberal-arts)

*Shared by: [TJ Hitchman](http://twitter.com/ProfNoodlearms), [Justin Lanier](http://twitter.com/j_lanier),

The output isn't perfect, but it's close. What a huge timesaver! This gives me all the stories and Twitter links I want from the Nuzzel page, and I can manually copy the ones for top story into Draft. I'd need to make the dates right and trim the unnecessary comma at the end of the "Shared by" list while replacing it with an asterisk to make that text italicized. I had been listing the "shared by" from oldest to newest (bottom-up) in TWiME, which the script doesn't do since it's top-down, but I'm really not too concerned about the order.

Then again, I was having fun with my newfound script-fu at this point, and pressed on to find a way to (a) format the dates in the script and (b) grab all seven days at once. That led to this code:

#!/usr/bin/python
import os, sys, string, urllib2
from datetime import datetime, date, time

base = "http://nuzzel.com/MathEdnet/mathed?sort=friends&when="
d = raw_input('Enter date, Nuzzel-style, or enter \"week\": ')

if d != "week":

    url = base+d

    d = datetime.strptime(str(d), "%m%d%Y")
    d = d.strftime("%B %d")

    f = urllib2.urlopen(url)

    for line in f:
        if "storyTitle" in line:
            url = line.split('"')[7]
            title = line.split('>')[2]
            title = title.split('<')[0]
            print "\n"
            print "**"+d+"**: "+"["+title+"]"+"("+url+")"+"\n\n"+"*Shared by:",
        if "externalUserLink" in line:
            url = line.split('"')[3]
            name = line.split('>')[1]
            name = name.split('<')[0]
            print "["+name+"]"+"("+url+"),",

if d == "week":

    dt = raw_input('Enter first day of your week, Nuzzel-style: ')
    dt = datetime.strptime(str(dt), "%m%d%Y")

    d1 = dt
    d2 = dt.replace(day=dt.day+1)
    d3 = dt.replace(day=dt.day+2)
    d4 = dt.replace(day=dt.day+3)
    d5 = dt.replace(day=dt.day+4)
    d6 = dt.replace(day=dt.day+5)
    d7 = dt.replace(day=dt.day+6)

    d1=d1.strftime("%m%d%Y")
    d2=d2.strftime("%m%d%Y")
    d3=d3.strftime("%m%d%Y")
    d4=d4.strftime("%m%d%Y")
    d5=d5.strftime("%m%d%Y")
    d6=d6.strftime("%m%d%Y")
    d7=d7.strftime("%m%d%Y")

    sevendays = [d1, d2, d3, d4, d5, d6, d7]
    print sevendays

    for i in sevendays:

        url = base+i

        d = datetime.strptime(str(i), "%m%d%Y")
        d = d.strftime("%B %d")

        f = urllib2.urlopen(url)

        for line in f:
            if "storyTitle" in line:
                url = line.split('"')[7]
                title = line.split('>')[2]
                title = title.split('<')[0]
                print "\n"
                print "**"+d+"**: "+"["+title+"]"+"("+url+")"+"\n\n"+"*Shared by:",
            if "externalUserLink" in line:
                url = line.split('"')[3]
                name = line.split('>')[1]
                name = name.split('<')[0]
                print "["+name+"]"+"("+url+"),",

You'll see two big if blocks: the top one for dealing with just a single day, and the bottom one for dealing with the whole week. This script still grabs every story from each day, not just the top one, but I like to be able to see other popular stories so that's not a big deal to me. I'm a bit of a clutz with the date formatting. The documentation is pretty helpful, and I think a general lack of experience with Python modules and syntax trips me up or causes me to write more lines of code than I probably need. That's fine with a short script that I'm going to run once a week. It's already going to save me an hour or two, so I'm not worried about losing milliseconds of CPU time.

It feels pretty good to have produced some code that will make my life a little easier. Right now Colorado is in the beginning phases of creating a voluntary set of secondary computer science standards, and it's little projects like this that remind me that even a little bit of scripting knowledge can be powerful. It's something I think every student should have the opportunity to learn and pursue further if they so choose.