見出し画像

【Scrapy初心者】連番収集の仕組み

スクレイピングするものは、ページ単体だけでなく、複数ページにまたがるのがほとんどだと思う。今回は、複数ページ、連番をどう収集するか?を考えてみます。

参考:10分で理解する Scrapy

ここに記載されているソースで考えていきます。

import scrapy
from ten_min_scrapy.items import Post

class ScrapyBlogSpiderSpider(scrapy.Spider):

   name = 'scrapy_blog_spider'
   allowed_domains = ['blog.scrapinghub.com']
   start_urls = ['http://blog.scrapinghub.com']

   def parse(self, response):
       """
       レスポンスに対するパース処理
       """
       # response.css で scrapy デフォルトの css セレクタを利用できる
       
       for post in response.css('.post-listing .post-item'):
           # items に定義した Post のオブジェクトを生成して次の処理へ渡す
           
           yield Post(
               url=post.css('div.post-header a::attr(href)').extract_first().strip(),
               title=post.css('div.post-header a::text').extract_first().strip(),
               date=post.css('div.post-header span.date a::text').extract_first().strip(),
           )
       # 再帰的にページングを辿るための処理
       older_post_link = response.css('.blog-pagination a.next-posts-link::attr(href)').extract_first()
       if older_post_link is None:
           # リンクが取得できなかった場合は最後のページなので処理を終了
           return
       # URLが相対パスだった場合に絶対パスに変換する
       older_post_link = response.urljoin(older_post_link)
       
       # 次のページをのリクエストを実行する
       yield scrapy.Request(older_post_link, callback=self.parse)
       

実行するファイルはこちら。

Spiderファイルの全体の構造は?

全体の構造として、
上部にアクセスするURLが記載しており、
次に、parse()
CSSセクレタを使って URL,title、dataを取得を繰り返す。
それが終わると。
リンクがあるか?を確認してできなければ、そこで終了。
リンクがあるとコールバックをする。

is None と == None の違い

if文だと普通は ==で指定するとおもってましたが、「is」がつかわれてます。まずは、Noneについて

if older_post_link is None:

Noneは、「nullオブジェクト」で、かんたんに言えば「空っぽのオブジェクト」。そして、「older_post_link」がNoneのときに、「True」を返す。
returndeで、呼び出し元にそのデータを返すのだが、何も無いを返して終了。

参考:PythonではNoneの比較は==ではなくisを使う

==だとエラーになる可能性がる、あと判別が早い。とのこと。
ここは、機会的にNone のときは is  か is not とおぼえましょうw

最後に、繰り返す

older_post_linkがTrueでなければ、止まらず、次のプログラムが反応する。

older_post_link = response.urljoin(older_post_link)
       # 次のページをのリクエストを実行する
       yield scrapy.Request(older_post_link, callback=self.parse)

最後の、Requestとは?

HTTPリクエストを表します。これは通常スパイダーで生成され、ダウンローダーによって実行され、そして、 Response が生成されます。

responseとは?

HTTPレスポンスを表し、通常は(ダウンローダーによって)ダウンロードされ、処理のためにスパイダーに送られます。

selfとはなんだろう?

あとの疑問は、def parse(self, response): こちらに記載されている。
selfですね。

selfとはインスタンス自身を指す慣用語(※)です。
インスタンスメソッド内で、インタンス変数や別のインスタンスメソッドを参照する際、selfを用います。

引用:Pythonのselfの使い方を現役エンジニアが解説【初心者向け】

こちら最初の def の関数ぽいものを「メソッド」と呼びます。

単独で呼び出しできるのが「関数」
変数や値に付けて呼び出すのが「メソッド」

へーーー。メソッドは前(.)を付けて呼び出す関数とのことなので、

def parse(self, response):

クラス内のメソッドの第1引数には、selfを渡す。
だが、

def __init__(self, 引数リスト)

だがこいつよく見てみると。
クラスのインスタンス生成時に、インスタンス変数設定する あの
コンストラクタさんではない。初期化する必要がなければやらなくてよいのかな?

中途半端におわりますが、クラスについてはまだ勉強不足なので、学習して別の機会にまとめたいと思います!

class ScrapyBlogSpiderSpider(scrapy.Spider):

基礎だと思うが、class 新規クラス名(継承したいクラス名):
そもそも継承しているということか。

なので、ドキュメントにも、

scrapy.Spider をサブクラス化

と書かれているのかな。
https://doc-ja-scrapy.readthedocs.io/ja/latest/intro/tutorial.html#our-first-spider

この記事が気に入ったらサポートをしてみませんか?