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 ở trongstart_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ênitem['title'] = response.xpath('//h1[@class="post-title u-fontSizeLargest u-md-fontSizeLarger"]/text()').extract()[0].strip()
Tìm kiếm thẻ h1 có classpost-title u-fontSizeLargest u-md-fontSizeLarger
và 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ấythumb_link
với img có classpost-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ênyield 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ử