ホームページ  >  記事  >  バックエンド開発  >  Python クローラー フレームワークのスクレイピーなサンプルの詳細な説明

Python クローラー フレームワークのスクレイピーなサンプルの詳細な説明

高洛峰
高洛峰オリジナル
2016-10-18 10:25:452409ブラウズ

プロジェクトの生成

Scrapy はプロジェクトを生成するツールを提供します。生成されたプロジェクトにはいくつかのファイルがプリセットされており、ユーザーはこれらのファイルに独自のコードを追加する必要があります。

コマンドラインを開いて実行します:scrapy startprojecttutorial 生成されたプロジェクトは次のような構造になります

tutorial/

scrapy.cfg

tutorial/

__init__.py

items.py

パイプライン.py

設定 .py

Spiders/

name 属性は重要です。異なるスパイダーが同じ名前を使用することはできません

start_url s はスパイダーが Web ページをクロールするための開始点であり、複数の URL を含めることができます

parse メソッドは、スパイダーが Web ページをキャプチャした後にデフォルトで呼び出されるコールバックです。独自のメソッドを定義するためにこの名前を使用することは避けてください。

スパイダーは URL のコンテンツを取得すると、parse メソッドを呼び出し、それに応答パラメータを渡します。parse メソッドでは、キャプチャされた Web ページのデータを解析できます。ページ。上記のコードは、Web ページのコンテンツをファイルに保存するだけです。

クロールを開始します

コマンドラインを開き、生成されたプロジェクトのルートディレクトリtutorial/に入力し、scrapy roll dmozを実行します。ここで、dmozはスパイダーの名前です。


Webページのコンテンツを解析する

scrapyは、Webページからデータを解析する便利な方法を提供します。それにはHtmlXPathSelectorの使用が必要です

from scrapy.spider import BaseSpider
class DmozSpider(BaseSpider):
    name = "dmoz"
    allowed_domains = ["dmoz.org"]
    start_urls = [
        "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/",
        "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"
    ]
    def parse(self, response):
        filename = response.url.split("/")[-2]
        open(filename, 'wb').write(response.body)

HtmlXPathSelectorはXpathを使用してデータを解析します


//ul/liはすべてのULを選択することを意味しますタグ 以下の li タグ

a/@href は、すべての a タグの href 属性を選択することを意味します

a/text() は、a タグのテキストを選択することを意味します

a[@href="abc"] は、href のすべての a を選択することを意味します属性は abc タグです

解析されたデータをscrapyが使用できるオブジェクトに保存すると、scrapyは自分でデータをファイルに保存することなく、これらのオブジェクトを保存するのに役立ちます。保存したいデータを記述するために使用されるいくつかのクラスを items.py に追加する必要があります

from scrapy.spider import BaseSpider
from scrapy.selector import HtmlXPathSelector
class DmozSpider(BaseSpider):
    name = "dmoz"
    allowed_domains = ["dmoz.org"]
    start_urls = [
        "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/",
        "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"
    ]
    def parse(self, response):
        hxs = HtmlXPathSelector(response)
        sites = hxs.select('//ul/li')
        for site in sites:
            title = site.select('a/text()').extract()
            link = site.select('a/@href').extract()
            desc = site.select('text()').extract()
            print title, link, desc

コマンドラインでscrapyを実行するとき、2つのパラメータを追加して、scrapyがparseメソッドによって返された項目を出力できるようにすることができます。 json ファイル内で

scrapy roll dmoz -o items.json -t json

items.json はプロジェクトのルート ディレクトリに配置されます

scrapy が Web ページ上のすべてのリンクを自動的にクロールできるようにします

上の例、scrapy start_urls 内の 2 つの URL のコンテンツのみがクロールされますが、通常、私たちが達成したいのは、scrapy が Web ページ上のすべてのリンクを自動的に検出し、これらのリンクのコンテンツをクロールすることです。これを実現するには、parse メソッドで必要なリンクを抽出し、いくつかの Request オブジェクトを構築して、Scrapy がこれらのリンクを自動的にクロールします。コードは似ています:

from scrapy.item import Item, Field
class DmozItem(Item):
   title = Field()
   link = Field()
   desc = Field()
然后在spider的parse方法中,我们把解析出来的数据保存在DomzItem对象中。
from scrapy.spider import BaseSpider
from scrapy.selector import HtmlXPathSelector
from tutorial.items import DmozItem
class DmozSpider(BaseSpider):
   name = "dmoz"
   allowed_domains = ["dmoz.org"]
   start_urls = [
       "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/",
       "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"
   ]
   def parse(self, response):
       hxs = HtmlXPathSelector(response)
       sites = hxs.select('//ul/li')
       items = []
       for site in sites:
           item = DmozItem()
           item['title'] = site.select('a/text()').extract()
           item['link'] = site.select('a/@href').extract()
           item['desc'] = site.select('text()').extract()
           items.append(item)
       return items

parse は、リクエスト リストを返すデフォルトのコールバックです。Web ページがキャプチャされると、Scrapy はこのリストに基づいて Web ページを自動的にクロールし、parse_item もリストを返します。 Scrapy はこのリストに基づいて Web ページがクロールされ、クロール後に parse_details が呼び出されます


このような作業を容易にするために、Scrapy はリンクの自動クロールを簡単に実装できる別のスパイダー基本クラスを提供します。 CrawlSpider を使用するには

class MySpider(BaseSpider):
    name = 'myspider'
    start_urls = (
        'http://example.com/page1',
        'http://example.com/page2',
        )
    def parse(self, response):
        # collect `item_urls`
        for item_url in item_urls:
            yield Request(url=item_url, callback=self.parse_item)
    def parse_item(self, response):
        item = MyItem()
        # populate `item` fields
        yield Request(url=item_details_url, meta={'item': item},
            callback=self.parse_details)
    def parse_details(self, response):
        item = response.meta['item']
        # populate more `item` fields
        return item

BaseSpider と比較して、新しいクラスには追加のルール属性があり、この属性には複数のルールを含めることができます。どのリンクがクロールされる必要があるかが説明されます。これは Rule クラスのドキュメントです http://doc.scrapy.org/en/latest/topics/spiders.html#scrapy.contrib.spiders.Rule

これらのルールはコールバックを含むかどうか、コールバックがない場合に指定できます。 、scrapy はこれらすべてのリンクをたどるだけです。

pipelines.py の使用法

pipelines.py では、不要な項目をフィルターで除外し、項目をデータベースに保存するためのクラスを追加できます。

from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
class MininovaSpider(CrawlSpider):
    name = 'mininova.org'
    allowed_domains = ['mininova.org']
    start_urls = ['http://www.mininova.org/today']
    rules = [Rule(SgmlLinkExtractor(allow=['/tor/\d+'])),
             Rule(SgmlLinkExtractor(allow=['/abc/\d+']), 'parse_torrent')]
    def parse_torrent(self, response):
        x = HtmlXPathSelector(response)
        torrent = TorrentItem()
        torrent['url'] = response.url
        torrent['name'] = x.select("//h1/text()").extract()
        torrent['description'] = x.select("//div[@id='description']").extract()
        torrent['size'] = x.select("//div[@id='info-left']/p[2]/text()[2]").extract()
        return torrent

項目が要件を満たしていない場合、例外がスローされ、項目は json ファイルに出力されません。

パイプラインを使用するには、settings.pyも変更する必要があります

行を追加します

ITEM_PIPELINES = ['dirbot.pipelines.FilterWordsPipeline']

次に、scrapy roll dmoz -o items.json -t jsonを実行します。要件を満たしていないアイテムは除外されました

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。