Thứ tư, 20/03/2019 | 00:00 GMT+7

Cách thu thập thông tin một trang web với Scrapy và Python 3

Gỡ bỏ trang web, thường được gọi là thu thập dữ liệu web hoặc thêu trang web, hoặc "lập trình duyệt qua một tập hợp các trang web và extract dữ liệu," là một công cụ mạnh mẽ để làm việc với dữ liệu trên web.

Với công cụ quét web, bạn có thể khai thác dữ liệu về một bộ sản phẩm, lấy một repodata văn bản hoặc dữ liệu định lượng lớn để sử dụng, lấy dữ liệu từ một trang web không có API chính thức hoặc chỉ thỏa mãn trí tò mò cá nhân của bạn .

Trong hướng dẫn này, bạn sẽ tìm hiểu về các nguyên tắc cơ bản của quy trình cạo và thêu khi bạn khám phá một tập dữ liệu vui nhộn. Ta sẽ sử dụng BrickSet , một trang web do cộng đồng điều hành có chứa thông tin về các bộ LEGO. Đến cuối hướng dẫn này, bạn sẽ có một trình duyệt web Python đầy đủ chức năng để lướt qua một loạt trang trên Brickset và extract dữ liệu về các bộ LEGO từ mỗi trang, hiển thị dữ liệu ra màn hình của bạn.

Máy quét sẽ dễ dàng mở rộng để bạn có thể mày mò và sử dụng nó làm nền tảng cho các dự án của bạn để thu thập dữ liệu từ web.

Yêu cầu

Để hoàn thành hướng dẫn này, bạn cần môi trường phát triển local cho Python 3. Bạn có thể làm theo Cách cài đặt và cài đặt môi trường lập trình local cho Python 3 để cấu hình mọi thứ bạn cần.

Bước 1 - Tạo Scraper cơ bản

Scraping là một quá trình gồm hai bước:

  1. Bạn tìm và tải các trang web một cách có hệ thống.
  2. Bạn lấy các trang web đó và extract thông tin từ chúng.

Cả hai bước đó đều có thể được thực hiện theo một số cách trong nhiều ngôn ngữ.

Bạn có thể tạo một trình quét từ đầu bằng cách sử dụng các module hoặc thư viện được cung cấp bởi ngôn ngữ lập trình của bạn, nhưng sau đó bạn phải đối mặt với một số vấn đề tiềm ẩn khi trình quét của bạn ngày càng phức tạp hơn. Ví dụ: bạn cần xử lý đồng thời để có thể thu thập thông tin nhiều trang cùng một lúc. Có thể bạn cần tìm ra cách chuyển đổi dữ liệu đã cóp nhặt của bạn thành các định dạng khác nhau như CSV, XML hoặc JSON. Và đôi khi bạn sẽ phải đối phó với các trang web yêu cầu các cài đặt và kiểu truy cập cụ thể.

Bạn sẽ gặp may mắn hơn nếu bạn xây dựng trình quét của bạn trên đầu một thư viện hiện có để xử lý những vấn đề đó cho bạn. Đối với hướng dẫn này, ta sẽ sử dụng Python và Scrapy để xây dựng bộ quét của ta .

Scrapy là một trong những thư viện cạo Python phổ biến và mạnh mẽ nhất; nó sử dụng cách tiếp cận “bao gồm pin” để cạo, nghĩa là nó xử lý nhiều chức năng phổ biến mà tất cả thợ cạo cần để các nhà phát triển không phải phát minh lại bánh xe mỗi lần. Nó làm cho việc cạo trở thành một quá trình nhanh chóng và thú vị!

Scrapy, giống như hầu hết các gói Python, nằm trên PyPI ( còn gọi là pip ). PyPI, Index gói Python, là một repository thuộc sở hữu cộng đồng của tất cả phần mềm Python đã xuất bản.

Nếu bạn có cài đặt Python giống như cài đặt được nêu trong yêu cầu cho hướng dẫn này, bạn đã cài đặt pip trên máy của bạn , vì vậy bạn có thể cài đặt Scrapy bằng lệnh sau:

  • pip install scrapy

