8

TextFields、Buttons などを持つ Web サイトからデータをスクレイピングしたいのですが、私の要件は、テキスト フィールドに入力し、フォームを送信して結果を取得し、結果ページからデータ ポイントをスクレイピングすることです。

Scrapy にこの機能があることを知りたいですか、またはこのタスクを達成するために Python のライブラリを推奨できる人はいますか?

(編集済み)
次の Web サイトからデータをスクレイピングしたい:
http://a836-acris.nyc.gov/DS/DocumentSearch/DocumentType

私の要件は、ComboBoxes から値を選択し、検索ボタンを押して、結果ページからデータ ポイントを取得することです。

PS セレン Firefox ドライバーを使用して他の Web サイトからデータをスクレイピングしていますが、セレン Firefox ドライバーは FireFox の EXE に依存しているため、スクレイパーを実行する前に Firefox をインストールする必要があるため、その解決策は適切ではありません。

Selenium Firefox ドライバーは、1 つのインスタンスで約 100MB のメモリを消費しています。私の要件は、スクレイピング プロセスを高速化するために一度に多数のインスタンスを実行することであり、メモリの制限もあります。

スクレイパーの実行中に Firefox がクラッシュすることがありますが、その理由はわかりません。また、Selenium Firefox ドライバーの場合には不可能なウィンドウレススクレイピングが必要です。

私の最終的な目標は、Heroku でスクレイパーを実行することです。そこに Linux 環境があるため、Selenium Firefox ドライバーは Heroku では動作しません。ありがとう

4

4 に答える 4

18

基本的に、選択できるツールはたくさんあります。

これらのツールにはさまざまな目的がありますが、タスクに応じて組み合わせることができます。

Scrapy は、Web サイトをクロールしてデータを抽出するための強力で非常にスマートなツールです。しかし、ボタンのクリック、フォームへの入力など、ページの操作に関しては、さらに複雑になります。

  • 場合によっては、基礎となるフォームアクションをスクレイピーで直接作成することにより、フォームの入力/送信を簡単にシミュレートできます
  • 場合によっては、機械化やセレンなど、スクレイピーを支援するために他のツールを使用する必要があります

質問をより具体的にすると、どのようなツールを使用または選択する必要があるかを理解するのに役立ちます。

興味深いスクレイピーとセレンの組み合わせの例を見てみましょう。ここで、セレンタスクはボタンをクリックしてスクレイピーアイテムのデータを提供することです:

import time
from scrapy.item import Item, Field

from selenium import webdriver

from scrapy.spider import BaseSpider


class ElyseAvenueItem(Item):
    name = Field()


class ElyseAvenueSpider(BaseSpider):
    name = "elyse"
    allowed_domains = ["ehealthinsurance.com"]
    start_urls = [
    'http://www.ehealthinsurance.com/individual-family-health-insurance?action=changeCensus&census.zipCode=48341&census.primary.gender=MALE&census.requestEffectiveDate=06/01/2013&census.primary.month=12&census.primary.day=01&census.primary.year=1971']

    def __init__(self):
        self.driver = webdriver.Firefox()

    def parse(self, response):
        self.driver.get(response.url)
        el = self.driver.find_element_by_xpath("//input[contains(@class,'btn go-btn')]")
        if el:
            el.click()

        time.sleep(10)

        plans = self.driver.find_elements_by_class_name("plan-info")
        for plan in plans:
            item = ElyseAvenueItem()
            item['name'] = plan.find_element_by_class_name('primary').text
            yield item

        self.driver.close()

アップデート:

あなたの場合にスクレイピーを使用する方法の例を次に示します。

from scrapy.http import FormRequest
from scrapy.item import Item, Field
from scrapy.selector import HtmlXPathSelector

from scrapy.spider import BaseSpider


class AcrisItem(Item):
    borough = Field()
    block = Field()
    doc_type_name = Field()


class AcrisSpider(BaseSpider):
    name = "acris"
    allowed_domains = ["a836-acris.nyc.gov"]
    start_urls = ['http://a836-acris.nyc.gov/DS/DocumentSearch/DocumentType']


    def parse(self, response):
        hxs = HtmlXPathSelector(response)
        document_classes = hxs.select('//select[@name="combox_doc_doctype"]/option')

        form_token = hxs.select('//input[@name="__RequestVerificationToken"]/@value').extract()[0]
        for document_class in document_classes:
            if document_class:
                doc_type = document_class.select('.//@value').extract()[0]
                doc_type_name = document_class.select('.//text()').extract()[0]
                formdata = {'__RequestVerificationToken': form_token,
                            'hid_selectdate': '7',
                            'hid_doctype': doc_type,
                            'hid_doctype_name': doc_type_name,
                            'hid_max_rows': '10',
                            'hid_ISIntranet': 'N',
                            'hid_SearchType': 'DOCTYPE',
                            'hid_page': '1',
                            'hid_borough': '0',
                            'hid_borough_name': 'ALL BOROUGHS',
                            'hid_ReqID': '',
                            'hid_sort': '',
                            'hid_datefromm': '',
                            'hid_datefromd': '',
                            'hid_datefromy': '',
                            'hid_datetom': '',
                            'hid_datetod': '',
                            'hid_datetoy': '', }
                yield FormRequest(url="http://a836-acris.nyc.gov/DS/DocumentSearch/DocumentTypeResult",
                                  method="POST",
                                  formdata=formdata,
                                  callback=self.parse_page,
                                  meta={'doc_type_name': doc_type_name})

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

        rows = hxs.select('//form[@name="DATA"]/table/tbody/tr[2]/td/table/tr')
        for row in rows:
            item = AcrisItem()
            borough = row.select('.//td[2]/div/font/text()').extract()
            block = row.select('.//td[3]/div/font/text()').extract()

            if borough and block:
                item['borough'] = borough[0]
                item['block'] = block[0]
                item['doc_type_name'] = response.meta['doc_type_name']

                yield item

保存してspider.py実行すると、次のように表示さscrapy runspider spider.py -o output.jsonoutput.jsonます。

{"doc_type_name": "CONDEMNATION PROCEEDINGS ", "borough": "Borough", "block": "Block"}
{"doc_type_name": "CERTIFICATE OF REDUCTION ", "borough": "Borough", "block": "Block"}
{"doc_type_name": "COLLATERAL MORTGAGE ", "borough": "Borough", "block": "Block"}
{"doc_type_name": "CERTIFIED COPY OF WILL ", "borough": "Borough", "block": "Block"}
{"doc_type_name": "CONFIRMATORY DEED ", "borough": "Borough", "block": "Block"}
{"doc_type_name": "CERT NONATTCHMENT FED TAX LIEN ", "borough": "Borough", "block": "Block"}
...

それが役立つことを願っています。

于 2013-05-28T08:06:26.310 に答える
3

単純にフォームを送信して、結果のページからデータを抽出したい場合は、次のようにします。

Scrapy の付加価値は、リンクをたどったり、Web サイトをクロールしたりする能力に本当にあります。探しているものを正確に知っている場合、Scrapy はその仕事に適したツールではないと思います。

于 2013-05-28T07:13:01.380 に答える