Scraping Marvel Comics
Contributed by Christopher Redino. He is currently in the NYC Data Science Academy 12 week full time Data Science Bootcamp program taking place between January 11th to April 1st, 2016. This post is based on his third class project – Web scraping (due on the 6th week of the program).
Comic book fans love showing off their knowledge of their hobby. Knowing which characters appeared in which issues, when certain meet ups and throw downs occurred; their familiarity with the extensive history of these characters reflects their passion for comics. Stated another way, comic book fans love data! Strong evidence of this is the extensive and thorough Marvel Database, a wiki that catalogs characters, teams, locations, events, and issues from Marvel Comics. The main continuity of stories that appear in Marvel comics has been in existence for over 75 years, and their stories contain thousands of characters, so there is a lot of data here, but with a short and simple Python script we can scrape this data and create some illustrative visualizations.
This project focuses on appearance data; in which issues do certain characters appear. This can be interesting for a few reasons. The total number of appearances acts as a proxy for the popularity of a character, the more popular a character is, the more issues they will appear in. More popularity means longer lasting solo runs, more appearances on teams, more cameos and team ups in other's comics, and if they are really popular, additional solo titles. Appearance data can also tell us which characters have appeared together most frequently in Marvel's long history, and can tell us about the relative make up of teams and how these rosters have changed over the decades.
Getting the Data
Wikis tend to be very well organized, which makes web scraping substantially easier. We can reasonably expect the same information to appear in the same place on every page. The whole script is rather short and is shown here in its entirety. Ignoring team data for now, this short script is all we need.
The script begins by specify which characters I am interested in learning about. Here I just pick five of the more popular characters: Captain America, Spider-Man, Wolverine, Iron Man and Thor, but other characters can be added as well. The script will go through each character one at a time, but the procedure for each character is the same. Each character has their own main page on the wiki, for example we have Spider-Man's page:
It has some stats, some personal info, and a brief bio of the character, but the part we are interested in is towards the bottom which has a variety of links related to the character.
The appearances link takes us to a separate page which lists links to issues where the character has appeared.
We want the script to save each of these issue links to a list, and then go to the next page of issue links for this character and repeat the process until all the pages are exhausted. This is easier than it sounds as looking at the source we see the html is very organized.
Once the script has the list of issue links, it goes to each of these pages where we can find the release date of that issue.
When the script is done running we are left with a csv file that for each row lists the issue title, the character that appears in it, and the date of its release. If two of the characters we are interested in both appear Fin the same issue, it will appear as two separate rows in the data.
Before moving on to the visualization results of this data, it should be specified what exactly we have scraped by running this script. You'll notice that when the characters are specified, for example for Spider-Man, it does not say "spider-man" in the URL, but rather, it says "Peter Parker" and further more for each character's URL you'll notice it says "Earth 616". This specifies two things: we are only considering the Spider-Man character that is Peter Parker, and we are only considering the main continuity of the comic books. For all five characters scraped here, and for many more popular comic book characters, it is very common for the for super hero mantle to passed on to other characters, either as a legacy, or at least temporarily. Peter Parker is not the only "Spider-Man" of the comics, and there have in fact been several others, Miles Morales (from another universe), Ben Reilly ( a clone of Peter Parker), Miguel O'Hara (from the future), and many others, but we are only considering the original or "classic" version of each character here. The designation "616" specifies the continuity of the story, meaning there are other appearances of Peter Parker in some stories which are not in a consistent storyline with those scraped here. For those unfamiliar with comics, this is like when a studio reboots a movie franchise. Bela Legosi and Christopher Lee both play the same character of Count Dracula, but there separate movies share no continuity with one another.
With the appearance data we can look at a few different things, as mentioned in the motivation. Since the Python Script outputs a csv, I can then open the data with any other software I want to do the visualization, and in this case, since this is really time series data, I chose to use the dygraphs library as implemented in R to make interactive plots of the appearances of characters over time. The interactive plots can be found here, and your invited to play with them.
The first plot shows appearances per month for the five characters, over the entire history of marvel comics. Captain America has a bit of a head start, originally appearing in the 1940's with Wolverine coming in the latest among these heavy hitters. As mentioned earlier, this is sort of a proxy for popularity, and onne may think that taking the total appearance count as a measure of popularity is flawed, since some characters are introduced so much earlier. I think this plot addresses this issues somewhat by showing that the overall trend of more titles being published in general greatly out weighs this. While Captain America did have over a 20 year head start on most other characters, there really weren't that many titles released back then, at least not compared to the rate of release today.
It is also interesting to look at this graph in terms of what other events happened at each of these dates, both within the continuity of the stories, and also with what has happening in the real world at the time. Deaths of comic book characters this popular do not actually reduce their monthly appearances, and each of these characters has experienced death in some form in their history. While death in comic books is more a temporary set back rather than a final ending, even while characters remain "dead" they will appear in stories via flash backs. Outside of the continuity of stories in the comics, the release of related movies clearly coincides with an increase in appearances. Perhaps the best example in this plot is the surge in Iron Man's appearances following his 2008 movie, but other examples can be found.
With a bit of reshaping we can produce another plot from the same data. The data shows when characters appear in each issue, and also two characters or more can appear in the same issue, so with the right manipulations we can show a time line of each grouping of characters. The groupings themselves are categories, which duos, trios or quartets appeared in each issue, but dygraphs expects numerical data, so we simply assign a different numerical value to each different grouping. It would also be nice if the groupings were sorted by there size, that is, if duos and trios were visually separated in our plot, so that the numerical values we assigned to these groups had some categorical meaning. This can be achieved by considering the numerical value of the group as a binary number, with each bit being the presence or absence of each character. To sort these values by duo trio, etc, we can sort on the sum of bits. Furthermore, to prevent over plotting (drawing one point over another) we can stagger these values between characters, that is to say if Captain America and Iron Man appear in an issue together than those appearances should have simliar but not identical group ID numbers. The a screen shot of the resulting interactive plot is given below, but please check out the interactive plot at the link given above. The vertical axis just denotes the category of the groupings, so it is unimportant. The way the plot should be read is that if two dots appears close together vertically then those two characters had at least one appearance together in an issue on that date. The bottom five lines are solo appearances, so these are well spaced. The band of double lines above the solo appearances are all the pairings that appeared at each date, and above this the trios, and so on, with the top band of five tight lines being those issue dates where all five characters appeared together.
There are actually quite a few patterns that can be extracted from this plot. Some combinations of characters are much more frequent, and some are much more rare. Some combinations become more frequent with time, and sometimes two characters will only appear together if a third character is present. A lot of this can be explained by team dynamics; the band of blue yellow gray shows the three long time Avengers, Cap, Iron Man and Thor have appeared together consistently without the other two until recently. Spider-Wolverine do eventually become Avengers, and there increased team ups over time can be seen.
The last two plots show membership in the Avengers over time. This required a slightly modified version of the Python script shown above, but the basic idea is the same. Instead of saving those issues and dates for which a character appears, it saves the issues and date for which the team the avengers appears, and if one or more of these five characters of interest appeared as an avenger in that issue that is also saved. The first of these team membership plots just shows a running total of appearances as an avenger over time, and we can see how Captain America has a little bit of a late start, (just a few issues) but quickly becomes the most active Avenger, with Spider-Man and Wolverine only joining much more recently.
The second team plot is showing the same information as the first, except instead of a running total of appearances it shows the percent the relative share of appearances as an avenger over time. Again at first Iron Man and Thor both have 50% of all avengers appearances, (among the characters considered) but towards today Captain America has over a third, with Iron Man and Thor having less than a third each and Spidey and Wolverine having a small remainder.
A wiki cataloging such a long history of media, such as the Marvel Database is a very natural choice for a data set to be visualized as a time series, and while there are some interesting visualizations shown here, there are a lot of ways this could be expanded. The inclusion of more characters and other teams is very straightforward so let me know who you want to see in the comments! At the very least I think I should add the Hulk so I can put some green in these plots. The characters shown here are all amongst the most popular in Marvel's library, so it should not be surprising that their trends over time look largely the same. Looking at less popular characters could be interesting because we could see their rise and fall, and in some cases their resurgence. It would also be very cool if I could implement the functionality to actually show the issue title with mouse over on these plots (perhaps not with dygraphs, but something similar).