Scrapy - Thử crawl bóc tách dữ liệu một cách đơn giản

Chào mọi người, mình cumback rồi đây, nhưng nay chán django rồi nên chuyển sang crawl dữ liệu cho có tí mới mẻ.

Mình dùng thằng Scrapy để clawling websiteextracting structured data.
Chi tiết về thằng này thì mọi người có thể xem tại đây

Ok, bắt đầu thôi. Trước tiên cứ cài đặt scrapy cái đã. Rất đơn giản, cứ package của python thôi.

$ pip3 install Scrapy

Xong cài đặt thì xác định trang web cần clone. Ở bài này, mình lấy trang http://quotes.toscrape.com trên document cho dễ chơi, dễ trúng thưởng. Mình sẽ lấy các bài viết trên trang đó cùng với tác giả của bài đó nữa.

Rồi tiếp theo là bắt tay vào thực hiện thôi!

Tạo Scrapy project

scrapy startproject quotes

thư mục project quotes sẽ được tạo ra với nội dung:

quotes/
    scrapy.cfg            # deploy configuration file
    quotes/             # project's Python module, you'll import your code from here
        __init__.py
        items.py          # project items definition file
        middlewares.py    # project middlewares file
        pipelines.py      # project pipelines file
        settings.py       # project settings file
        spiders/          # a directory where you'll later put your spiders
            __init__.py

Tạo Spider

Tạo một file tên là quotes_spider.py trong thư mục spiders đã được tạo ở trên và đây cũng là file thao tác chính trong bài này. Thư mục là nơi mọi người đưa ra các chỉ định cho Scrapy biết muốn thu thập dữ liệu gì. Trong thư mục này, mọi người có thể định nghĩa các Spider khác nhau cho các trang Web khác nhau.

Trước tiên cứ thêm các định nghĩa ban đầu cho spider(quotes_spider.py) đã.

import scrapy

class QuotesSpider(scrapy.Spider):
    name = "quotes"
    def start_requests(self):
        start_urls = [
            'http://quotes.toscrape.com/page/1/',
        ]
        for url in urls:
            yield scrapy.Request(url=url, callback=self.parse)

Ta thấy, trong mỗi quote được thể hiện giống như sau:

<div class="quote">
    <span class="text">“The world as we have created it is a process of our
    thinking. It cannot be changed without changing our thinking.”</span>
    <span>
        by <small class="author">Albert Einstein</small>
        <a href="/author/Albert-Einstein">(about)</a>
    </span>
    <div class="tags">
        Tags:
        <a class="tag" href="/tag/change/page/1/">change</a>
        <a class="tag" href="/tag/deep-thoughts/page/1/">deep-thoughts</a>
        <a class="tag" href="/tag/thinking/page/1/">thinking</a>
        <a class="tag" href="/tag/world/page/1/">world</a>
    </div>
</div>

Để crawl dữ liệu, ta dùng CSS trong response khi call đến site.(Ngoài CSS còn có XPath nhưng để thao tác đơn giản hơn với HTML thì mình dùng XPath). Mình tạo hàm parse để crawl ra nội dung của các quotes.
Trong quotes_spider.py mình thêm:

def parse(self, response):
    for quote in response.css('div.quote'):
        yield {
            'text': quote.css('span.text::text').extract_first(),
            'author': quote.css('small.author::text').extract_first(),
            'tags': quote.css('div.tags a.tag::text').extract(),
        }

Giải thích thêm là:

  • response.css('div.quote') nó sẽ lấy tất cả bài quotes có thẻ HTML là
  • quote.css('span.text::text').extract_first()::text sẽ lấy text trong thẻ qua extract_first()
  • 'tags': quote.css('div.tags a.tag::text').extract() lấy tất cả tags của bài quote, trả ra array

Chạy Spider thôi

$ scrapy crawl quotes

nó sẽ gửi một số request cho quotes.toscrape.com và nhận được phản hồi (response) và chúng ta sẽ bóc tách data từ response mà chúng ta vừa nhận được bằng hàm parse. Và kết quả:

Để lưu ra file json

$ scrapy crawl quotes  -o quotes.json 

Crawl in next_page

Để crawl không chỉ trong 1 page mà ở tất cả các page bằng cách lấy liên kết page tiếp và đệ quy parse với mỗi liên kết.
Thêm đoạn sau vào cuối parse

next_page = response.css('li.next a::attr(href)').extract_first()
    if next_page is not None:
        yield response.follow(next_page, callback=self.parse)

và run lại spider là có thể lấy được tất cả các bài quote trong quotes.toscrape.com.

Trên đây, mình vừa giới thiệu nhẹ ví dụ đơn giản về crawl bằng Scrapy. Mọi người có thể tham khảo thêm tại: https://docs.scrapy.org/en/latest/index.html