Hướng dẫn crawl website với Scrapy

Crawl

5 min read
Bởi Quang Dang
Hướng dẫn crawl website với Scrapy

Scrapy là một trình thu thập dữ liệu dựa trên Python có thể được sử dụng để trích xuất thông tin từ các trang web. Nó nhanh và đơn giản, và có thể điều hướng các trang giống như trình duyệt có thể. Nó là một trong những framework  mã nguồn mở tốt nhất dùng để crawl dữ liệu. (link)

Bước 1: Cài đặt

Ở đây chúng tôi sử dụng virtualenv để cài đặt scrapy. Điều này cho phép chúng tôi cài đặt scrapy mà không ảnh hưởng đến các mô-đun cài đặt hệ thống khác.

Tạo một thư mục chứa project crawler dữ liệu dùng để lưu trữ code và tạo một môi trường ảo trong đó.

mkdir crawlBlogArrow
cd crawlBlogArrow
virtualenv venv
. venv/bin/activate

Cài đặt scrapy

pip install scrapy

Kiểm tra xem nó đã hoạt động hay chưa. Màn hình dưới đây cho thấy phiên bản mà tôi đang sử dụng là 1.8.0

Bước 2: Tạo Project và sử dụng

2.1 Tạo Project

Để tạo 1 project scrapy ta sử dụng câu lệnh sau

scrapy startproject crawl

Đây là cấu trúc thư mục chúng ta vừa tạo thông qua Scrapy

crawl/
├── crawl                             # nơi chứa code của dự án
│   ├── init.py
│   ├── items.py                    # nơi định nghĩa các trường dữ liệu cần lưu vào db
│   ├── pipelines.py              # nơi xử lý các item trích xuất được và lưu vào db
│   ├── settings.py                # cấu hình thêm các phần mở rộng (middlewares) và các thông số cấu hình khác
│   └── spiders                     # thư mục chứa các spider
│       └── init.py
└── scrapy.cfg                      # file cấu hình về deploy và settings của project

2.2 Đặc tả dữ liệu

File items.py được sử dụng để khai báo metadata cho những dữ liệu mà chúng ta muốn scrape. Trong file này có class StackItem là class được kế thừa từ class Item của Scrapy. Trong class này đã định nghĩa trước một số đối tượng mà Scrapy cần dùng để scrape.

import scrapy

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

Bây giờ, chúng ta sẽ thêm và những dữ liệu mà chúng ta cần

import scrapy

class StackItem(scrapy.Item):
    title = scrapy.Field()
    thumb = scrapy.Field()    
    content = scrapy.Field()    
    author = scrapy.Field()

2.3 Tạo spiders

Chúng ta sẽ tạo một  spider blogarrow.py trong thư mục spiders  đã được tạo ở trên. Thư mục này khá đặc biệt, bởi nó là nơi chúng ta đưa ra các chỉ định cho Scrapy biết chính xác chúng ta muốn thu thập dữ liệu gì. Trong thư mục này, bạn có thể định nghĩa các Spider khác nhau cho các trang Web khác nhau.

Bắt đầu bằng một class kế thừa từ class Spider của Scrapy và chúng ta sẽ thêm vào các thuộc tính cần thiết.

from scrapy import Spider

class CrawlerSpider(Spider):
    name = "crawler"
    allowed_domains = ["blog.arrow-tech.vn"]
    start_urls = [
        "https://blog.arrow-tech.vn/detect-labels-faces-and-landmarks-in-images-with-the-cloud-vision-api/",
    ]

Những thuộc tính ở đây khá dễ hiểu, chúng thể hiện ý nghĩa qua chính tên của mình. Nếu cần thêm thông tin, bạn có thể tham khảo ở đây:

  • name định nghĩa tên của Spider.
  • allowed_domains chứa URL gốc của trang Web bạn muốn scrape.
  • start_urls là danh sách các URL để Spider bắt đầu quá trình scraping. Tất cả mọi dữ liệu sẽ được Spider download từ các URL ở trong start_urls này.

XPath selector

Một điều rất quan trọng, đó là Scrapy sử dụng XPath selector để trích xuất dữ liệu từ các trang Web. Nói một cách khác, đó là chúng ta có thể chọn lọc ra một thành phần chính xác trên một trang Web bằng cách sử dụng XPath.

Trích xuất dữ liệu

Chúng ta thực hiện trích xuất dữ liệu với đoạn code dưới đây

import scrapy
from scrapy import Spider
from crawl.items import CrawlItem

class CrawlerSpider(Spider):
    name = "crawler"
    allowed_domains = ["blog.arrow-tech.vn"]
    start_urls = [
        "https://blog.arrow-tech.vn/detect-labels-faces-and-landmarks-in-images-with-the-cloud-vision-api/",
    ]
    
    def parse(self, response):

        item = CrawlItem()
        item['title'] = response.xpath('//h1[@class="post-title u-fontSizeLargest u-md-fontSizeLarger"]/text()').extract()[0].strip()    
        thumb_link = "https://blog.arrow-tech.vn" + response.xpath('//img[@class="post-img u-block u-marginAuto"]/@src').extract()[0].strip()   
        item['thumb'] = thumb_link.split('/')[-1]
        yield scrapy.Request(thumb_link,callback=self.parse_img)
        item['author'] =  response.xpath('//a[@class="link link--underline u-fontWeightMedium u-textColorDarker"]/text()').extract()[0].strip() 
        item['content'] =  response.xpath('//div[@class="post-inner js-post-content"]').extract()[0].strip() 
        yield item


    def parse_img(self, response):
        with open("img/%s" % response.url.split('/')[-1], 'wb') as f:
            f.write(response.body)
    

    
  • item = CrawlItem() Khởi tạo một mảng dữ liệu như đã đặc tả ở bên trên
  • item['title'] = response.xpath('//h1[@class="post-title u-fontSizeLargest u-md-fontSizeLarger"]/text()').extract()[0].strip() Tìm kiếm thẻ h1 có class post-title u-fontSizeLargest u-md-fontSizeLargervà lấy text của nó text()
  • thumb_link = "https://blog.arrow-tech.vn" + response.xpath('//img[@class="post-img u-block u-marginAuto"]/@src').extract()[0].strip()  Lấy thumb_link với img có class post-img u-block u-marginAuto
  • item['thumb'] = thumb_link.split('/')[-1] Lấy trường thumb bằng các xữ lý biến thumb_link vừa lấy được ở trên
  • yield scrapy.Request(thumb_link,callback=self.parse_img) Thực hiện download image thumb từ thumb_link

 Đoạn code dưới đây có chức năng lưu ảnh thumb vào máy của chúng ta (ở đây mình lưu trữ vào thư mục img cùng cấp với thư mục project)

def parse_img(self, response):
        with open("img/%s" % response.url.split('/')[-1], 'wb') as f:
            f.write(response.body)
  • item['content'] =  response.xpath('//div[@class="post-inner js-post-content"]').extract()[0].strip() Lấy content với thẻ div có class là post-inner js-post-content

Sau khi đã thực hiện xong những bước trên, chạy lệnh crawl

Lệnh này sẽ lưu trữ kết quả crawl vào file result.json

scrapy crawl crawler -o result.json 

Bạn có thể clone ví dụ trên ở đây để dùng thử

phobrv/demo_use_scrapy
Demo use Scrapy to crawler website data. Contribute to phobrv/demo_use_scrapy development by creating an account on GitHub.