讓我們討論一下,你希望獲得整個(gè)網(wǎng)站的語(yǔ)錄而不是僅僅的爬取開(kāi)始http://quotes.toscrape.com,給的兩個(gè)網(wǎng)頁(yè)。
現(xiàn)在你理解了如何從網(wǎng)頁(yè)中提取數(shù)據(jù),讓我們了解如何從開(kāi)始的鏈接來(lái)追蹤后續(xù)鏈接。
首先是從網(wǎng)頁(yè)中提取我們想要追蹤的鏈接。檢查測(cè)試我們的網(wǎng)頁(yè),我們可以看到下一頁(yè)的鏈接,以HTML標(biāo)記:
<ul class = "pager">
<li class = "next">
<a href = "/page/2/">Next <span aria-hidden = "true">→</span></a>
</li>
</ul>
我們可以嘗試在shell中提取它:
>>>response.css('li.next a').extract_first()
'<a href = "/page/2/">Next <span aria-hidden = "true">→</span></a>'
我們提取了標(biāo)簽元素,但是我們想要其中屬性的href值。為此,Scarpy提供CSS的擴(kuò)展應(yīng)用讓我們提取屬性中的內(nèi)容,像這樣:
>>>response.css('li.next a::attr(href)').extract_first()
'/page/2/'
現(xiàn)在修改我們的爬蟲(chóng)來(lái)遞歸下一頁(yè)的功能,從網(wǎng)頁(yè)中提取數(shù)據(jù):
import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
start_urls = [
'http://quotes.toscrape.com/page/1/',
]
def parse(self, response):
for quote in response.css('div.quote'):
yield{
'text':quote.css('span.text::text').extract_first(),
'author':quote.css('span.text:text').extract_first(),
'tags':quote.css('div.tags a.tag::text').extract(),
}
next_page = response.css('li.next a::attr(href)').extract_first()
if next_page is not None:
next_page = response.urljoin(next_page)
yield scrapy.Request(next_page, callback = self.parse)
現(xiàn)在提取數(shù)據(jù)后,parse()方法查找下一頁(yè)的鏈接,以urljoin()方法建立網(wǎng)站完整的URL,向下一頁(yè)生成新請(qǐng)求,為下一頁(yè)的鏈接提取數(shù)據(jù)注冊(cè)它本身為返回函數(shù)同時(shí)保持爬取整個(gè)網(wǎng)站。
你看到的是Scrapy追蹤鏈接的機(jī)制:當(dāng)你在返回函數(shù)中生成請(qǐng)求,Scrapy將會(huì)安排請(qǐng)求被發(fā)送和注冊(cè)返回函數(shù)被執(zhí)行,直到請(qǐng)求結(jié)束。
使用這方法,你可以搭建復(fù)雜的爬蟲(chóng)來(lái)追蹤你需要的深度,同時(shí)在你訪(fǎng)問(wèn)的網(wǎng)頁(yè)中提取數(shù)據(jù)。
在我們的例子中,它創(chuàng)建了一個(gè)循環(huán),追蹤所有網(wǎng)頁(yè)的鏈接——讓我們來(lái)爬取具有標(biāo)記頁(yè)數(shù)的博客、論壇和其他網(wǎng)站。