なんだか久しぶりの更新な気がする
今回はなんだか最近クローラを書く事が増えてきました。
なぜなんでしょうね? まあ、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; |
これで、こいつを継承して、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"); |
このような感じでスクリプトを指定して、クロールするurlを入力すれば解決です。
ここにリポジトリを上げているので、気になる人はご覧ください(最小構成ですのであしからず)
これから
まだ、エンジンの指定が出来なかったり、クローラの追加がscpだったりして、あれなので。
1. HTMLだけじゃなくJSON,feedなどもスクレイピングできるようにする
2. Jenkinsとかとうまく連携してgit pushでクローラを追加するような仕組みにする
というのが当面の目標ですかね。
Quite helpful! good job!Thanks for sharing the information.Keep updating good stuff...
返信削除ibm websphere training