Nếu bạn gặp sự cố nào với quá trình cài đặt hoặc bạn muốn cài đặt Scrapy mà không sử dụng pip , hãy xem tài liệu cài đặt chính thức .

Với Scrapy được cài đặt, hãy tạo một folder mới cho dự án của ta . Bạn có thể làm điều này trong terminal bằng lệnh:

  • mkdir brickset-scraper

Bây giờ, chuyển vào folder mới bạn vừa tạo:

  • cd brickset-scraper

Sau đó, tạo một file Python mới cho trình scraper.py của ta có tên là scraper.py . Ta sẽ đặt tất cả mã của ta trong file này cho hướng dẫn này. Bạn có thể tạo file này trong terminal bằng lệnh touch , như sau:

  • touch scraper.py

Hoặc bạn có thể tạo file bằng editor văn bản hoặc trình quản lý file đồ họa của bạn .

Ta sẽ bắt đầu bằng cách tạo một chiếc cạp rất cơ bản sử dụng Scrapy làm nền tảng. Để làm điều đó, ta sẽ tạo một lớp Python phân lớp con scrapy.Spider , một lớp nhện cơ bản do Scrapy cung cấp. Lớp này sẽ có hai thuộc tính bắt buộc:

  • name - chỉ là tên cho con nhện.
  • start_urls - danh sách các URL mà bạn bắt đầu thu thập thông tin. Ta sẽ bắt đầu với một URL.

Mở file scrapy.py trong editor của bạn và thêm mã này để tạo nhện cơ bản:

scraper.py
import scrapy   class BrickSetSpider(scrapy.Spider):     name = "brickset_spider"     start_urls = ['http://brickset.com/sets/year-2016'] 

Hãy chia nhỏ điều này theo từng dòng:

Đầu tiên, ta nhập scrapy để ta có thể sử dụng các lớp mà gói cung cấp.

Tiếp theo, ta lấy lớp Spider do Scrapy cung cấp và tạo một lớp con từ nó có tên là BrickSetSpider . Hãy coi một lớp con là một dạng chuyên biệt hơn của lớp cha của nó. Lớp con Spider có các phương thức và hành vi xác định cách theo dõi URL và extract dữ liệu từ các trang mà nó tìm thấy, nhưng nó không biết phải tìm ở đâu hoặc tìm dữ liệu nào. Bằng cách phân lớp nó, ta có thể cung cấp cho nó thông tin đó.

Sau đó, ta đặt tên cho con nhện là brickset_spider .

Cuối cùng, ta cung cấp cho trình duyệt của ta một URL duy nhất để bắt đầu từ: http://brickset.com/sets/year-2016 . Nếu bạn mở URL đó trong trình duyệt của bạn , URL sẽ đưa bạn đến trang kết quả tìm kiếm, hiển thị trang đầu tiên trong số nhiều trang có chứa các bộ LEGO.

Bây giờ ta hãy kiểm tra cạp. Bạn thường chạy các file Python bằng cách chạy một lệnh như python path/to/file.py Tuy nhiên, Scrapy đi kèm với giao diện dòng lệnh riêng để hợp lý hóa quá trình khởi động máy quét. Khởi động máy cạp của bạn bằng lệnh sau:

  • scrapy runspider scraper.py

Bạn sẽ thấy thông tin như thế này:

Output
2016-09-22 23:37:45 [scrapy] INFO: Scrapy 1.1.2 started (bot: scrapybot) 2016-09-22 23:37:45 [scrapy] INFO: Overridden settings: {} 2016-09-22 23:37:45 [scrapy] INFO: Enabled extensions: ['scrapy.extensions.logstats.LogStats', 'scrapy.extensions.telnet.TelnetConsole', 'scrapy.extensions.corestats.CoreStats'] 2016-09-22 23:37:45 [scrapy] INFO: Enabled downloader middlewares: ['scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware', ... 'scrapy.downloadermiddlewares.stats.DownloaderStats'] 2016-09-22 23:37:45 [scrapy] INFO: Enabled spider middlewares: ['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware', ... 'scrapy.spidermiddlewares.depth.DepthMiddleware'] 2016-09-22 23:37:45 [scrapy] INFO: Enabled item pipelines: [] 2016-09-22 23:37:45 [scrapy] INFO: Spider opened 2016-09-22 23:37:45 [scrapy] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) 2016-09-22 23:37:45 [scrapy] DEBUG: Telnet console listening on 127.0.0.1:6023 2016-09-22 23:37:47 [scrapy] DEBUG: Crawled (200) <GET http://brickset.com/sets/year-2016> (referer: None) 2016-09-22 23:37:47 [scrapy] INFO: Closing spider (finished) 2016-09-22 23:37:47 [scrapy] INFO: Dumping Scrapy stats: {'downloader/request_bytes': 224, 'downloader/request_count': 1, ... 'scheduler/enqueued/memory': 1, 'start_time': datetime.datetime(2016, 9, 23, 6, 37, 45, 995167)} 2016-09-22 23:37:47 [scrapy] INFO: Spider closed (finished)

