Giới thiệu/hướng dẫn về Crawler với Scrapy Framework (Phần 2)

Ở phần trước mình đã giới thiệu với các bạn về thành phần và luồng hoạt động của Scrapy Framwork, tới phần này mình sẽ hướng dẫn các bạn cài đặt và sử dụng Scrapy để crawl tin tức ở trang https://sohoa.vnexpress.net/

1. Cài đặt

Mình sẽ sử dụng virtualenv và cài đặt thông qua pip. Nếu các bạn chưa biết về chúng thì có thể tìm hiểu trên mạng và cài đặt chúng. Trước tiên tạo file requirements.txt:

touch requirements.txt

hoặc

pip freeze > requirements.txt

Mở file requirements.txt và thêm các thư viện sau:

lxml
parsel
w3lib
twisted
cryptography
pyOpenSSL
Scrapy

Save lại và chạy:

pip install -r requirements.txt

Vậy là chúng ta đã cài đặt xong Scrapy rồi đấy.

2. Sử dụng

a. Tạo project

Ta chạy câu lệnh sau để khởi tạo dự án có tên scraper:

scrapy startproject scraper

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

scraper/
├── scraper                             # 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

b. Tạo spiders

Chúng ta sẽ tạo 1 con spider sohoavnexpress.py để extract bài viết từ link https://sohoa.vnexpress.net/tin-tuc/doi-song-so/tap-chi-co-chu-ky-steve-jobs-duoc-ban-gia-50-000-usd-3662652.html. Trong bài báo trên, chúng ta cần lấy những thông tin: tiêu đề, phần giới thiệu, nội dung, tác giả, ngày đăng, mình sẽ dùng xpath để trích xuất dữ liệu.

# -*- coding: utf8 -*-
import scrapy

class SohoaVnexpressNet(scrapy.Spider):
    name = "sohoa"

    def start_requests(self):
        urls = [
            'https://sohoa.vnexpress.net/tin-tuc/doi-song-so/tap-chi-co-chu-ky-steve-jobs-duoc-ban-gia-50-000-usd-3662652.html',
        ]
        for url in urls:
            yield scrapy.Request(url=url, callback=self.parse_artilce)

    def parse_artilce(self, response):
        artilce = {}
        artilce['title'] = response.xpath('//*[@id="col_sticky"]/h1/text()').extract()[0].encode('utf-8').strip()
        artilce['description'] = response.xpath('//*[@id="col_sticky"]/h2').extract()[0].encode('utf-8').strip()
        artilce['content'] = response.xpath('//*[@id="col_sticky"]/article').extract()[0].encode('utf-8').strip()
        artilce['author'] = response.xpath('//*[@id="col_sticky"]/article/p[5]/strong/text()').extract()[0].encode('utf-8').strip()
        artilce['publish_date'] = response.xpath('//*[@id="col_sticky"]/header/span/text()').extract()[0].encode('utf-8').strip()
        for key, text in artilce.iteritems():
            print "{key}: {text}".format(key = key.upper(), text = text)

Sau đó chạy lệnh sau:

scrapy crawl sohoa

và kết quả

