2012-05-15 8 views
6

私はScrapy、特にScrapyのCrawlSpiderクラスを使用して、特定のキーワードを含むWebリンクをスクラップしています。私はかなり長いstart_urlsリストを持っています。このリストは、Djangoプロジェクトに接続されたSQLiteデータベースからエントリを取得します。このデータベースにスクレイプされたWebリンクを保存します。Scrapy CrawlSpiderの特定のstart_urlにアクセスする方法は?

私は2つのDjangoのモデル、などなどhttp://example.com/website1http://example.com/website2などすべてのかき取りウェブリンクはstart_urlsリスト内の開始URLのいずれかのサブサイトです掻き取っWebリンクについてhttp://example.comと一つとして開始URLのための1つを持っています。

ウェブリンクモデルは、開始URLモデルと多対1の関係を有する。すなわち、ウェブリンクモデルは、開始URLモデルに対する外部キーを有する。スクラップされたウェブリンクをデータベースに適切に保存するために、CrawlSpiderparse_item()メソッドに、スクラップされたウェブリンクが属するURLを開始する方法を伝える必要があります。どうやってやるの? ScrapyのDjangoItemクラスは、私がまだ使用されている開始URLを明示的に定義しなければならないので、この点では役に立ちません。

つまり、現在使用されている開始URLをparse_item()メソッドに渡すことで、適切なスクラップされたWebリンクをデータベースに保存することができますか?何か案は?前もって感謝します!

+0

weblinksテーブルと同じテーブルのstart_urlフィールドを使用できますか(使用しているDjangoItemの場合のように)?確かに、それは冗長な非正規化を作成しますが、明示的に呼び出すことを避けたい場合は、これが役に立ちます。 – zubinmehta

答えて

8

デフォルトでは、元の開始URLにアクセスすることはできません。

ただし、make_requests_from_urlメソッドをオーバーライドして、開始URLをmetaに入れることができます。次に、パースでそこから抽出することができます(その解析メソッドの後続のリクエストで、その開始URLを転送することを忘れないでください)。


私はCrawlSpiderで働いていないと、多分何マキシムが示唆することはあなたのために働くが、response.urlが可能リダイレクト後のURLを持っていることに注意してくださいます。ここで

は、私はそれを行うだろうかの例であるが、それは(scrapyのチュートリアルから取られた)単なる一例だと、テストされていなかった。質問があれば

class MySpider(CrawlSpider): 
    name = 'example.com' 
    allowed_domains = ['example.com'] 
    start_urls = ['http://www.example.com'] 

    rules = (
     # Extract links matching 'category.php' (but not matching 'subsection.php') 
     # and follow links from them (since no callback means follow=True by default). 
     Rule(SgmlLinkExtractor(allow=('category\.php',), deny=('subsection\.php',))), 

     # Extract links matching 'item.php' and parse them with the spider's method parse_item 
     Rule(SgmlLinkExtractor(allow=('item\.php',)), callback='parse_item'), 
    ) 

    def parse(self, response): # When writing crawl spider rules, avoid using parse as callback, since the CrawlSpider uses the parse method itself to implement its logic. So if you override the parse method, the crawl spider will no longer work. 
     for request_or_item in CrawlSpider.parse(self, response): 
      if isinstance(request_or_item, Request): 
       request_or_item = request_or_item.replace(meta = {'start_url': response.meta['start_url']}) 
      yield request_or_item 

    def make_requests_from_url(self, url): 
     """A method that receives a URL and returns a Request object (or a list of Request objects) to scrape. 
     This method is used to construct the initial requests in the start_requests() method, 
     and is typically used to convert urls to requests. 
     """ 
     return Request(url, dont_filter=True, meta = {'start_url': url}) 

    def parse_item(self, response): 
     self.log('Hi, this is an item page! %s' % response.url) 

     hxs = HtmlXPathSelector(response) 
     item = Item() 
     item['id'] = hxs.select('//td[@id="item_id"]/text()').re(r'ID: (\d+)') 
     item['name'] = hxs.select('//td[@id="item_name"]/text()').extract() 
     item['description'] = hxs.select('//td[@id="item_description"]/text()').extract() 
     item['start_url'] = response.meta['start_url'] 
     return item 

を確認して下さい。ところで、PyDevの「Go to definition」機能を使って、治療ソースを確認し、Requestmake_requests_from_urlなどのクラスとメソッドが期待するパラメータを理解することができます。コードを手に入れておくと時間が節約できますが、最初は難しいように見えるかもしれません。

+0

私はおおまかなことを理解していると思いますが、実装方法はわかりません。おそらく 'make_requests_from_url'メソッドがどのように使われているのか、それが' parse'メソッドにどのように関係しているのかを簡単に示す例がありますか?私はまだ初心者です。ありがとう! – pemistahl

+1

warwarukありがとう、これはうまく動作します。しかし、この作業をするには、メソッド 'make_requests_from_url'とリクエストの' meta'タグの設定だけが必要であることがわかりました。私は最後に開始URLを保存したくないので、それをアイテムに入れるのは意味がありません。とにかく、もう一度、ありがとう! :) – pemistahl

1

私が問題を正しく理解していれば、response.urlからURLを取得してitem['url']に書き込むことができます。スパイダーで

item['url'] = response.url

、パイプラインで:url = item['url']

またはresponse.urlmetaに入れて、warvariucと書いてください。

1

warvariucの回答には、Scrapy 1.3.3のように少し修正が必要です:parseの代わりに_parse_responseを上書きする必要があります。オーバーライドmake_requests_from_urlは不要になりました。