Đó là rất nhiều sản lượng, vì vậy hãy chia nhỏ nó.

  • Trình quét đã khởi tạo và tải các thành phần và tiện ích bổ sung cần thiết để xử lý việc đọc dữ liệu từ URL.
  • Nó sử dụng URL mà ta đã cung cấp trong danh sách start_urls và lấy HTML, giống như trình duyệt web sẽ làm.
  • Nó đã chuyển HTML đó sang phương thức parse pháp, phương thức này không thực hiện bất cứ điều gì theo mặc định. Vì ta chưa bao giờ viết phương thức parse pháp của riêng mình nên con nhện chỉ kết thúc mà không cần thực hiện bất kỳ công việc nào.

Bây giờ ta hãy lấy một số dữ liệu từ trang.

Bước 2 - Extract dữ liệu từ một trang

Ta đã tạo ra một chương trình rất cơ bản để kéo một trang xuống, nhưng nó chưa thực hiện bất kỳ thao tác cạo hoặc thêu nào. Hãy cung cấp cho nó một số dữ liệu để extract .

Nếu bạn nhìn vào trang ta muốn quét , bạn sẽ thấy nó có cấu trúc như sau:

  • Có một tiêu đề xuất hiện trên mọi trang.
  • Có một số dữ liệu tìm kiếm cấp cao nhất, bao gồm số lượng kết quả phù hợp, những gì ta đang tìm kiếm và đường dẫn cho trang web.
  • Sau đó, có các bộ tự, được hiển thị trong những gì trông giống như một bảng hoặc danh sách có thứ tự. Mỗi bộ có một định dạng tương tự.

Khi viết một bản quét, bạn nên xem nguồn của file HTML và tự làm quen với cấu trúc. Vì vậy, đây là nó, với một số thứ đã bị loại bỏ để dễ đọc:

brickset.com/sets/year-2016
<body> <section class="setlist"> <article class='set'> <a href="https://images.brickset.com/sets/large/10251-1.jpg?201510121127" class="highslide plain mainimg" onclick="return hs.expand(this)"><img src="https://images.brickset.com/sets/small/10251-1.jpg?201510121127" title="10251-1: Brick Bank" onError="this.src='/assets/images/spacer.png'" /></a> <div class="highslide-caption"> <h1>Brick Bank</h1><div class='tags floatleft'><a href='/sets/10251-1/Brick- Bank'>10251-1</a> <a href='/sets/theme-Creator-Expert'>Creator Expert</a> <a class='subtheme' href='/sets/theme-Creator-Expert/subtheme-Modular- Buildings'>Modular Buildings</a> <a class='year' href='/sets/theme-Creator- Expert/year-2016'>2016</a> </div><div class='floatright'>&copy;2016 LEGO Group</div> <div class="pn"> <a href="#" onclick="return hs.previous(this)" title="Previous (left arrow key)">&#171; Previous</a> <a href="#" onclick="return hs.next(this)" title="Next (right arrow key)">Next &#187;</a> </div> </div> ... </article> </section> </body>

Quét trang này là một quá trình gồm hai bước:

  1. Đầu tiên, lấy từng bộ LEGO bằng cách tìm kiếm các phần của trang có dữ liệu mà ta muốn.
  2. Sau đó, đối với mỗi tập hợp, lấy dữ liệu ta muốn từ nó bằng cách kéo dữ liệu ra khỏi các thẻ HTML.

