質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.49%

scrapyの仕組みがいまいちわかってないので確認&質問

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 2,472

score 11

 前提・実現したいこと

pythonのscrapyを使ったクローリングを勉強したくて下記のサイトを参考にチュートリアルを行いました。
しかし、pythonの基本文法も怪しいレベルでいじったため、動くんだけどドユコト?ってなってしまいました。そこでコードの理解が正しいか確認&わからないことの質問をさせてください。
python超初心者がスクレイピングしてみる
Python, Scrapyの使い方(Webクローリング、スクレイピング)

 該当のソースコード(自分の解釈をコメントアウトで書いています)

spider

# -*- coding: utf-8 -*-
import scrapy
from tutorial.items import TutorialItem
# この2文によってscrapyのフレームワークと、他の名前空間?(items.py)にある定義をこのファイルでも使えるようにする

class QuotesSpider(scrapy.Spider):
    name = 'quotes'
    # ここよくわかりません。このnameどこで使ってます?
    allowed_domains = ['quotes.toscrape.com']
    start_urls = ['http://quotes.toscrape.com/page/1/']
    # allowed_domeinsでダウンロードするドメインの指定。念のため的な?start_urlsはダウンロードするページ

    def parse(self, response):
      # perseという関数の役割がよくわかりません。引数がself??これはページのurlでしょうか?responseはダウンロードしたページの情報が入っているという解釈で良いですか??
      for quote in response.css('div.quote'):
        # response.css()でページの中でもさらに情報を絞ってそれをquoteにlistとして入れてる
          item = TutorialItem()
          # itemという空のlistを定義?
          item['author'] = quote.css('small.author::text').extract_first()
          item['text'] = quote.css('span.text::text').extract_first()
          item['tags'] = quote.css('div.tags a.tag::text').extract_first()
          # cssセレクターによって欲しい情報を入手!
          yield item
          # itemを返す
      # for文でこの動作を繰り返し、ページ上のquoteを全て取得

      next_page = response.css('li.next a::attr(href)').extract_first()
      # ここで次ページのurl(/page/ページ数/)を取得
      if next_page is not None:
        # 次ページが存在しない(最終ページ)の時は処理をやめるための文
          next_page = response.urljoin(next_page)
          # urljoinによってresponseの中の情報のurlと今取得した次ページのurlを合体させてる??
          yield scrapy.Request(next_page, callback=self.parse)
          # scrapy.Requestはどういう関数?ですか?また引数にnext_pageとcallback=self.perseここの引数、上のperseという関数にまた渡してる感じなんでしょうが、いまいちよくわかりません。


item.py

# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html

import scrapy


class TutorialItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    text = scrapy.Field()
    author = scrapy.Field()
    tags = scrapy.Field()
#ここでスクレイピングで使う変数の定義をしてる

 補足情報(FW/ツールのバージョンなど)

python3.5.2

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

だいたい合ってます。分からないとこだけ。
Request objects

name = 'quotes'
#スパイダーの名前。クロールするときに名前を必ず指定します。nameが無いと動きませんので重要です。スパイダーを複数作っておいて名前を指定して動かすスパイダーを決めたり出来ます。

$ scrapy crawl quotes #コマンド+名前でスパイダーを動かします。


    def parse(self, response):
#responseはこの場合、要求した1ページ分って解釈で大丈夫です。parse=解析ですから、送られてきた1ページ分のresponseの中から抜き出したい情報を決めるために定義している関数です。
      for quote in response.css('div.quote'):
          item = TutorialItem()
#空のリストではなくitem.pyで定義したTutorialItem()を入れてます。空のリストを定義する理屈と一緒です。抜き出してきたアイテムを入れたいので器を別のitem.pyから持ってきたイメージでしょうか
#空のリストの場合はitem = []
          item['author'] = quote.css('small.author::text').extract_first()
          item['text'] = quote.css('span.text::text').extract_first()
          item['tags'] = quote.css('div.tags a.tag::text').extract_first()

          yield item

      next_page = response.css('li.next a::attr(href)').extract_first()

      if next_page is not None:
          next_page = response.urljoin(next_page)

          yield scrapy.Request(next_page, callback=self.parse)
# スscrapy.Requestはスパイダーを起動時に呼び出されます。もう一ページクロールしたいのでもう一回呼び出す必要があるわけです。引数は次のページで同じルールで抽出したいのでself.parseをコールバックしています。
次のページで違うルールで抽出したい場合は、違う関数を書いてcallbackに渡してあげる事で違った動きをします。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/19 21:06

    なるほど!とてもわかりやすく書いていただきありがとうございます!!
    次のページは違うルールで抽出とかもできるんですね!勉強になりました!!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る