CONTENT: <article class="content_detail fck_detail width_common block_ads_connect">
                <table align="center" border="0" cellpadding="3" cellspacing="0" class="tplCaption"><tbody><tr><td>
				<img alt="tap-chi-co-chu-ky-steve-jobs-duoc-ban-gia-50000-usd" data-natural-width="500" src="https://i-sohoa.vnecdn.net/2017/10/29/a1-5746-1509288199.jpg"></td>
		</tr><tr><td>
				<p class="Image">
					Tạp chí Newsweek với hình Jobs trên trang bìa. </p>
			</td>
		</tr></tbody></table><p class="Normal">
	Tạp chí Newsweek số ra ngày 24/10/1988 có hình ảnh trang bìa là Steve Jobs, cố CEO của Apple. Khi đó, ông mới 33 tuổi và đang chuẩn bị cho lễ ra mắt máy tính NeXT đầu tiên. Nhưng điểm đặc biệt nhất trên cuốn tạp chí này chính là chữ ký của ông cùng lời nhắn nhủ về niềm đam mê cá nhân.</p><p class="Normal">
	Cuốn tạp chí vốn thuộc sở hữu của <span>Diane Williams khi đó đang làm việc cho </span><span>Lotus Development - công ty được IBM mua lại năm 1995 và khai tử năm 2013. Cô có mặt tại lễ ra mắt máy tính NeXT tại </span><span>Cambridge, Massachusetts (Mỹ) ít ngày sau khi cuốn tạp chí xuất bản. </span><span>Williams đã tiếp cận Jobs để xin chữ ký và đưa ra lời đề nghị "viết một điều gì đó xuất phát từ trái tim của anh". Jobs mỉm cười cầm lấy cuốn tạp chí và viết: "Tôi yêu việc chế tạo". Trong lời nhắn nhủ, cựu CEO của Apple còn nhấn mạnh chữ "tình yêu" đi kèm chữ ký. </span></p><p class="Normal">
	Kỷ vật của <span>Williams mới đây được nhà đấu giá </span><span style="color:rgb(34,34,34);">RR Auction đem ra chào bán với giá khởi điểm 1.000 USD. Theo Appleinsider, phiên đấu giá nhận được 34 lần đặt giá từ 18 người mua đủ điều kiện. Mức giá cuối cùng được đưa ra là 50.587,6 USD - số tiền đủ mua 44 chiếc iPhone X dung lượng 256 GB sắp bán ra của Apple. </span></p><p class="Normal">
	Apple mua lại NeXT vào năm 1997 với giá 429 triệu USD đi kèm là 1,5 triệu cổ phiếu của Apple. Đây là bước ngoặt lớn của "Quả táo" vì hợp đồng này đã đưa Steve Jobs trở lại công ty mà ông chính là người sáng lập. Ngay năm sau đó, hãng phát hành iMac và tiếp nối sự thành công cho tới tận bây giờ. Apple đang là công ty có giá trị lớn nhất trên thế giới. </p>                    <p class="author_mail">
        <strong>Tuấn Hưng</strong>
                    <a href="javascript:;" class="email" id="send_mail_author" data-article-id="3662652"><i class="ic ic-email"></i></a>
            </p>
                            </article>
AUTHOR: Tuấn Hưng
DESCRIPTION: <h2 class="description">Cuốn tạp chí phát hành năm 1988 khi Jobs chuẩn bị ra mắt máy tính NeXT đầu tiên được bán với giá gấp 50 lần con số khởi điểm. </h2>
PUBLISH_DATE: Chủ nhật, 29/10/2017
TITLE: Tạp chí có chữ ký Steve Jobs được bán giá 50.000 USD

Như phần trước mình đã nói về luồng dữ liệu của Scrapy, khi chạy câu lệnh trên, Scrapy sẽ duyệt tất cả các file trong folder spiders để tìm file có name = 'sohoa', khi tìm được nó sẽ chạy vào hàm start_requests . Như vậy, trong đoạn code trên, name = "sohoa" là để định danh cho spider, hàm start_requests là chúng ta override từ class scrapy.Spider, hàm parse_artilce là chúng ta tự định nghĩa và sẽ callback khi tạo Request. Có một số bạn sẽ tự hỏi sao mình lấy được các đoạn xpath trên thì đơn giản là mình dùng chrome inspect để copy xpath thôi và thêm vào hàm text() để chỉ lấy phần content trong title, author và publish_date. Trong xpath còn rất nhiều hàm hỗ trợ việc extract dữ liệu hiệu quả, các bạn có thể tự tìm hiểu thêm.

3. Tổng kết

Như vậy mình đã hướng dẫn các bạn các cài đặt và sử dụng scrapy để trích xuất một bài báo, phần tới mình sẽ hướng dẫn tối ưu lại đoạn code trên ra sao cho dễ quản lý và lưu dữ liệu sau khi trích xuất vào db Nguồn tham khảo: https://doc.scrapy.org/en/latest/intro/tutorial.html