山傘のプログラミング勉強日記

プログラミングに関する日記とどうでもよい雑記からなるブログです。

Pythonクローリング&スクレイピング[増補改訂版] ―データ収集・解析のための実践開発ガイドー その17

第6章 フレームワーク Scrapy

今回から新しい章を進めていきます。

Scrapy

クローロングとスクレイピングのための Pythonフレームワークである Scrapy を使います。

scrapy runspider myscript.py

上記のコマンドで実行します。

import scrapy

class BlogSpider(scrapy.Spider):
    name = 'blogSpider'
    start_urls = ['http://blog.scrapinghub.com']

    def parse(self, response):
        """
        ページに投稿されたタイトルを抜き出し、次のページのリンクをたどる
        """
        for title in response.css('post-header>h2'):
            yield {'title': title.css('a ::text').get()}

        for next_page in response.css('a.next-posts-link'):
            yield response.follow(next_page, self.parse)

Scrapy プロジェクト

scrapy startproject myproject

これを実行して Scrapy プロジェクトを作成します。

f:id:yamakasa3:20190913225041p:plain

Scrapy Shell

インタラクティブスクレイピングを行うために、Scrapy Shell というものがあります。

URL を指定してシェルを起動します。

scrapy shell https://news.yahoo.co.jp/pickup/6336500

マンボウ実は速く泳げる 話題 | 2019/9/14(土) 10:11 - Yahoo!ニュース

f:id:yamakasa3:20190914170415p:plain

f:id:yamakasa3:20190914210404p:plain

Yahoo!ニュースのスクレイピング

news.py
import scrapy

from myproject.items import Headline

class NewsSpider(scrapy.Spider):
    name = 'news'
    allowed_domains = ['news.yahoo.co.jp'] # クロールを許可するドメイン
    start_urls = ['https://news.yahoo.co.jp/'] # クロールを開始するURL

    def parse(self, response):
        """
        トップページのトピックス一覧からそれぞれのトピックスのリンクを抜き出す
        """
        
        for url in response.css('ul.topicsList_main a::attr("href")').re(r'/pickup/\d+$'):
            yield response.follow(url, self.parse_topics)

    def parse_topics(self, response):
        """
        トピックスのページからタイトルと本文を抜き出す
        """
        item = Headline()
        item['title'] = response.css('.tpcNews_title::text').get()
        item['body'] = response.css('.tpcNews_summary').xpath('string()').get()
        print('---------------------------')
        print(item['title'])
        yield item
items.py
import scrapy

class MyprojectItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    pass

class Headline(scrapy.Item):
    """
    Yahoo! ニュースのヘッドラインを表すItem
    """

    title = scrapy.Field()
    body = scrapy.Field()

f:id:yamakasa3:20190914231206p:plain