scrapy lấy dữ liệu dựa trên bộ chọn mà bạn cung cấp. Bộ chọn là các mẫu mà ta có thể sử dụng để tìm một hoặc nhiều phần tử trên một trang để sau đó ta có thể làm việc với dữ liệu trong phần tử đó. scrapy hỗ trợ bộ chọn CSS hoặc bộ chọn XPath .

Hiện tại, ta sẽ sử dụng bộ chọn CSS vì CSS là tùy chọn dễ dàng hơn và hoàn toàn phù hợp để tìm tất cả các bộ trên trang. Nếu bạn nhìn vào HTML của trang, bạn sẽ thấy rằng mỗi tập hợp được chỉ định với set lớp. Vì ta đang tìm kiếm một lớp, ta sẽ sử dụng .set cho bộ chọn CSS của ta . Tất cả những gì ta phải làm là chuyển bộ chọn đó vào đối tượng response , như sau:

scraper.py
class BrickSetSpider(scrapy.Spider):     name = "brickset_spider"     start_urls = ['http://brickset.com/sets/year-2016']      def parse(self, response):         SET_SELECTOR = '.set'         for brickset in response.css(SET_SELECTOR):             pass 

Mã này lấy tất cả các tập hợp trên trang và lặp lại chúng để extract dữ liệu. Bây giờ ta hãy extract dữ liệu từ các tập hợp đó để ta có thể hiển thị nó.

Một cái nhìn khác về nguồn của trang mà ta đang phân tích cú pháp cho ta biết rằng tên của mỗi group được lưu trữ trong thẻ h1 cho mỗi group :

brickset.com/sets/year-2016
<h1>Brick Bank</h1><div class='tags floatleft'><a href='/sets/10251-1/Brick-Bank'>10251-1</a>

Các brickset đối tượng ta đang Looping trên có riêng của bạn css phương pháp, vì vậy ta có thể vượt qua trong một selector để xác định vị trí phần tử con. Sửa đổi mã của bạn như sau để tìm tên của tập hợp và hiển thị nó:

scraper.py
class BrickSetSpider(scrapy.Spider):     name = "brickset_spider"     start_urls = ['http://brickset.com/sets/year-2016']      def parse(self, response):         SET_SELECTOR = '.set'         for brickset in response.css(SET_SELECTOR):              NAME_SELECTOR = 'h1 ::text'             yield {                 'name': brickset.css(NAME_SELECTOR).extract_first(),             } 

Lưu ý : Dấu phẩy ở cuối sau extract_first() không phải là lỗi đánh máy. Ta sẽ sớm bổ sung thêm vào phần này, vì vậy ta đã để dấu phẩy ở đó để việc thêm vào phần này sau này dễ dàng hơn.

Bạn sẽ nhận thấy hai điều đang xảy ra trong mã này:

  • Ta nối ::text vào bộ chọn của ta cho tên. Đó là một CSS pseudo-selector rằng fetches các bên trong nội dung của a thẻ chứ không phải thẻ chính nó.
  • Ta gọi extract_first() trên đối tượng được trả về bởi brickset.css(NAME_SELECTOR) bởi vì ta chỉ muốn phần tử đầu tiên trùng với bộ chọn. Điều này cung cấp cho ta một chuỗi , thay vì một danh sách các phần tử.

Lưu file và chạy lại trình quét:

  • scrapy runspider scraper.py

Lần này, bạn sẽ thấy tên của các bộ xuất hiện trong kết quả :

