Scraping iTunes Charts Using Scrapy Python

By  on  

Hacking is more fun when you have some data to play with, but from where do you get data when you are just hacking for fun? I use web scraping to make my hacks interesting and cool and have learned a lot in the process. In this post, I will tell you about how to get started with web scraping using Scrapy.

Everyone is talking about Apple this week so let's begin by scraping iTunes. We will scrape iTunes Charts and get the list of the top free apps (along with their category, iTunes link, and image url).

I am assuming that you are familiar with basics of Python. As it is required to get most out of Scrapy. If not, I recommend you take a look at this list of the Python learning resources.

What is Scrapy?

Scrapy is a high level screen scraping and web crawling framework. It used for data mining and web crawling. It is written in pure Python.

So, let's start with setting up Scrapy on your machine. I m assuming that you have Python installed (required 2.7+), as of now Scrapy is not compatible with Python 3. If you do not have Python Installed, you can download it here. And setup `pip` for installing Scrapy:

Scrapy can be installed with:

$ pip install Scrapy

Or you can use easy_install:

$ easy_install Scrapy

Creating a project:

You can create a scrapy project using:

$ scrapy startproject apple

Since, I m writing a scraper for Apple iTunes, I created a project `apple`. This will create a `apple` directory, along with the following contents


	scrapy.cfg # the project configuration file

	apple/ # project module # items file # pipelines file # settings file

	spiders/ # all your spiders will be stored in this file

Well Scrapy did create a lot of files for us, there but you don't have to be worried looking at them.

The only files we are concerned with is the ‘' and the spiders. The ‘spiders' directory will store all the spiders for our project. In this case we will be creating ‘', that will have the logic for extracting items from iTunes pages.

Define Items to be stored:

The items act like simple Python dicts but they prevent against populating undeclared fields, for preventing typos.

Items will act as storage for the scraped data. This is where you define the attributes to Item by extending the scrapy.item.Item.

Here is how the will look like our project, we will be storing the `app_name`, the `category` of the app, the `appstore_link` and the `img_src` for the icon of the app, for each app:


from scrapy.item import Item, Field

class AppItem(Item):

	# define the fields for your item here like:
	app_name = Field()
	category = Field()
	appstore_link = Field()
	img_src = Field()

Writing the Spider:

Now we will add the logic to extract data from the webpages in our Spiders. Spiders are the classes that are used to extract data from webpages. It is created by extending `scrapy.spider.BaseSpider`

It is where you provide the initial list of `urls` to start scraping from, and how to extract data(Items) from webpages.

While creating a spider you need to define 3 required attributes.

name: identification of the spider (unique) (string)
start_urls: it is the list of urls, where the crawling starts from (list)
parse(): this is the method that gets the response object when the url is downloaded.

The parse() method is where we add the logic to extract the data(items) from webpages and follow more URLs if specified. Here we've used XPath to select the elements..

Scrapy provides this awesome Command line tool, that you can use to play with the `Response` Object, using XPath Selectors. So you don't have to create spiders to test your Xpath expressions.

This is the Spider for extracing the list of the apps from iTunes charts.

( in the spiders directory)

from scrapy.spider import BaseSpider
from scrapy.selector import HtmlXPathSelector

from apple.items import AppItem

class AppleSpider(BaseSpider):
    name = "apple"
    allowed_domains = [""]
    start_urls = [""]

    def parse(self, response):
        hxs = HtmlXPathSelector(response)
        apps ='//*[@id="content"]/section/ul/li')
        count = 0
        items = []

	for app in apps:

		item = AppItem()
		item['app_name'] ='//h3/a/text()')[count].extract()
		item['appstore_link'] ='//h3/a/@href')[count].extract()
		item['category'] ='//h4/a/text()')[count].extract()
		item['img_src'] ='//a/img/@src')[count].extract()

		count += 1

	return items

The command to start crawling:

$ scrapy crawl apple -o apps.json -t json

This will start the crawling, and the extracted items will be stored in apps.json with JSON as the feed exporter.

The Scrapy docs are available here.

