如何用30行代码爬取Google Play 100万个App的数据

144
作者 linxiangyu
2015.05.06 23:38* 字数 921

2016/07/14 更新:

碰到一些朋友问附在文末的代码不能运行,在此说明下,如果你用的是最新版本的 Scrapy,而不是 requirement.txt 里面的版本,那么需要把源代码里面的app/settings.py 里面的 ITEM_PIPELINES 改成

ITEM_PIPELINES = {
  'scrapy_mongodb.MongoDBPipeline': 100
}

才能运行。

此外,如果迟迟没有响应,可以检查科学上网的姿势是否正确,终端下是否能正确翻墙。


最近在做一些 App 的统计工作,打算爬取一些市场上 App 的数据,于是尝试了下 Scrapy,不愧是 Github 上近 10000 Star 的项目, 十分强大和易用。

Scrapy中文文档)是一个 Python 爬虫框架,它帮开发者做了绝大多数爬虫需要做的基础工作:

  • 内置元素选择器
  • 序列化和存储数据
  • 处理cookie、HTTP头这些东西的中间件
  • 爬取 Sitemap 或者 RSS

等等

我的需求是爬取 Google Play 市场上的所有 App 的页面链接以及下载数量。

首先确保配置好 Python 2.7, MongoDB 数据库, 以及 Python 的 pip 包管理系统。

然后安装对应的 Python 包并且生成项目模板:

pip install scrapy scrapy-mongodb 
scrapy startproject app
cd app
scrapy genspider google

然后把 app/spider/google.py 换成下面的内容:

`# -*- coding: utf-8 -*-
import scrapy

from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.contrib.linkextractors import LinkExtractor
from app.items import GoogleItem


    class GoogleSpider(CrawlSpider):
        name = "google"
        allowed_domains = ["play.google.com"]
        start_urls = [
            'http://play.google.com/',
            'https://play.google.com/store/apps/details?id=com.viber.voip'
        ]
        rules = [
            Rule(LinkExtractor(allow=("https://play\.google\.com/store/apps/details", )), callback='parse_app',follow=True),
        ] #  CrawlSpider 会根据 rules 规则爬取页面并调用函数进行处理


        def parse_app(self, response):
            # 在这里只获取页面的 URL 以及下载数量
            item = GoogleItem()
            item['url'] = response.url
            item['num'] =  response.xpath("//div[@itemprop='numDownloads']").xpath("text()").extract()
            yield item

在 app/items 里添加下面的代码:

class GoogleItem(scrapy.Item):
    url = scrapy.Field()
    num = scrapy.Field()

在 app/setting.py 里面添加下面的代码

# 这里是配置 scrapy-mongodb 到数据库的连接,用于自动把爬取后的数据存入到 MongoDB
ITEM_PIPELINES = [
     'scrapy_mongodb.MongoDBPipeline',
]

MONGODB_URI = 'mongodb://127.0.0.1:27017'
MONGODB_DATABASE = 'scrapy'
MONGODB_COLLECTION = 'play'

然后,没有其他工作了。。连配置文件一共不到四十行。之后开启 MongoDB,在项目目录下运行

 scrapy crawl google -s JOBDIR=app/jobs

然后就静静等它跑完吧。-s JOBDIR=app/jobs 参数的意思是把工作状态和已经爬取过的页面数据存到 app/jobs 目录下,即使中间中断了,也可以运行上面的命令从该目录恢复工作,而不用重新开始。

在我的 Linode 最低配的 VPS 上,它跑了大概 40 个小时,最后在 MongoDB 下的数据是有 156 万条记录。2015 年 1 月的新闻是 Google Play 上有 143 万款 App, 相信已经爬取了绝大多数 App 页面了。

`> use scrapy
switched to db scrapy
> db.play.count()
1564754
> db.play.find().limit(1)
 "_id" : ObjectId("55479d9da28a7c1cca449c23"), "url" : "https://play.google.com/store/apps/details?id=com.viber.voip", "num" : [ "  100,000,000 - 500,000,000  " ]() 
>

同时我也写了其他国内市场的爬虫,目前还在不断完善中,有需要的朋友可以看看。

代码的项目地址

此外推荐两个更值得学习的 Scrapy 爬虫项目:

日记本