如何用Python Scrapy跟蹤連結

語言: CN / TW / HK

How To Follow Links With Python Scrapy

在使用Python Scrapy進行資料提取時跟蹤連結是非常直接的。我們需要做的第一件事是找到頁面上的導航連結。很多時候,這是一個包含文字 "下一步 "的連結,但它不一定是。然後,我們需要構建一個XPath或CSS選擇器查詢,以獲得我們需要的錨元素的href屬性中包含的值。一旦完成,我們就可以使用Scrapy的response.follow()方法來自動導航到網站的其他頁面。


查詢下一個按鈕

這個例子使用的是books.tscrape.com,我們可以看到,在主頁上有一個 "下一步 "按鈕,可以連結到下一個頁面。這一直持續到所有50個頁面被顯示出來。

next button for responsefollow scrapy

在Scrapy Shell中的測試顯示,response.css('.next a').attrib['href']給了我們需要的URL值。


實現 response.follow()

現在,為了讓我們的Spider能夠導航到下一頁,我們可以構建下面的程式碼。第一步是使用response.css('.next a').attrib['href']選擇器從頁面中提取要訪問的URL,並將該結果儲存在next_page變數中。

一旦完成,我們使用if語句來確保next_page是一個有效的URL。如果它是有效的,那麼我們就會產生一個對response.follow()的呼叫,像這樣。

python response.follow(next_page, callback=self.parse)

請注意,在這個Spider類中,有一個回撥函式是指向parse()方法的。這告訴Scrapy繼續搜刮當前頁面,當你完成後--點選連結訪問下一個頁面,然後再次執行parse()方法來搜刮新的頁面。這個過程一直持續到不再有一個從當前頁面提取的有效URL為止。換句話說,最後一個頁面不會有一個文字為 "Next "的錨標籤指向一個新的頁面。此時,response.css('.next a').attrib['href']實際上將是空的,或者說是無,因此response.follow()方法將不會被呼叫,Spider將停止。

```python import scrapy

class BooksSpider(scrapy.Spider): name = 'books' allowed_domains = ['books.toscrape.com'] start_urls = ['http://books.toscrape.com/']

def parse(self, response):
    for book in response.xpath('//article'):
        yield {
            'booktitle': book.xpath('.//a/text()').get(),
            'bookrating': book.xpath('.//p').attrib['class'],
            'bookprice': book.xpath('.//div[2]/p/text()').get(),
            'bookavailability': book.xpath('.//div[2]/p[2]/i/following-sibling::text()').get().strip()
        }

    next_page = response.css('.next a').attrib['href']
    if next_page is not None:
        yield response.follow(next_page, callback=self.parse)

```


執行Spider

對我們的Scrapy專案所做的這個小改動,現在已經有了一個遞迴跟蹤連結的方法,直到所有的頁面都被抓取。我們可以執行蜘蛛,並將其輸出到一個JSON檔案。

bookstoscrape $scrapy crawl books -o books.json

在蜘蛛的輸出中,我們現在可以看到一些令人印象深刻的統計數字。蜘蛛顯示,現在有1000個專案在大約12秒內被搜刮完畢。這就是整個網站,而我們只添加了幾行程式碼

``` {'downloader/request_bytes': 15059, 'downloader/request_count': 51, 'downloader/request_method_count/GET': 51, 'downloader/response_bytes': 291875, 'downloader/response_count': 51, 'downloader/response_status_count/200': 50, 'downloader/response_status_count/404': 1, 'elapsed_time_seconds': 12.535962, 'finish_reason': 'finished', 'item_scraped_count': 1000, 'log_count/DEBUG': 1051, 'log_count/ERROR': 1, 'log_count/INFO': 11, 'request_depth_max': 49, 'response_received_count': 51, 'robotstxt/request_count': 1, 'robotstxt/response_count': 1, 'robotstxt/response_status_count/404': 1, 'scheduler/dequeued': 50, 'scheduler/dequeued/memory': 50, 'scheduler/enqueued': 50, 'scheduler/enqueued/memory': 50, 'spider_exceptions/KeyError': 1, }

```

我們可以檢查Scrapy專案中生成的books.json檔案,當然,它現在有1000個物件,每個物件都有一個標題、評級、價格和可用性屬性。令人印象深刻!

連結擴充套件器

Scrapy還提供了所謂的連結提取器。這是一個可以從響應中自動提取連結的物件。它們通常用於Crawl Spiders,儘管它們也可以用於普通的Spiders,比如本文介紹的那個。語法不同,但可以達到同樣的效果。上面的連結跟蹤程式碼是用連結提取器改寫的,結果是一樣的。

``` import scrapy from scrapy.linkextractors import LinkExtractor

class BooksSpider(scrapy.Spider): name = 'books' allowed_domains = ['books.toscrape.com'] start_urls = ['http://books.toscrape.com/']

def parse(self, response):
    for book in response.xpath('//article'):
        yield {
            'booktitle': book.xpath('.//a/text()').get(),
            'bookrating': book.xpath('.//p').attrib['class'],
            'bookprice': book.xpath('.//div[2]/p/text()').get(),
            'bookavailability': book.xpath('.//div[2]/p[2]/i/following-sibling::text()').get().strip()
        }

    next_page = LinkExtractor(restrict_css='.next a').extract_links(response)[0]
    if next_page.url is not None:
        yield response.follow(next_page, callback=self.parse)

```

如何限制被跟蹤連結的數量

當這種型別的遞迴程式執行時,它將一直執行下去,直到滿足停止條件。你可能不希望在一個非常大的網站上出現這種情況。在這種情況下,你需要一種方法來阻止蜘蛛抓取新的連結,有幾種方法可以做到這一點。

CLOSESPIDER_PAGECOUNT
一種方法是在settings.py中新增一個配置值,將CLOSESPIDER_PAGECOUNT設定為25。

```python

Scrapy settings for bookstoscrape project

For simplicity, this file contains only settings considered important or

commonly used. You can find more settings consulting the documentation:

https://docs.scrapy.org/en/latest/topics/settings.html

https://docs.scrapy.org/en/latest/topics/downloader-middleware.html

https://docs.scrapy.org/en/latest/topics/spider-middleware.html

BOT_NAME = 'bookstoscrape'

SPIDER_MODULES = ['bookstoscrape.spiders'] NEWSPIDER_MODULE = 'bookstoscrape.spiders'

CLOSESPIDER_PAGECOUNT = 25 ```

現在,當我們執行蜘蛛時,它在搜刮了25個頁面後就會停止執行。你也可以通過設定要搜刮的專案數量來做同樣的事情。例如,如果你設定CLOSESPIDER_ITEMCOUNT = 100,那麼在檢索完100個專案後,爬行會自動停止。在處理大型資料集時,請記住settings.py檔案中的這兩個配置值。

如何用Python Scrapy跟蹤連結摘要

在Python Scrapy中還有幾種跟蹤連結的方法,但response.follow()方法可能是最容易使用的,特別是在第一次使用Scrapy時。跟蹤連結的其他選擇是urljoin()方法和LinkExtractor物件。