Output
... [scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016> {'name': 'Brick Bank'} [scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016> {'name': 'Volkswagen Beetle'} [scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016> {'name': 'Big Ben'} [scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016> {'name': 'Winter Holiday Train'} ...

Hãy tiếp tục mở rộng về vấn đề này bằng cách thêm selectors mới cho hình ảnh, từng mảnh, và số liệu thu nhỏ, hoặc minifigs đi kèm với một bộ.

Hãy xem xét HTML để biết một tập hợp cụ thể:

brickset.com/sets/year-2016
<article class="set"> <a class="highslide plain mainimg" href="http://images.brickset.com/sets/images/10251-1.jpg?201510121127" onclick="return hs.expand(this)"> <img src="http://images.brickset.com/sets/small/10251-1.jpg?201510121127" title="10251-1: Brick Bank"></a> ... <div class="meta"> <h1><a href="/sets/10251-1/Brick-Bank"><span>10251:</span> Brick Bank</a> </h1> ... <div class="col"> <dl> <dt>Pieces</dt> <dd><a class="plain" href="/inventories/10251-1">2380</a></dd> <dt>Minifigs</dt> <dd><a class="plain" href="/minifigs/inset-10251-1">5</a></dd> ... </dl> </div> ... </div> </article>

Ta có thể thấy một số điều bằng cách kiểm tra mã này:

  • Những hình ảnh cho các cài đặt được lưu trữ trong src thuộc tính của một img tag bên trong một a thẻ vào lúc bắt đầu của bộ này. Ta có thể sử dụng một bộ chọn CSS khác để tìm nạp giá trị này giống như ta đã làm khi ta lấy tên của mỗi tập hợp.
  • Lấy số lượng mảnh phức tạp hơn một chút. Có một thẻ dt chứa các Pieces văn bản và sau đó là thẻ dd theo sau nó chứa số lượng mảnh thực tế. Ta sẽ sử dụng XPath , một ngôn ngữ truy vấn để duyệt qua XML, để nắm bắt điều này, bởi vì nó quá phức tạp để được biểu diễn bằng các bộ chọn CSS.
  • Lấy số lượng minifigs trong một bộ tương tự như lấy số lượng mảnh. Có một thẻ dt chứa văn bản Minifigs , theo sau là một thẻ dd ngay sau đó với số.

Vì vậy, hãy sửa đổi trình quét để có thông tin mới này:

scraper.py
class BrickSetSpider(scrapy.Spider):     name = 'brick_spider'     start_urls = ['http://brickset.com/sets/year-2016']      def parse(self, response):         SET_SELECTOR = '.set'         for brickset in response.css(SET_SELECTOR):              NAME_SELECTOR = 'h1 ::text'             PIECES_SELECTOR = './/dl[dt/text() = "Pieces"]/dd/a/text()'             MINIFIGS_SELECTOR = './/dl[dt/text() = "Minifigs"]/dd[2]/a/text()'             IMAGE_SELECTOR = 'img ::attr(src)'             yield {                 'name': brickset.css(NAME_SELECTOR).extract_first(),                 'pieces': brickset.xpath(PIECES_SELECTOR).extract_first(),                 'minifigs': brickset.xpath(MINIFIGS_SELECTOR).extract_first(),                 'image': brickset.css(IMAGE_SELECTOR).extract_first(),             } 

Lưu các thay đổi và chạy lại trình quét:

  • scrapy runspider scraper.py

Đến đây bạn sẽ thấy dữ liệu mới đó trong kết quả của chương trình:

Output
2016-09-22 23:52:37 [scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016> {'minifigs': '5', 'pieces': '2380', 'name': 'Brick Bank', 'image': 'http://images.brickset.com/sets/small/10251-1.jpg?201510121127'} 2016-09-22 23:52:37 [scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016> {'minifigs': None, 'pieces': '1167', 'name': 'Volkswagen Beetle', 'image': 'http://images.brickset.com/sets/small/10252-1.jpg?201606140214'} 2016-09-22 23:52:37 [scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016> {'minifigs': None, 'pieces': '4163', 'name': 'Big Ben', 'image': 'http://images.brickset.com/sets/small/10253-1.jpg?201605190256'} 2016-09-22 23:52:37 [scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016> {'minifigs': None, 'pieces': None, 'name': 'Winter Holiday Train', 'image': 'http://images.brickset.com/sets/small/10254-1.jpg?201608110306'} 2016-09-22 23:52:37 [scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016> {'minifigs': None, 'pieces': None, 'name': 'XL Creative Brick Box', 'image': '/assets/images/misc/blankbox.gif'} 2016-09-22 23:52:37 [scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016> {'minifigs': None, 'pieces': '583', 'name': 'Creative Building Set', 'image': 'http://images.brickset.com/sets/small/10702-1.jpg?201511230710'}

Bây giờ ta hãy biến chiếc cạp này thành một con nhện theo các liên kết.

Bước 3 - Thu thập thông tin nhiều trang

Ta đã extract thành công dữ liệu từ trang đầu tiên đó, nhưng ta không thể vượt qua nó để xem phần còn lại của kết quả. Toàn bộ điểm của spider là phát hiện và duyệt các liên kết đến các trang khác và lấy dữ liệu từ các trang đó.

Bạn sẽ nhận thấy rằng đầu và cuối mỗi trang có một carat nhỏ bên phải ( > ) liên kết đến trang kết quả tiếp theo. Đây là HTML cho điều đó:

brickset.com/sets/year-2016
<ul class="pagelength"> ... <li class="next"> <a href="http://brickset.com/sets/year-2017/page-2">&#8250;</a> </li> <li class="last"> <a href="http://brickset.com/sets/year-2016/page-32">&#187;</a> </li> </ul>

Như bạn thấy , có một thẻ li với lớp next và bên trong thẻ đó, có a thẻ có liên kết đến trang tiếp theo. Tất cả những gì ta phải làm là yêu cầu người cạo theo liên kết đó nếu nó tồn tại.

Sửa đổi mã của bạn như sau:

scraper.py
class BrickSetSpider(scrapy.Spider):     name = 'brick_spider'     start_urls = ['http://brickset.com/sets/year-2016']      def parse(self, response):         SET_SELECTOR = '.set'         for brickset in response.css(SET_SELECTOR):              NAME_SELECTOR = 'h1 ::text'             PIECES_SELECTOR = './/dl[dt/text() = "Pieces"]/dd/a/text()'             MINIFIGS_SELECTOR = './/dl[dt/text() = "Minifigs"]/dd[2]/a/text()'             IMAGE_SELECTOR = 'img ::attr(src)'             yield {                 'name': brickset.css(NAME_SELECTOR).extract_first(),                 'pieces': brickset.xpath(PIECES_SELECTOR).extract_first(),                 'minifigs': brickset.xpath(MINIFIGS_SELECTOR).extract_first(),                 'image': brickset.css(IMAGE_SELECTOR).extract_first(),             }          NEXT_PAGE_SELECTOR = '.next a ::attr(href)'         next_page = response.css(NEXT_PAGE_SELECTOR).extract_first()         if next_page:             yield scrapy.Request(                 response.urljoin(next_page),                 callback=self.parse             ) 

Đầu tiên, ta xác định một bộ chọn cho liên kết “trang tiếp theo”, extract kết quả phù hợp đầu tiên và kiểm tra xem nó có tồn tại hay không. The scrapy.Request là một giá trị mà ta trả về với nội dung “Này, hãy thu thập thông tin trang này” và callback=self.parse cho biết “khi bạn đã nhận được HTML từ trang này, hãy chuyển nó trở lại phương thức này để ta có thể phân tích cú pháp, extract dữ liệu và tìm trang tiếp theo. "

Điều này nghĩa là khi ta chuyển sang trang tiếp theo, ta sẽ tìm kiếm liên kết đến trang tiếp theo ở đó và trên trang đó, ta sẽ tìm liên kết đến trang tiếp theo, v.v., cho đến khi ta không tìm thấy một liên kết cho trang tiếp theo. Đây là phần quan trọng của việc tìm kiếm trên web: tìm và theo dõi các liên kết. Trong ví dụ này, nó rất tuyến tính; một trang có liên kết đến trang tiếp theo cho đến khi ta đến trang cuối cùng, Nhưng bạn có thể theo các liên kết đến thẻ, hoặc kết quả tìm kiếm khác, hoặc bất kỳ URL nào khác mà bạn muốn.

Bây giờ, nếu bạn lưu mã của bạn và chạy lại spider, bạn sẽ thấy rằng nó không chỉ dừng lại khi nó lặp qua trang đầu tiên của bộ. Nó tiếp tục trải qua tất cả 779 trận đấu trên 23 trang! Trong sơ đồ tổng thể của mọi thứ, đó không phải là một lượng lớn dữ liệu, nhưng bây giờ bạn biết quá trình bạn tự động tìm các trang mới để loại bỏ.

Đây là mã hoàn chỉnh của ta cho hướng dẫn này, sử dụng tô sáng dành riêng cho Python:

scraper.py
import scrapy   class BrickSetSpider(scrapy.Spider):     name = 'brick_spider'     start_urls = ['http://brickset.com/sets/year-2016']      def parse(self, response):         SET_SELECTOR = '.set'         for brickset in response.css(SET_SELECTOR):              NAME_SELECTOR = 'h1 ::text'             PIECES_SELECTOR = './/dl[dt/text() = "Pieces"]/dd/a/text()'             MINIFIGS_SELECTOR = './/dl[dt/text() = "Minifigs"]/dd[2]/a/text()'             IMAGE_SELECTOR = 'img ::attr(src)'             yield {                 'name': brickset.css(NAME_SELECTOR).extract_first(),                 'pieces': brickset.xpath(PIECES_SELECTOR).extract_first(),                 'minifigs': brickset.xpath(MINIFIGS_SELECTOR).extract_first(),                 'image': brickset.css(IMAGE_SELECTOR).extract_first(),             }          NEXT_PAGE_SELECTOR = '.next a ::attr(href)'         next_page = response.css(NEXT_PAGE_SELECTOR).extract_first()         if next_page:             yield scrapy.Request(                 response.urljoin(next_page),                 callback=self.parse             ) 

Kết luận

Trong hướng dẫn này, bạn đã xây dựng một trình thu thập dữ liệu đầy đủ chức năng để extract dữ liệu từ các trang web trong ít hơn ba mươi dòng mã. Đó là một khởi đầu tuyệt vời, nhưng có rất nhiều điều thú vị bạn có thể làm với con nhện này. Dưới đây là một số cách bạn có thể mở rộng mã bạn đã viết. Họ sẽ cung cấp cho bạn một số dữ liệu thực hành.

  1. Hiện tại, ta chỉ phân tích kết quả từ năm 2016, như bạn có thể đã đoán từ phần 2016 của http://brickset.com/sets/year-2016 - bạn sẽ thu thập kết quả từ những năm khác gì ?
  2. Có một giá bán lẻ bao gồm trên hầu hết các bộ. Làm thế nào để bạn extract dữ liệu từ ô đó? Làm thế nào bạn có được một con số thô từ nó? Gợi ý : bạn sẽ tìm thấy dữ liệu trong một dt giống như số lượng mảnh và hình nhỏ.
  3. Hầu hết các kết quả đều có các thẻ chỉ định dữ liệu ngữ nghĩa về các tập hợp hoặc ngữ cảnh của chúng. Làm cách nào để ta thu thập dữ liệu các thẻ này, với điều kiện có nhiều thẻ cho một tập hợp?

Điều đó đủ để bạn suy nghĩ và thử nghiệm. Nếu bạn cần thêm thông tin về Scrapy, hãy xem các tài liệu chính thức của Scrapy . Để biết thêm thông tin về cách làm việc với dữ liệu từ web, hãy xem hướng dẫn của ta về "Cách chỉnh sửa các trang web với Beautiful Soup và Python 3" .


Tags:

Các tin liên quan

Cách cạo các trang web với Beautiful Soup và Python 3
2019-03-20
Cách sử dụng API Web trong Python 3
2019-03-20
Tạo ứng dụng web tiến bộ (PWA) với React
2019-03-02
Tụ điện: Chạy ứng dụng web trên thiết bị di động
2019-02-27
Cách gửi thông báo đẩy web từ ứng dụng Django
2018-10-24
Cách xây dựng ứng dụng web hiện đại để quản lý thông tin khách hàng với Django và React trên Ubuntu 18.04
2018-10-22
Cách cài đặt Django Web Framework trên Ubuntu 18.04
2018-08-06
Cách sử dụng Trình quản lý cảnh báo và Trình xuất hộp đen để giám sát web server của bạn trên Ubuntu 16.04
2018-05-11
Giải pháp Deep Dive: Xây dựng một ứng dụng web khả dụng cao với khả năng xử lý và lưu trữ web bằng cách sử dụng MongoDB và Elk Stack
2018-03-15
Các bước đầu tiên của bạn với API âm thanh web
2018-01-09