Web Scraping dễ dàng với Scrapy (phần 9)

Các Item loaders

Có hai vấn đề phổ biến cái bạn có thể gặp phải trong khi rút dữ liệu từ Web:
+ Cho cùng website, bố cục trang và HTML nằm dưới có thể là khác nhau. Nếu bạn scrape một website TMĐT, bạn sẽ
thường có một regular price và một discounted price, với các XPath / CSS selectors khác nhau.
+ Dữ liệu có thể là bẩn và bạn có thể cần bình thường hóa nó, lại một lần nữa cho một website TMĐT nó có thể là
cách thức các prices được hiển thị ví dụ ($1.00, $1, $1,00).
Scrapy đi với một giải pháp tích hợp cho cái này, ItemLoaders. Nó là một cách thức thú vị để định vị product object
của chúng ta.
Bạn có thể thêm một vài biểu thức XPath vào cùng trường vật, và nó sẽ test nó tuần tự. Theo mặc định, trong trường
hợp Scrapy có thể thành công nhiều hơn một biểu thức XPath, nó sẽ load tất cả chúng vào một list. Bạn có thể
thấy nhiều ví dụ của các cái xử lí đầu vào và đầu ra trong tài liệu hướng dẫn Scrapy.
Nó thực sự là hữu dụng khi bạn cần chuyển dạng/làm sạch dữ liệu bạn rút. Ví dụ, rút currency khỏi một price,
chuyển dạng một đơn vị sang cái khác (centimeter thành meters, Celsius thành Fahrenheit) …
Trong trang web của chúng ta chúng ta có thể thấy product title với các biểu thức XPath //title và
//section[1]//h2/text().
Sau đây là làm cách nào bạn có thể sử dụng Itemloader trong trường hợp này:

def parse(self, response):

l = ItemLoader(item=Product(), response=response)
l.add_xpath(‘price’, “//div[@class=’my-4′]/span/text()”)
l.add_xpath(‘title’, ‘//section[1]//h2/text()’)
l.add_xpath(‘title’, ‘//title’)
l.add_value(‘product_url’, response.url)
return l.load_item()

Nói chung, bạn chỉ muốn XPath khớp đầu tiên, nên bạn sẽ cần thêm output_processor=TakeFirst() này vào constructor
trường của item của bạn.
Và đó là chính xác chúng ta sẽ làm gì trong trường hợp của chúng ta, nên một cách tiếp cận tốt hơn sẽ là tạo ItemLoader
của bản thân chúng ta và khai báo một cái xử lí đầu ra mặc định để lấy XPath khớp đầu tiên:

from scrapy.loader import ItemLoader
from scrapy.loader.processors import TakeFirst, MapCompose, Join

def remove_dollar_sign(value):

return value.replace(‘$’, ”)

class ProductLoader(ItemLoader):

default_output_processor = TakeFirst()
price_in = MapCompose(remove_dollar_sign)

Tôi cũng thêm một trường price_in, cái là một cái xử lí đầu vào để xóa dollar sign khỏi price. Tôi đang sử dụng
MapCompose cái là một cái xử lí tích hợp cái lấy một hay một vài hàm sẽ được thực thi tuần tự. Bạn có thể gắn
nhiều hàm như bạn thích. Thông lệ là thêm _in hay _out vào tên của trường của Item để thêm một cái xử lí đầu
vào hay đầu ra vào nó.
Có nhiều hơn cái xử lí, bạn có thể học nhiều hơn về cái này trong tài liệu hướng dẫn.

Chia sẻ