Scrapyを使ったFossdroidのAPK-crawl
FossdroidというAndroidのOSSのアプリを集めたサイトがある。ここにあるアプリの内HTMLハイブリッドアプリが欲しくて、集めようとした備忘録
Scrapyとshellscriptを使ったよ
Scrapyのインストール
$ sudo pip install --upgrade pip $ sudo pip install pyopenssl $ sudo pip install --upgrade pyopenssl $ sudo pip install scrapy $ sudo pip install --upgrade Scrapy
pipでいれればいいけど色々エラーが起きたのでその度調べて解決、最終的には私は上のコマンドを打ってインストール完了
Scrapyを使ったcrawl
プロジェクトの作成
まずはクロールを行うプロジェクトを作成する.scrapy startproject プロジェクト名
で作成
$ scrapy startproject apkcrawl
設定ファイルの編集
今回対象とするfossdroid.comのrobots.txtに従うように、かつ負荷をかけないようにDELAYをつける
ROBOTSTXT_OBEY
がTrue
になっていること(デフォルトでTrueなので問題ないはず)
DOWNLOAD_DELAY
のコメントアウトをはずし3と設定する
$ cd apkcrawl/apkcrawl $ vim settings.py # -*- coding: utf-8 -*- # Scrapy settings for apkcrawl project # # For simplicity, this file contains only settings considered important or # commonly used. You can find more settings consulting the documentation: # # http://doc.scrapy.org/en/latest/topics/settings.html # http://scrapy.readthedocs.org/en/latest/topics/downloader-middleware.html # http://scrapy.readthedocs.org/en/latest/topics/spider-middleware.html BOT_NAME = 'apkcrawl' SPIDER_MODULES = ['apkcrawl.spiders'] NEWSPIDER_MODULE = 'apkcrawl.spiders' # Crawl responsibly by identifying yourself (and your website) on the user-agent #USER_AGENT = 'apkcrawl (+http://www.yourdomain.com)' # Obey robots.txt rules ROBOTSTXT_OBEY = True # Configure maximum concurrent requests performed by Scrapy (default: 16) #CONCURRENT_REQUESTS = 32 # Configure a delay for requests for the same website (default: 0) # See http://scrapy.readthedocs.org/en/latest/topics/settings.html#download-delay # See also autothrottle settings and docs DOWNLOAD_DELAY = 3 (snipping)
保存するデータのクラスを作成
crawlした際に保存するデータのクラスを作成する.
今回はapkのタイトルとapkのurlを保存したいので、そういったクラスとする
$ vim items.py # -*- coding: utf-8 -*- # Define here the models for your scraped items # # See documentation in: # http://doc.scrapy.org/en/latest/topics/items.html import scrapy class ApkcrawlItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() title = scrapy.Field() # name of application url = scrapy.Field() # url of APK
crawl本体を書く
scrapy genspider クロールファイル名 集めたいデータのurl
でクロール本体のスクリプトファイルを作成
クロールファイル名は何でもいいので私はapkcrawl_spider
,fossdroidからデータを集めるので集めたいデータのurlはfossdroid.com
となる
$ scrapy genspider apkcrawl_spider fossdroid.com $ vim spiders/apkcrawl_spider.py # -*- coding: utf-8 -*- from ..items import ApkcrawlItem import scrapy class ApkcrawlSpiderSpider(scrapy.Spider): name = 'apkcrawl_spider' allowed_domains = ['fossdroid.com'] start_urls = ( 'http://fossdroid.com/c/system/whats_new.html', 'http://fossdroid.com/c/internet/whats_new.html', 'http://fossdroid.com/c/multimedia/whats_new.html', 'http://fossdroid.com/c/games/whats_new.html', 'http://fossdroid.com/c/navigation/whats_new.html', 'http://fossdroid.com/c/time/whats_new.html', 'http://fossdroid.com/c/writing/whats_new.html', 'http://fossdroid.com/c/science-education/whats_new.html', 'http://fossdroid.com/c/reading/whats_new.html', 'http://fossdroid.com/c/connectivity/whats_new.html', 'http://fossdroid.com/c/theming/whats_new.html', 'http://fossdroid.com/c/security/whats_new.html', 'http://fossdroid.com/c/development/whats_new.html', 'http://fossdroid.com/c/money/whats_new.html', 'http://fossdroid.com/c/sports-health/whats_new.html', 'http://fossdroid.com/c/phone-sms/whats_new.html', 'http://fossdroid.com/c/graphics/whats_new.html' ) def parse(self, response): for res in response.css("h5"): apk = ApkcrawlItem() apk['title'] = res.css("a::text").extract_first() print(apk['title']) nextpage = res.css("a::attr('href')").extract_first() print(nextpage) if nextpage: url = response.urljoin(nextpage) apk['url'] = url yield apk
start_urlsにはクロールするurlを書いておく。start_urlsに書いてあるurl毎にparse関数を実行していくことになる.
あとはfossdroidのソースコードを確認していく。urlから更にurlを入手してcrawlしていく方法がわからなかったため、ここではアプリケーションページのurlを入手することにした.
scrapyの実行
$ scrapy crawl apkcrawl_spider -o apklist.json
-oで書き出すjsonファイルを指定する.
入手したいapkのファイルは入手したアプリケーション名.html
のhtmlをapkに変えるだけで良いとわかったのでここからはスクリプトを書く
apkのダウンロード
文字列を置換してひたすらwgetするだけ.保存用のディレクトリapkを作成しておく
import json import os f = open("apklist.json","r") apklist = [] json_data = json.load(f) for i in range(len(json_data)): url = json_data[i]['url'].replace("html","apk") os.system("wget "+url+" -P apk")
HTMLハイブリッドアプリの判別
最後に集めたapkの中からHTMLハイブリッドアプリを判別する.apkの実体はzipファイルなのでunzip
してhtmlファイルがあるかないかで判別を行う
事前に作業ディレクトリであるtmpディレクトリとhtmlハイブリッドアプリのapkファイルを保存するhtmlapkディレクトリを作成しておく
#!/bin/bash for file in `\find ./apk -maxdepth 1 -type f`; do unzip -d ./tmp $file htmlfile=`find ./tmp/ -type f -name "*.html"` for a in $htmlfile; do cp $file ./htmlapk/ break done rm -r ./tmp/* done