Crawl dữ liệu từ Shopee sử dụng Scrapy + Splash + ItemLoader và phân trang

Yêu cầu:

  • Scrapy
  • Splash (Splash chạy trên docker)

Nội dung bài viết này tham khảo bài viết ở viblo.asia, tác giả đã giải thích rất chi tiết, các bạn có thể đọc để hiểu thêm.
Ở Bài này mình chỉ sử dụng thêm ItemLoader để có thể tùy chỉnh dữ liệu dễ hơn, đồng thời sử dụng phân trang đơn giản hơn.

1. Tạo Spinder

scrapy genspider shopee https://shopee.vn

Xác định các thông tin cần lấy, Ví dụ

  • title - tên sản phẩm
  • price - giá sản phẩm

2. Trong tệp items.py

Sử dụng Itemloader để dễ xử lý thôn tin khi cần

# items.py
import scrapy
from scrapy.loader import ItemLoader
from itemloaders.processors import TakeFirst, MapCompose
from w3lib.html import remove_tags

""" Dùng với ItemLoader """
# Xóa dấu chấm (.) trong giá
def remove_dot(value):
    return value.replace('.', '')
# xóa khoảng trắng đầu và cuôi trong tiêu đề nếu có
def remove_space(value):
    return value.strip()

class ShopeeProduct(scrapy.Item):
    title = scrapy.Field(input_processor = MapCompose(remove_tags, remove_space), output_processor = TakeFirst())
    price = scrapy.Field(remove_tags, remove_vnd, remove_dot), output_processor = TakeFirst())

3. Trong tệp shopee.py

  • Vì Shopee sử dung Javascript hiển thị danh sách sản phẩm, nên ta sử dụng scrapy_splash.
  • Sử dụng ItemLoader để có thể dễ dàng thêm bớt dữ liệu vào chuỗi trước khi nó được lưu lại.
import re
import scrapy
from scrapy_splash import SplashRequest
from ..items import ShopeeProduct
from scrapy.loader import ItemLoader

class ShopeeSpider(scrapy.Spider):
    name = 'shopee'
    allowed_domains = ['shopee.vn']

    page_number = 0  # trang mặc định page=0

    start_urls = ["https://shopee.vn/sp.btw2"]  # đây là 1 trang cửa hàng

    def start_requests(self):
        for url in self.start_urls:
            yield SplashRequest(
                url,
                endpoint="render.html",
                args={
                    'wait': 5,
                },
                callback=self.parse,
                dont_filter=True
            )

    def parse(self, response):
        for data in response.css(".col-xs-2-4"):

            l = ItemLoader(item = ShopeeProduct(), selector = data)

            l.add_css('title', '.pcmall-shopmicrofe_2498rm', re='([^]]+$)')  # Xóa chuỗi [text]
            l.add_css('price', '.pcmall-shopmicrofe_1KcSLJ')
           
            yield l.load_item()


           # phân trang
            next_page = 'https://shopee.vn/sp.btw2?page='+ str(ShopeeSpider.page_number)

            if ShopeeSpider.page_number < 5:  # Giới hạn quét bao nhiêu trang
                ShopeeSpider.page_number += 1
                yield response.follow(next_page, callback=self.parse)

4. Bây giờ, đã có thể Crawl và xuất dữ liệu shopee

Ví dụ: Crawl và xuất dữ liệu ra tệp shopee-product.csv

scrapy crawl shopee -o shopee-product.csv