Trong quá trình cào dữ liệu, sẽ có lúc bạn cần phải thực hiện việc đăng nhập vì nhiều nhiều lí do. Trong phần này chúng ta sẽ tìm hiểu cách đăng nhập.
Chúng ta sẽ dùng trang quotes.toscrape.com/login làm ví dụ. Trước khi đi vào viết code Scrapy thì chúng ta phải tìm hiểu cách server xử lý việc đăng nhập như thế nào.
Phần đăng nhập của trang web này khá đơn giản, chỉ có 2 ô điền thông tin là Username và Password. Trang này không có phần đăng kí thông tin, và để đăng nhập thì chúng ta có thể nhập bất cứ thứ gì vào cũng được, miễn là không bỏ trống ô nào.
Chúng ta mở chức năng Inspect của Chrome rồi mở tab Network, sau đó đăng nhập thử, ở đây mình đăng nhập với username và password là chữ cái a.
Khi chúng ta bấm nút Login thì trình duyệt sẽ gửi một Request POST lên máy chủ, bạn có thể tìm hiểu thêm về POST và GET cũng như các phương thức HTTP khác trên mạng. Ở dưới ô Name chúng ta có thể thấy những Request đã được gửi/nhận. trong đó có request login được gửi đi khi chúng ta bấm nút Login, bấm vào request đó thì ô bên phải sẽ hiện ra cụ thể những thông tin gì đã được truyền đi và những gì đã được nhận về. Kéo xuống dưới cùng ô này, chúng ta thấy thông tin về Form data, bao gồm username
, password
và csrf_token
.
Username
và password
thì chúng ta đã hiểu, nhưng csrf_token
là gì? Đây là một element ẩn mà server gửi cho chúng ta khi chúng ta vào trang /login, có tác dụng chống các loại tấn công, bot…v.v. Và khi gửi Request login thì chúng ta phải gửi lại cả thông tin này, nếu không sẽ không thể đăng nhập được.
Quay trở lại với Scrapy, chúng ta tạo một Spider với tên login như sau:
$ scrapy genspider login web
File login.py
được tạo ra trong thư mục spiders. Chúng ta sửa file này như sau:
# -*- coding: utf-8 -*- import scrapy from scrapy.http import FormRequest class LoginSpider(scrapy.Spider): name = 'login' allowed_domains = ['web'] start_urls = ['http://quotes.toscrape.com/login',] def parse(self, response): csrf_token = response.xpath('//*[contains(@name, "csrf_token")]//@value').extract() return [ FormRequest( "http://quotes.toscrape.com/login", formdata={"username": "a", "password": "a", "csrf_token":csrf_token[0]}, callback=self.parse_item, dont_filter=True)] def parse_item(self, response): # Cào dữ liệu như bình thường pass
Lớp LoginSpider
cũng được kế thừa từ lớp Spider như trong các bài trước. Ở đây chúng ta cho phương thức parse()
trả về một đối tượng FormRequest.
Trong form chúng ta điền vào URL của trang login, một đối tượng JSON là formdata
với 3 thông tin là username
, password
và csrf_token
. Hai tham số còn lại là callback
và dont_filter
đã được giải thích trong các phần trước.
Để lấy được csrf_token
thì chúng ta dùng gọi response.xpath()
và đưa vào đoạn XPath dẫn tới giá trị csrf_token
.
Bây giờ chúng ta có thể chạy:
$ scrapy crawl login ... DEBUG: Crawled (200) <GET http://quotes.toscrape.com/login> (referer: None) DEBUG: Redirecting (302) to <GET http://quotes.toscrape.com/> from <POST http://quotes.toscrape.com/login/> DEBUG: Crawled (200) <GET http://quotes.toscrape.com/> (referer: http://quotes.toscrape.com/login) ...
Nếu khi chạy chúng ta thấy có đoạn DEBUG Redirecting (302) thì tức là việc đăng nhập thành công. Vì khi đăng nhập xong thì chúng ta sẽ được chuyển hướng lại về trang chủ.
Nếu muốn chắc ăn hơn, chúng ta có thể tìm nút Logout:
# -*- coding: utf-8 -*- import scrapy from scrapy.http import FormRequest class LoginSpider(scrapy.Spider): name = 'login' allowed_domains = ['web'] start_urls = ['http://quotes.toscrape.com/login',] def parse(self, response): csrf_token = response.xpath('//*[contains(@name, "csrf_token")]//@value').extract() return [ FormRequest( "http://quotes.toscrape.com/login", formdata={"username": "a", "password": "a", "csrf_token":csrf_token[0]}, callback=self.parse_item, dont_filter=True)] def parse_item(self, response): logout = response.xpath('//*[contains(@href, "logout")]') if len(logout) == 1: print("Login success---")
Khi chaỵ, nếu outut có dòng “Login success—“ thì chúng ta đã đăng nhập thành công.
$ scrapy crawl login ... Login success--- ...