Hope you will find this useful and do some cool things with Scrapy. Be careful about how you use the data you scrape from other websites though, you might be violating their privacy policy. 

The code for this post is available on GitHub.

Virendra Rajput

About Virendra Rajput

Virendra Rajput is a self-taught Python hacker. He is a Co-Founder of Markitty, a marketing recommendations and reminders tool for small businesses. He is obsessed with web technologies and the world of startups! His current love is Django.

Recent Features

  • By
    Facebook Open Graph META Tags

    It's no secret that Facebook has become a major traffic driver for all types of websites.  Nowadays even large corporations steer consumers toward their Facebook pages instead of the corporate websites directly.  And of course there are Facebook "Like" and "Recommend" widgets on every website.  One...

  • By
    39 Shirts – Leaving Mozilla

    In 2001 I had just graduated from a small town high school and headed off to a small town college. I found myself in the quaint computer lab where the substandard computers featured two browsers: Internet Explorer and Mozilla. It was this lab where I fell...

Incredible Demos

  • By
    DWRequest: MooTools 1.2 AJAX Listener & Message Display

    Though MooTools 1.2 is in its second beta stage, its basic syntax and theory changes have been hashed out. The JavaScript library continues to improve and become more flexible. Fellow DZone Zone Leader Boyan Kostadinov wrote a very useful article detailing how you can add a...

  • By
    Detect Vendor Prefix with JavaScript

    Regardless of our position on vendor prefixes, we have to live with them and occasionally use them to make things work.  These prefixes can be used in two formats:  the CSS format (-moz-, as in -moz-element) and the JS format (navigator.mozApps).  The awesome X-Tag project has...


  1. Chetan Dhembre

    very good post !! keep it up !!

  2. Hey Thanks Chetan! Glad you liked it :)

  3. Why in the world would you scrape for this data when iTunes provides an API for all the data you are looking for and more?

    Say you have a link to an app already:

    Take the id from the URL and append it to the lookup API:

    If you want the App Store Charts – try using the RSS feeds that iTunes provides:

    Top Paid Applications in the US (300 limit) in both XML or JSON

    • The post is more about scraping in general — iTunes is just the example.

    • Tia

      Is the lookup API considered scraping, in any form? Can this be blocked or barred? Thanks!

  4. shaun

    Hey awesome tutorial mate!

    gonna play with it for a while

  5. Hi virendra . Great post ! well after doing this all the data will be stored in the json file . Now what i would like to do is display this contents of json file on a web page … like the logo and its download link .. how can i do that ? So what should happen is – When a user clicks on the link he will be redirected to the itunes page for that app to download it ..

  6. oluwaseun

    The apps variable in your code is in a local context, hence the way your wrote your code would raise an error. I tried to clean the code up.

    Here is my revised snippet below.

    class AppleSpider(BaseSpider):
        name = "apple"
        allowed_domains = [""]
        start_urls = [""]
        def parse(self, response):
            hxs = HtmlXPathSelector(response)
            apps ='//*[@id="content"]/section/ul/li')
            return extractData(apps)
    def extractData(apps):
        items = []
        count = 0
        for app in apps:
            item = AppItem()
            item['app_name'] ='//h3/a/text()')[count].extract()
            item['appstore_link'] ='//h3/a/@href')[count].extract()
            item['category'] ='//h4/a/text()')[count].extract()
            item['img_src'] ='//a/img/@src')[count].extract()
            count += 1
        return items
  7. Pete

    For anyone coming across this now simply change “content” in

    apps ='//*[@id="content"]/section/ul/li')

    to “main” and it works.

    Thanks for the tutorial!

  8. will

    Hi, How I can use cookies in scrapy?

  9. GeneRickyShaw

    Doesn’t work for me; my json file only has “[” in it; if I choose to make a .csv file, it’s completely blank.

  10. GeneRickyShaw

    My json file only contains one character and if I use csv files they’re totally blank – what am I doing wrong?

    I also got a lot of deprecated warnings.

  11. Hi Virendra. I added it to my website’s list of great Python- and Scrapy-based website crawler tutorials. Thank you for the wonderful resource!

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!