4

基本的には問題なく動作し、本来の動作をするスパイダーを Scrapy で作成しました。問題は、小さな変更を加える必要があり、いくつかのアプローチを試みましたが成功しませんでした (InitSpider の変更など)。スクリプトが今すべきことは次のとおりです。

  • 開始 URL をクロールするhttp://www.example.de/index/search?method=simple
  • 今すぐURLに進みますhttp://www.example.de/index/search?filter=homepage
  • ルールで定義されたパターンでここからクロールを開始します

したがって、基本的に変更する必要があるのは、間に 1 つの URL を呼び出すことだけです。BaseSpider で全体を書き直すのは避けたいので、誰かがこれを達成する方法についてアイデアを持っていることを願っています :)

追加情報が必要な場合は、お知らせください。以下に、現在のスクリプトを示します。

#!/usr/bin/python
# -*- coding: utf-8 -*-

from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.selector import HtmlXPathSelector
from scrapy.http import Request
from example.items import ExampleItem
from scrapy.contrib.loader.processor import TakeFirst
import re
import urllib

take_first = TakeFirst()

class ExampleSpider(CrawlSpider):
    name = "example"
    allowed_domains = ["example.de"]

    start_url = "http://www.example.de/index/search?method=simple"
    start_urls = [start_url]

    rules = (
        # http://www.example.de/index/search?page=2
        # http://www.example.de/index/search?page=1&tab=direct
        Rule(SgmlLinkExtractor(allow=('\/index\/search\?page=\d*$', )), callback='parse_item', follow=True),
        Rule(SgmlLinkExtractor(allow=('\/index\/search\?page=\d*&tab=direct', )), callback='parse_item', follow=True),
    )

    def parse_item(self, response):
        hxs = HtmlXPathSelector(response)

        # fetch all company entries
        companies = hxs.select("//ul[contains(@class, 'directresults')]/li[contains(@id, 'entry')]")
        items = []

        for company in companies:
            item = ExampleItem()
            item['name'] = take_first(company.select(".//span[@class='fn']/text()").extract())
            item['address'] = company.select(".//p[@class='data track']/text()").extract()
            item['website'] = take_first(company.select(".//p[@class='customurl track']/a/@href").extract())

            # we try to fetch the number directly from the page (only works for premium entries)
            item['telephone'] = take_first(company.select(".//p[@class='numericdata track']/a/text()").extract())

            if not item['telephone']:
              # if we cannot fetch the number it has been encoded on the client and hidden in the rel=""
              item['telephone'] = take_first(company.select(".//p[@class='numericdata track']/a/@rel").extract())

            items.append(item)
        return items

編集

これが InitSpider での私の試みです: https://gist.github.com/150b30eaa97e0518673a 私はここからそのアイデアを得ました: Scrapy で認証されたセッションでクロール

ご覧のとおり、CrawlSpider を継承していますが、コアの Scrapy ファイルにいくつかの変更を加えました (私のお気に入りのアプローチではありません)。CrawlSpider が BaseSpider ( source )の代わりに InitSpider を継承するようにしました。

これは今のところ機能しますが、スパイダーは他のすべてのページを取得するのではなく、最初のページの後で停止するだけです。

また、このアプローチは私には絶対に不要なようです:)

4

1 に答える 1

3

わかりました、私は自分で解決策を見つけました。実際には、最初に考えていたよりもはるかに簡単です:)

簡略化されたスクリプトは次のとおりです。

#!/usr/bin/python
# -*- coding: utf-8 -*-

from scrapy.spider import BaseSpider
from scrapy.http import Request
from scrapy import log
from scrapy.selector import HtmlXPathSelector
from example.items import ExampleItem
from scrapy.contrib.loader.processor import TakeFirst
import re
import urllib

take_first = TakeFirst()

class ExampleSpider(BaseSpider):
    name = "ExampleNew"
    allowed_domains = ["www.example.de"]

    start_page = "http://www.example.de/index/search?method=simple"
    direct_page = "http://www.example.de/index/search?page=1&tab=direct"
    filter_page = "http://www.example.de/index/search?filter=homepage"

    def start_requests(self):
        """This function is called before crawling starts."""
        return [Request(url=self.start_page, callback=self.request_direct_tab)]

    def request_direct_tab(self, response):
        return [Request(url=self.direct_page, callback=self.request_filter)]

    def request_filter(self, response):
        return [Request(url=self.filter_page, callback=self.parse_item)]

    def parse_item(self, response):
        hxs = HtmlXPathSelector(response)

        # fetch the items you need and yield them like this:
        # yield item

        # fetch the next pages to scrape
        for url in hxs.select("//div[@class='limiter']/a/@href").extract():
            absolute_url = "http://www.example.de" + url             
            yield Request(absolute_url, callback=self.parse_item)

ご覧のとおり、私は現在 BaseSpider を使用しており、最後に新しいリクエストを自分で生成しています。そして最初は、クロールを開始する前に行う必要のあるさまざまな要求をすべて説明するだけです。

これが誰かの役に立てば幸いです :) 質問があれば、喜んでお答えします。

于 2012-09-06T10:04:38.063 に答える