Scrapy có cung cấp thư viện scrapy-selenium cho phép việc sử dụng Seleinum để lấy dữ liệu trang web trước khi trả về cho spdier xử lý. Tuy nhiên trong 1 số trường hợp ví dụ mình không muốn dùng selenium bình thường mà mình muốn dùng undetected-chromedriver vì nó giúp bypass Cloudflare trên website, muốn add proxy thông qua extension của chrome, muốn scroll lên xuống và một số hành động trước khi vào spider,… thì việc sử dụng thư viện sẽ là rất hạn chế. việc xử dụng thư viện cũng rất tiện lợi trong 1 số trường hợp đơn giản và mình sẽ giới thiệu trong bài viết sau. Trong bài viết này mình sẽ nói về việc sử dụng undetected-chromedriver xây dựng SeleniumMiddleware bypass Cloudflare website.
Khởi tạo project
Khởi tạo một project scrapy:
1
scrapy startproject seleniummiddlewarescrapydemo
Tạo một spider để crawl dữ liệu, ở đây mình crawl dữ liệu từ trang vinpearl.com/
:
1
scrapy genspider vinpearl_dot_com https://vinpearl.com/vi/news/ha-noi
Cài đặt thư viện cần thết:
1
2
pip install scrapy
pip install scrapy-selenium
SeleniumMiddleware
Tạo class SeleniumBaseMiddleware
như sau:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class SeleniumBaseMiddleWare(object):
@classmethod
def from_crawler(cls, crawler):
middleware = cls()
crawler.signals.connect(middleware.spider_opened, signals.spider_opened)
crawler.signals.connect(middleware.spider_closed, signals.spider_closed)
return middleware
def get_chrome_options(self):
options = uc.ChromeOptions()
return options
def spider_opened(self, spider):
try:
options = self.get_chrome_options()
self.driver = uc.Chrome(
options=options,
version_main=127
)
except Exception as e:
logging.error(f"Failed to open spider and create driver: {e}")
raise
def process_request(self, request, spider):
logging.info('SELENIUM FETCH URL {}'.format(request.url))
self.driver.get(request.url)
request.meta.update({'driver': self.driver})
content = self.driver.page_source
return HtmlResponse(
request.url, encoding="utf-8", body=content, request=request
)
def process_response(self, request, response, spider):
return response
def spider_closed(self, spider):
self.driver.quit()
spider_opened()
khởi tạodriver
và các tham số cần thiết, ví dụ như làoptions
hay nếu có thêm proxy chúng ta cũng sẽ thêm proxy tại đây.spider_closed()
tắtdriver
sau khi kết thúc crawl.process_request()
xử lý việc lấy về dữ liệu, gánrequest.meta.update({'driver': self.driver})
để sử dụng driver phía trong spider nếu cần thiêt.
Trong spider vinpearl_dot_com
nếu có những tác vụ mà cần sử dụng driver
như scroll lên xuống, click button thì sẽ lấy ra driver
như sau:
1
2
3
4
driver = response.request.meta["driver"]
driver.execute_script(
"window.scrollTo(0, document.body.scrollHeight);"
)
Với điều kiện là driver
đã được update vào trong request của middleware trước đó request.meta.update({'driver': self.driver})
như trong SeleniumBaseMiddleware.
Trong file settings
thêm SeleniumBaseMiddleware vào trong DOWNLOADER_MIDDLEWARES:
1
2
3
DOWNLOADER_MIDDLEWARES = {
"seleniummiddlewarescrapydemo.middlewares.SeleniumBaseMiddleWare": 543,
}
Bây giờ việc crawl website rất là dễ dàng khi không còn bị chặn bởi Cloudflare và đã gen toàn bộ mã Javascript của website động thành HTML để dễ dàng phân tích.
Toàn bộ project xem tại: https://github.com/demanejar/selenium-middleware-scrapy-demo