在爬取一個(gè)網(wǎng)站時(shí)改衩,要爬取的數(shù)據(jù)通常不全是在一個(gè)頁(yè)面上驯镊,每個(gè)頁(yè)面包含一部分?jǐn)?shù)據(jù)以及到其他頁(yè)面的鏈接。比如前面講到的獲取簡(jiǎn)書文章信息橄镜,在列表頁(yè)只能獲取到文章標(biāo)題冯乘、文章URL及文章的作者名稱,如果要獲取文章的詳細(xì)內(nèi)容和文章的評(píng)論只能去到文章的詳情頁(yè)中獲取姊氓。
獲取數(shù)據(jù)的方法在前面章節(jié)中已經(jīng)講解過喷好,當(dāng)然也使用Selector獲取過文章URL,那么LinkExtractor又有什么特別之處呢棕孙?為什么說LinkExtrator非常適合整站抓刃┡颉?下面將對(duì)LinkExtrator做一個(gè)介紹肢预。
一洼哎、LinkExtractor基本使用
以獲取簡(jiǎn)書首頁(yè)的文章信息為例沼本,我們使用LinkExtractor提取網(wǎng)站上的鏈接锭沟,如圖22-1所示,提取的是class=note-list
下的所有<li>
中的鏈接辫红。
代碼如下:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import scrapy
from scrapy.linkextractor import LinkExtractor
class Jianshu(scrapy.Spider):
name = "jianshu_spider"
allowed_domains = ["jianshu.com"]
def __init__(self, *args, **kwargs):
super(Jianshu, self).__init__(*args, **kwargs)
self.start_urls = ['http://www.reibang.com/']
def parse(self, response):
link = LinkExtractor(restrict_xpaths='//ul[@class="note-list"]/li')
links = link.extract_links(response)
if links:
for link_one in links:
print (link_one)
1)先使用from scrapy.linkextractor import LinkExtractor
導(dǎo)入LinkExtractor
贴妻。
2)創(chuàng)建一個(gè)LinkExtractor對(duì)象蝙斜,使用構(gòu)造器參數(shù)描述提取規(guī)則,這里是使用XPaths選擇器表達(dá)式給restrict_xpaths傳遞參數(shù)底循。
3)調(diào)用LinkExtractor對(duì)象的extract_links方法傳入一個(gè)Response對(duì)象槐瑞,該方法依據(jù)創(chuàng)建對(duì)象描述的提取規(guī)則在Response對(duì)象所包含的頁(yè)面中提取鏈接阁苞,并返回一個(gè)列表,列表中每個(gè)元素都是一個(gè)Link對(duì)象悼沿,即提取到的一個(gè)鏈接骚灸。
執(zhí)行上面的代碼,得到如下結(jié)果:
Link(url='http://www.reibang.com/p/29621e57077f', text='\n \n ', fragment='', nofollow=False)
Link(url='http://www.reibang.com/u/bfb1aa483a03', text='\n \n', fragment='', nofollow=False)
Link(url='http://www.reibang.com/p/737d34bf3e55', text='\n \n', fragment='', nofollow=False)
Link(url='http://www.reibang.com/p/29621e57077f#comments', text='\n 338\n', fragment='', nofollow=False)
Link(url='http://www.reibang.com/p/c9185e45c4e2', text='\n \n ', fragment='', nofollow=False)
Link(url='http://www.reibang.com/u/cbd1e1bd402e', text='\n \n', fragment='', nofollow=False)
Link(url='http://www.reibang.com/p/d1d89ed69098', text='\n \n', fragment='', nofollow=False)
Link(url='http://www.reibang.com/p/c9185e45c4e2#comments', text='\n 80\n', fragment='', nofollow=False)
...
...
Link(url='http://www.reibang.com/p/1b638533689f', text='\n \n ', fragment='', nofollow=False)
Link(url='http://www.reibang.com/u/5428ad454a2c', text='\n \n', fragment='', nofollow=False)
Link(url='http://www.reibang.com/p/1b638533689f#comments', text='\n 31\n', fragment='', nofollow=False)
Link(url='http://www.reibang.com/p/9f18c99fb70c', text='\n \n ', fragment='', nofollow=False)
Link(url='http://www.reibang.com/u/a6c211083de3', text='\n \n', fragment='', nofollow=False)
Link(url='http://www.reibang.com/p/9f18c99fb70c#comments', text='\n 39\n', fragment='', nofollow=False)
Link(url='http://www.reibang.com/p/fdc53c576324', text='\n \n ', fragment='', nofollow=False)
Link(url='http://www.reibang.com/u/2b3ad4f2a058', text='\n \n', fragment='', nofollow=False)
Link(url='http://www.reibang.com/p/fdc53c576324#comments', text='\n 33\n', fragment='', nofollow=False)
我們發(fā)現(xiàn)每個(gè)Link有一個(gè)url,可以通過link.url
獲取鏈接信息非驮,如下代碼雏赦,把print link
修改為print link.url
:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import scrapy
from scrapy.linkextractor import LinkExtractor
class Jianshu(scrapy.Spider):
name = "jianshu_spider"
allowed_domains = ["jianshu.com"]
def __init__(self, *args, **kwargs):
super(Jianshu, self).__init__(*args, **kwargs)
self.start_urls = ['http://www.reibang.com/']
def parse(self, response):
link = LinkExtractor(restrict_xpaths='//ul[@class="note-list"]/li')
links = link.extract_links(response)
if links:
for link_one in links:
print link_one.url
運(yùn)行之后得到的結(jié)果:
http://www.reibang.com/p/ee7e0647fb56
http://www.reibang.com/u/a7f876850fa6
http://www.reibang.com/p/d1d89ed69098
http://www.reibang.com/p/ee7e0647fb56#comments
...
...
http://www.reibang.com/p/2b55d55d2100
http://www.reibang.com/u/08529139a77b
http://www.reibang.com/p/2b55d55d2100#comments
以上就是LinkExtractor的基本使用,接下來繼續(xù)介紹LinkExtractor更多的提取參數(shù)方法填大。
二、更多的提取參數(shù)方法
- allow:接收一個(gè)正則表達(dá)式或一個(gè)正則表達(dá)式列表圈浇,提取絕對(duì)url于正則表達(dá)式匹配的鏈接例获,如果該參數(shù)為空,默認(rèn)全部提取蠕搜。
def parse(self, response):
pattern = '/gsschool/.+\.shtml'
link = LinkExtractor(allow=pattern)
links = link.extract_links(response)
- deny:接收一個(gè)正則表達(dá)式或一個(gè)正則表達(dá)式列表收壕,與allow相反,排除絕對(duì)url于正則表達(dá)式匹配的鏈接虫埂,換句話說圃验,就是凡是跟正則表達(dá)式能匹配上的全部不提取。
def parse(self, response):
pattern = '/gsschool/.+\.shtml'
link = LinkExtractor(deny=pattern)
links = link.extract_links(response)
- allow_domains:接收一個(gè)域名或一個(gè)域名列表斧散,提取到指定域的鏈接摊聋。
def parse(self, response):
domain = ['gaosivip.com','gaosiedu.com']
link = LinkExtractor(allow_domains=domain)
links = link.extract_links(response)
- deny_domains:和allow_doains相反,拒絕一個(gè)域名或一個(gè)域名列表箍镜,提取除被deny掉的所有匹配url煎源。
def parse(self, response):
domain = ['gaosivip.com','gaosiedu.com']
link = LinkExtractor(deny_domains=domain)
links = link.extract_links(response)
- restrict_xpaths:上面的例子使用的就是這種方式,接收一個(gè)xpath表達(dá)式或一個(gè)xpath表達(dá)式列表脚草,提取xpath表達(dá)式選中區(qū)域下的鏈接原献。
- restrict_css:和restrict_xpaths使用一樣埂淮,只是使用規(guī)則不一樣倔撞。
def parse(self, response):
link = LinkExtractor(restrict_css='ul.note-list > li')
links = link.extract_links(response)
- tags:接收一個(gè)標(biāo)簽(字符串)或一個(gè)標(biāo)簽列表慕趴,提取指定標(biāo)簽內(nèi)的鏈接。
- attrs:接收一個(gè)屬性(字符串)或者一個(gè)屬性列表冕房,提取指定的屬性內(nèi)的鏈接耙册。
def parse(self, response):
link = LinkExtractor(tags='a',attrs='href')
links = link.extract_links(response)