Introduction
More and more information from local, state and federal governments is being placed on the web. However, a lot of the data is not presented in a way that is easy to download and manipulate. I think it is an important civic duty for us all to be aware of how government money is spent. Having the data in a more accessible format is a first step in that process.
In this article, I’ll use BeautifulSoup to scrape some data from the Minnesota 2014 Capital Budget. Then I’ll load the data into a pandas DataFrame and create a simple plot showing where the money is going.
My purpose in writing this is not to make any specific political statements about this data set. I chose this data because:
I personally found it interesting
I think it translates well across other states and across the world
It highlights several useful python tools both in and outside of the stdlib
The process is applicable to other domains outside of government data
It is a manageable size so you can understand it using basic tools
The Data
I live in MN so thought I would take a look at what sort of budget information is available to us via the various state websites. To be honest, there is a lot of information but it seems like the vast majority is stored in a PDF or on an HTML page.
I applaud the state for making the data available but it is not easy to analyze the data in the way it is currently presented. As I looked through the Minnesota government website, I found this 2014 Capital Budget page which is actually pretty straightforward to understand.
The first part of the document contains a high level summary of all the projects receiving capital dollars as well as how the capital budget will be funded.
The second part of the document has a lot of detail on each of the summary items. For the purpose of this exercise, I am only going to scrape the summary section but the same basic principle can be applied to the detailed line items.
One final note, I realize that this data set is not that large and that you could easily type it all into Excel. However, if we were to scale this to pull in more data, you quickly get to the point where hand typing the data just does not make sense. The principles I walk through will scale to much larger sets. I hope it has the added bonus that you will learn something as well. I know I enjoyed working on this little project.
The Tools
For this particular task, I am going to use 2 very common python tools for scraping the site:
BeautifulSoup to parse the data
Requests to get the data from the website.
Strictly speaking, Requests is not being used for much in this case but I think it makes sense to start using it. If/when you start getting more complicated situations, you’ll be happy you are already using it.
Scrapy is another powerful tool for doing web scraping but for my needs BeautifulSoup was perfect so that’s what I’m sticking with for this article. Maybe I’ll look at it for a future article.
Once I scrape the data, I’ll convert it to a pandas DataFrame so that I can analyze and plot the data.
One final note, I’m trying to use idiomatic python as much as possible. My current environment is python 2.7 but I’ll use the print_function to make the python 3 conversion much easier. Also, I’m going to use the defaultdict to streamline the processing of the data. This was first introduced in python 2.5 and is pretty handy when working with dictionaries where the values are lists.
Now we need to initialize the variables. I’m going to use two dictionaries. One will store all of the expense items and the other will include the funding source. Note, I am not going to store the total. We can calculate it so we’ll skip that piece of data. I am using the defaultdict to make it easy to append the values I scrape:
Use requests to get the data and pass it to BeautifulSoup. In my final script, I’m going to store the HTML to disk so that I don’t need to hit the website every time I run it. I won’t show it in this section in order to keep the code short.
Understand Your HTML
The key to understanding any scraping is looking at the HTML and understanding how you want to pull your data out.
In this case, I downloaded the HTML into an editor and collapsed some of the data. It is very helpful that there is a div that wraps the data I need:
Within that div, there are mutliple tables which ultimately contain the info we need:
In the example above, we want to parse out two pieces of data - the description (Universty of Minnesota) and the amount (119,367,000). Another item to note is that the number comes through with commas as well as parenthesis for negative values so we are going to need to clean it up a little. I also found that I pulled in a lot of extra white space in the process, so using string.strip is a good idea.
Here is the clean up function we’ll use:
Now that we know how to get to our tables, use BeautifulSoup’s powerful API to get at our data.
Parse each row in the table and add to the appropriate dictionary depending on whether it is a funding line or expense line
Convert the Data
Our dictionaries contain the data we need, let’s add them to a pandas DataFrame using DataFrame.from_dict() :
It looks like everything was processed correctly. Now, we can analyze the data any way we want.
Plot The Data
In this specific case, I am going to generate a simple horizontal bar graph so that it is easy to see where the biggest expenditures are.
First, I’ll sort both sets of data:
Regardless of the format, I think you’ll agree that viewing the capital budget in this plot yields a lot more insight than the raw HTML data.
Final Thoughts
This little project has been useful for me and I hope it provides a starting point for you to understand how to use various python tools to scrape the web. In this case, I learned a little bit that I think could be applicable to lots of other projects. I also am curious about this little slice of data and intend to look into it some more and see what insight I can glean.
For reference, here is the complete code for this example. This version will download the data to a file and use that locally instead of hitting the site each time.
Source: http://pbpython.com/web-scraping-mn-budget.html
More and more information from local, state and federal governments is being placed on the web. However, a lot of the data is not presented in a way that is easy to download and manipulate. I think it is an important civic duty for us all to be aware of how government money is spent. Having the data in a more accessible format is a first step in that process.
In this article, I’ll use BeautifulSoup to scrape some data from the Minnesota 2014 Capital Budget. Then I’ll load the data into a pandas DataFrame and create a simple plot showing where the money is going.
My purpose in writing this is not to make any specific political statements about this data set. I chose this data because:
I personally found it interesting
I think it translates well across other states and across the world
It highlights several useful python tools both in and outside of the stdlib
The process is applicable to other domains outside of government data
It is a manageable size so you can understand it using basic tools
The Data
I live in MN so thought I would take a look at what sort of budget information is available to us via the various state websites. To be honest, there is a lot of information but it seems like the vast majority is stored in a PDF or on an HTML page.
I applaud the state for making the data available but it is not easy to analyze the data in the way it is currently presented. As I looked through the Minnesota government website, I found this 2014 Capital Budget page which is actually pretty straightforward to understand.
The first part of the document contains a high level summary of all the projects receiving capital dollars as well as how the capital budget will be funded.
The second part of the document has a lot of detail on each of the summary items. For the purpose of this exercise, I am only going to scrape the summary section but the same basic principle can be applied to the detailed line items.
One final note, I realize that this data set is not that large and that you could easily type it all into Excel. However, if we were to scale this to pull in more data, you quickly get to the point where hand typing the data just does not make sense. The principles I walk through will scale to much larger sets. I hope it has the added bonus that you will learn something as well. I know I enjoyed working on this little project.
The Tools
For this particular task, I am going to use 2 very common python tools for scraping the site:
BeautifulSoup to parse the data
Requests to get the data from the website.
Strictly speaking, Requests is not being used for much in this case but I think it makes sense to start using it. If/when you start getting more complicated situations, you’ll be happy you are already using it.
Scrapy is another powerful tool for doing web scraping but for my needs BeautifulSoup was perfect so that’s what I’m sticking with for this article. Maybe I’ll look at it for a future article.
Once I scrape the data, I’ll convert it to a pandas DataFrame so that I can analyze and plot the data.
One final note, I’m trying to use idiomatic python as much as possible. My current environment is python 2.7 but I’ll use the print_function to make the python 3 conversion much easier. Also, I’m going to use the defaultdict to streamline the processing of the data. This was first introduced in python 2.5 and is pretty handy when working with dictionaries where the values are lists.
Now we need to initialize the variables. I’m going to use two dictionaries. One will store all of the expense items and the other will include the funding source. Note, I am not going to store the total. We can calculate it so we’ll skip that piece of data. I am using the defaultdict to make it easy to append the values I scrape:
Use requests to get the data and pass it to BeautifulSoup. In my final script, I’m going to store the HTML to disk so that I don’t need to hit the website every time I run it. I won’t show it in this section in order to keep the code short.
Understand Your HTML
The key to understanding any scraping is looking at the HTML and understanding how you want to pull your data out.
In this case, I downloaded the HTML into an editor and collapsed some of the data. It is very helpful that there is a div that wraps the data I need:
Within that div, there are mutliple tables which ultimately contain the info we need:
In the example above, we want to parse out two pieces of data - the description (Universty of Minnesota) and the amount (119,367,000). Another item to note is that the number comes through with commas as well as parenthesis for negative values so we are going to need to clean it up a little. I also found that I pulled in a lot of extra white space in the process, so using string.strip is a good idea.
Here is the clean up function we’ll use:
Now that we know how to get to our tables, use BeautifulSoup’s powerful API to get at our data.
Parse each row in the table and add to the appropriate dictionary depending on whether it is a funding line or expense line
Convert the Data
Our dictionaries contain the data we need, let’s add them to a pandas DataFrame using DataFrame.from_dict() :
It looks like everything was processed correctly. Now, we can analyze the data any way we want.
Plot The Data
In this specific case, I am going to generate a simple horizontal bar graph so that it is easy to see where the biggest expenditures are.
First, I’ll sort both sets of data:
Regardless of the format, I think you’ll agree that viewing the capital budget in this plot yields a lot more insight than the raw HTML data.
Final Thoughts
This little project has been useful for me and I hope it provides a starting point for you to understand how to use various python tools to scrape the web. In this case, I learned a little bit that I think could be applicable to lots of other projects. I also am curious about this little slice of data and intend to look into it some more and see what insight I can glean.
For reference, here is the complete code for this example. This version will download the data to a file and use that locally instead of hitting the site each time.
Source: http://pbpython.com/web-scraping-mn-budget.html