爬虫课堂(二十二)|使用LinkExtractor提取链接

在爬取一个网站时,要爬取的数据通常不全是在一个页面上,每个页面包含一部分数据以及到其他页面的链接。比如前面讲到的获取简书文章信息,在列表页只能获取到文章标题、文章URL及文章的作者名称,如果要获取文章的详细内容和文章的评论只能去到文章的详情页中获取。
获取数据的方法在前面章节中已经讲解过,当然也使用Selector获取过文章URL,那么LinkExtractor又有什么特别之处呢?为什么说LinkExtrator非常适合整站抓取?下面将对LinkExtrator做一个介绍。
一、LinkExtractor基本使用
以获取简书首页的文章信息为例,我们使用LinkExtractor提取网站上的链接,如图22-1所示,提取的是class=note-list下的所有<li>中的链接。

图22-1

代码如下:

#!/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 = ['//www.greatytc.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导入LinkExtractor
2)创建一个LinkExtractor对象,使用构造器参数描述提取规则,这里是使用XPaths选择器表达式给restrict_xpaths传递参数。
3)调用LinkExtractor对象的extract_links方法传入一个Response对象,该方法依据创建对象描述的提取规则在Response对象所包含的页面中提取链接,并返回一个列表,列表中每个元素都是一个Link对象,即提取到的一个链接。

执行上面的代码,得到如下结果:

Link(url='//www.greatytc.com/p/29621e57077f', text='\n      \n    ', fragment='', nofollow=False)
Link(url='//www.greatytc.com/u/bfb1aa483a03', text='\n        \n', fragment='', nofollow=False)
Link(url='//www.greatytc.com/p/737d34bf3e55', text='\n            \n', fragment='', nofollow=False)
Link(url='//www.greatytc.com/p/29621e57077f#comments', text='\n           338\n', fragment='', nofollow=False)
Link(url='//www.greatytc.com/p/c9185e45c4e2', text='\n      \n    ', fragment='', nofollow=False)
Link(url='//www.greatytc.com/u/cbd1e1bd402e', text='\n        \n', fragment='', nofollow=False)
Link(url='//www.greatytc.com/p/d1d89ed69098', text='\n            \n', fragment='', nofollow=False)
Link(url='//www.greatytc.com/p/c9185e45c4e2#comments', text='\n           80\n', fragment='', nofollow=False)
...
...
Link(url='//www.greatytc.com/p/1b638533689f', text='\n      \n    ', fragment='', nofollow=False)
Link(url='//www.greatytc.com/u/5428ad454a2c', text='\n        \n', fragment='', nofollow=False)
Link(url='//www.greatytc.com/p/1b638533689f#comments', text='\n           31\n', fragment='', nofollow=False)
Link(url='//www.greatytc.com/p/9f18c99fb70c', text='\n      \n    ', fragment='', nofollow=False)
Link(url='//www.greatytc.com/u/a6c211083de3', text='\n        \n', fragment='', nofollow=False)
Link(url='//www.greatytc.com/p/9f18c99fb70c#comments', text='\n           39\n', fragment='', nofollow=False)
Link(url='//www.greatytc.com/p/fdc53c576324', text='\n      \n    ', fragment='', nofollow=False)
Link(url='//www.greatytc.com/u/2b3ad4f2a058', text='\n        \n', fragment='', nofollow=False)
Link(url='//www.greatytc.com/p/fdc53c576324#comments', text='\n           33\n', fragment='', nofollow=False)

我们发现每个Link有一个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 = ['//www.greatytc.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

运行之后得到的结果:

//www.greatytc.com/p/ee7e0647fb56
//www.greatytc.com/u/a7f876850fa6
//www.greatytc.com/p/d1d89ed69098
//www.greatytc.com/p/ee7e0647fb56#comments
...
...
//www.greatytc.com/p/2b55d55d2100
//www.greatytc.com/u/08529139a77b
//www.greatytc.com/p/2b55d55d2100#comments

以上就是LinkExtractor的基本使用,接下来继续介绍LinkExtractor更多的提取参数方法。
二、更多的提取参数方法

  • allow:接收一个正则表达式或一个正则表达式列表,提取绝对url于正则表达式匹配的链接,如果该参数为空,默认全部提取。
def parse(self, response):
    pattern = '/gsschool/.+\.shtml'
    link = LinkExtractor(allow=pattern)
    links = link.extract_links(response)
  • deny:接收一个正则表达式或一个正则表达式列表,与allow相反,排除绝对url于正则表达式匹配的链接,换句话说,就是凡是跟正则表达式能匹配上的全部不提取。
def parse(self, response):
   pattern = '/gsschool/.+\.shtml'
   link = LinkExtractor(deny=pattern)
   links = link.extract_links(response)
  • allow_domains:接收一个域名或一个域名列表,提取到指定域的链接。
def parse(self, response):
    domain = ['gaosivip.com','gaosiedu.com']
    link = LinkExtractor(allow_domains=domain)
    links = link.extract_links(response)
  • deny_domains:和allow_doains相反,拒绝一个域名或一个域名列表,提取除被deny掉的所有匹配url。
def parse(self, response):
    domain = ['gaosivip.com','gaosiedu.com']
    link = LinkExtractor(deny_domains=domain)
    links = link.extract_links(response)
  • restrict_xpaths:上面的例子使用的就是这种方式,接收一个xpath表达式或一个xpath表达式列表,提取xpath表达式选中区域下的链接。
  • restrict_css:和restrict_xpaths使用一样,只是使用规则不一样。
def parse(self, response):
    link = LinkExtractor(restrict_css='ul.note-list > li')
    links = link.extract_links(response)
  • tags:接收一个标签(字符串)或一个标签列表,提取指定标签内的链接。
  • attrs:接收一个属性(字符串)或者一个属性列表,提取指定的属性内的链接。
def parse(self, response):
    link = LinkExtractor(tags='a',attrs='href')
    links = link.extract_links(response)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,376评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,126评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,966评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,432评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,519评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,792评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,933评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,701评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,143评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,488评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,626评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,292评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,896评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,324评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,494评论 2 348

推荐阅读更多精彩内容