2013年3月10日日曜日

クローラファームを作ってみたかった

なんだか久しぶりの更新な気がする


今回はなんだか最近クローラを書く事が増えてきました。
なぜなんでしょうね? まあ、TwitterAPIを常に監視したり、RSSリーダーで取って来たサイトの中にまで入ったり、アニメのデータベースが欲しいなーとか思ったり、様々な用途でクローラを書きます。

そこで最近懸念しているのがサーバでクローラを動かすときに書いたスクリプトをサーバで勝手にnohupでデーモンっぽく動かしてる。
ほとんど処理同じなのに毎回書いたりしてたのです。(正直打鍵スピードのおかげであんまり時間は気になってなかったんだけど)

そこでその懸念の解決の為にちょっと、頑張って見ました。


まず、毎回同じ事を書いている事に対する解決として、ベースのクラスを作ってしまえばいいじゃん。

ってことで、こんな感じのクラスを作りました

#coding: utf-8
import urllib
import urllib2
class BaseCrawler:
def __init__(self, base_url, params=None):
self.base_url = base_url;
self.params = params;
def run(self):
if self.params:
for param in self.params:
self.crawl(self.base_url + "?" + urllib.urlencode(param));
self.exec_scraping();
else:
self.crawl(self.base_url);
self.exec_scraping();
def crawl(self, url):
f = urllib2.urlopen(url);
self.source = f.read();
def exec_scraping(self):
import bs4
self.pre_scraping(self.source);
bs = bs4.BeautifulSoup(self.source);
self.scraping(bs);
#スクレイピングの前の文書整形
def pre_scraping(self, html):
pass;
#スクレイピングを行う
def scraping(self, bs):
pass;
if __name__ == "__main__":
pass;
view raw BaseCralwer hosted with ❤ by GitHub

これで、こいつを継承して、scrapingとpre_scrapingをオーバーライドしてやればおk

こんかいは、HTMLのスクレイピングをする事を前提で作っちゃったのでBeautifulSoupを使ってスクレイピングしてますが。ゆくゆくはいろんなのを切り替えて使えるようにします。(必要になったら)

まぁ、使ってる例はいくつかgithubに上げてるきがします。

次に、なんか一つ一つのクローラがデーモンっぽく動いてて気持ち悪いという問題

それは、クローラをまとめて置くデーモンっぽいものを作ってそれを常に動かしておくというたちを作ってみました。

なんか、タスクキューとかも勉強してみたかったのでRabbitMQを使ってみました。

RabbitMQというのはタスクキューを作ってくれる奴ですね〜。公式のドキュメントがPythonを使ったサンプルが乗っていたのでこいつを選びました。

こいつを使って、任意の位置にクローラのスクリプトを配置して、適当なスクリプトからクロール命令するとQueueに溜め込まれてクロールをして行くという、システムを構成しました。

├── crawlers
│   ├── BaseCrawler.py
│   ├── BaseCrawler.pyc
│   ├── SampleCrawler.py
│   ├── SampleCrawler.pyc
│   ├── __init__.py
│   └── __init__.pyc
└── worker.py

このように/crawlers以下にクローラを配置して行き。

import pika
import json
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.queue_declare(queue='crawler_task_queue')
def send(crawler_name, url):
channel.basic_publish(exchange='',
routing_key='crawler_task_queue',
body=json.dumps((crawler_name, url)))
if __name__ == '__main__':
send("SampleCrawler", "http://google.com");
send("TestCrawler", "http://google.com");
view raw sender.py hosted with ❤ by GitHub

このような感じでスクリプトを指定して、クロールするurlを入力すれば解決です。

ここにリポジトリを上げているので、気になる人はご覧ください(最小構成ですのであしからず)

これから

まだ、エンジンの指定が出来なかったり、クローラの追加がscpだったりして、あれなので。
1. HTMLだけじゃなくJSON,feedなどもスクレイピングできるようにする
2. Jenkinsとかとうまく連携してgit pushでクローラを追加するような仕組みにする

というのが当面の目標ですかね。

1 件のコメント:

  1. Quite helpful! good job!Thanks for sharing the information.Keep updating good stuff...

    ibm websphere training

    返信削除