爬虫框架Scrapy(8)使用 LinkExtractor 提取链接

news/2024/7/19 12:37:42 标签: python, 爬虫

文章目录

    • 使用 LinkExtractor 提取链接
        • 1. 提取链接的方法
          • (1)使用Selector
          • (2)使用LinkExtractor
        • 2. LinkExtractor 提取链接的规则
          • (1)allow
          • (2)deny
          • (3)allow_domains
          • (4)deny_domains
          • (5)restrict_xpaths
          • (6)restrict_css
          • (7)tags
          • (8)attrs
          • (9)process_value

使用 LinkExtractor 提取链接

1. 提取链接的方法

在爬取一个网站时,想要爬取的数据通常分布在多个页面中,每个页面包含一部分数据以及到其他页面的链接,提取页面中数据的方法大家已经掌握,提取链接有使用 Selector 和使用 LinkExtractor 两种方法。

(1)使用Selector

因为链接也是页面中的数据,所以可以使用与提取数据相同的方法进行提取,在提取少量链接或提取规则比较简单时,使用 Selector 就足够了。例如我们在项目 toscrapy 中编写爬虫 books.py 的数据解析函数 parse() 时,就是用了 Selector 提取了下一个页面的链接,代码如下:

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

    def parse(self, response):
        ......

        # 提取链接
        next_url = response.css('ul.pager li.next a::attr(href)').extract_first()
        if next_url:
            next_url = response.urljoin(next_url)
            yield scrapy.Request(next_url, callback=self.parse)

第一种方法我们早已掌握,下面学习如何使用 LinkExtractor 提取链接。

(2)使用LinkExtractor

Scrapy 提供了一个专门用于提取链接的类 LinkExtractor,在提取大量链接或提取规则比较复杂时,使用 LinkExtractor 更加方便。

LinkExtractor 的使用非常简单,我们通过将上述代码中的 Selector 替换成 LinkExtractor 进行讲解,代码如下:

python">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):
        ...
        # 提取链接 
        le = LinkExtractor(restrict_css='ul.pager li.next') 
        links = le.extract_links(response) 
        if links:
            next_url = links[0].url 
            yield scrapy.Request(next_url, callback=self.parse)

代码解析如下:

  • Step 1:创建一个 LinkExtractor 对象,使用一个或多个构造器参数描述提取规则。这里传递给 restrict_css 参数一个 CSS 选择器表达式。它描述出下一页链接所在的区域(在 li.next 下)。
  • Step 2:调用 LinkExtractor 对象的 extract_links 方法传入一个 Response 对象,该方法依据创建对象时所描述的提取规则, 在 Response 对象所包含的页面中提取链接,最终返回一个列表,其中的每一个元素都是一个 Link 对象,即提取到的一个链接。
  • Step 3:由于页面中的下一页链接只有一个,因此用 links[0] 获取 LinkExtractor 对象,LinkExtractor 对象的 url 属性便是链接页面的绝对 url 地址(无须再调用 response.urljoin 方法),用其构造 Request 对象并提交。

2. LinkExtractor 提取链接的规则

接下来,我们来学习使用 LinkExtractor 的构造器参数描述提取链接的规则。

首先我们创建两个包含多个链接的HTML页面,作为 LinkExtractor 提取链接的示例网页:

<!-- example1.html -->
<html>
    <body>
        <div id="top">
            <p>下面是一些站内链接</p>
            <a class="internal" href="/intro/install.html">Installation guide</a>
            <a class="internal" href="/intro/tutorial.html">Tutorial</a>
            <a class="internal" href="../examples.html">Examples</a>
        </div>
        <div id="bottom">
            <p>下面是一些站外链接</p>
            <a href="http://stackoverflow.com/tags/scrapy/info">StackOverflow</a>
            <a href="https://github.com/scrapy/scrapy">Fork on Github</a>
        </div>
    </body>
</html>

<!-- example2.html -->
<html>
<head>
    <script type='text/javascript' src='/js/app1.js'/>
    <script type='text/javascript' src='/js/app2.js'/>
</head>
<body>
    <a href="/home.html">主页</a>
    <a href="javascript:goToPage('/doc.html'); return false">文档</a>
    <a href="javascript:goToPage('/example.html'); return false">案例</a>
</body>
</html>

LinkExtractor 构造器的所有参数都有默认值,如果构造对象时不传递任何参数(使用默认值),就提取页面中所有链接。例如以下代码将提取页面 example1.html 中的所有链接:

python">from scrapy.http import HtmlResponse
from scrapy.linkextractors import LinkExtractor

html1 = open('LE_Example1.html').read()
response1 = HtmlResponse(url='http://example1.com', body=html1, encoding='utf8')
le = LinkExtractor()
links = le.extract_links(response1)
print([link.url for link in links])

# 运行结果:
['http://example1.com/intro/install.html', 'http://example1.com/intro/tutorial.html', 'http://example1.com/examples.html', 'http://stackoverflow.com/tags/scrapy/info', 'https://github.com/scrapy/scrapy']

下面依次介绍 LinkExtractor 构造器的各个参数:

(1)allow

allow 接收一个正则表达式或一个正则表达式列表,提取绝对 url 与正则表达式匹配的链接,如果该参数为空(默认),就提取全部链接。

例1:提取页面 example1.html 中路径以 /intro 开始的链接:

python">from scrapy.http import HtmlResponse
from scrapy.linkextractors import LinkExtractor

html1 = open('LE_Example1.html').read()
response1 = HtmlResponse(url='http://example1.com', body=html1, encoding='utf8')
pattern = '/intro/.+\.html$'
le = LinkExtractor(allow=pattern)
links = le.extract_links(response1)
print([link.url for link in links])

# 运行结果:
['http://example1.com/intro/install.html', 'http://example1.com/intro/tutorial.html']
(2)deny

接收一个正则表达式或一个正则表达式列表,与 allow 相反,排除绝对 url 与正则表达式匹配的链接。

例2:提取页面 example1.html 中所有站外链接(即排除站内链接):

python">from scrapy.http import HtmlResponse
from scrapy.linkextractors import LinkExtractor
from urllib.parse import urlparse

html1 = open('LE_Example1.html').read()
response1 = HtmlResponse(url='http://example1.com', body=html1, encoding='utf8')
pattern = '^' + urlparse(response1.url).geturl()
le = LinkExtractor(deny=pattern)
links = le.extract_links(response1)
print([link.url for link in links])

# 运行结果:
['http://stackoverflow.com/tags/scrapy/info', 'https://github.com/scrapy/scrapy']
(3)allow_domains

接收一个域名或一个域名列表,提取到指定域的链接。

例3::提取页面 example1.html 中所有到 github.comstackoverflow.com 这两个域的链接:

python">from scrapy.http import HtmlResponse
from scrapy.linkextractors import LinkExtractor

html1 = open('LE_Example1.html').read()
response1 = HtmlResponse(url='http://example1.com', body=html1, encoding='utf8')
domains = ['github.com', 'stackoverflow.com']
le = LinkExtractor(allow_domains=domains)
links = le.extract_links(response1)
print([link.url for link in links])

# 运行结果:
['http://stackoverflow.com/tags/scrapy/info', 'https://github.com/scrapy/scrapy']
(4)deny_domains

接收一个域名或一个域名列表,与 allow_domains 相反,排除到指定域的链接。

例4:提取页面 example1.html 中除了到 github.com 域以外的链接:

python">from scrapy.http import HtmlResponse
from scrapy.linkextractors import LinkExtractor

html1 = open('LE_Example1.html').read()
response1 = HtmlResponse(url='http://example1.com', body=html1, encoding='utf8')
le = LinkExtractor(deny_domains='github.com')
links = le.extract_links(response1)
print([link.url for link in links])

# 运行结果:
['http://example1.com/intro/install.html', 'http://example1.com/intro/tutorial.html', 'http://example1.com/examples.html', 'http://stackoverflow.com/tags/scrapy/info']
(5)restrict_xpaths

接收一个 XPath 表达式或一个 XPath 表达式列表,提取 XPath 表达式选中区域下的链接。

例5:提取页面 example1.html<div id="top"> 元素下的链接:

python">from scrapy.http import HtmlResponse
from scrapy.linkextractors import LinkExtractor

html1 = open('LE_Example1.html').read()
response1 = HtmlResponse(url='http://example1.com', body=html1, encoding='utf8')
le = LinkExtractor(restrict_xpaths='//div[@id="top"]')
links = le.extract_links(response1)
print([link.url for link in links])

# 运行结果:
['http://example1.com/intro/install.html', 'http://example1.com/intro/tutorial.html', 'http://example1.com/examples.html']
(6)restrict_css

接收一个 CSS 选择器或一个 CSS 选择器列表,提取 CSS 选择器选中区域下的链接。

例6:提取页面 example1.html<div id="bottom"> 元素下 的链接:

python">from scrapy.http import HtmlResponse
from scrapy.linkextractors import LinkExtractor

html1 = open('LE_Example1.html').read()
response1 = HtmlResponse(url='http://example1.com', body=html1, encoding='utf8')
le = LinkExtractor(restrict_css='div#bottom')
links = le.extract_links(response1)
print([link.url for link in links])

# 运行结果:
['http://stackoverflow.com/tags/scrapy/info', 'https://github.com/scrapy/scrapy']
(7)tags

接收一个标签(字符串)或一个标签列表,提取指定标签内的链接,默认为 ['a', 'area']

(8)attrs

接收一个属性(字符串)或一个属性列表,提取指定属性内的链接,默认为[‘href’]。

例7:提取页面 example2.html 中引用 JavaScript 文件的链接:

python">from scrapy.http import HtmlResponse
from scrapy.linkextractors import LinkExtractor

html2 = open('LE_Example2.html').read()
response2 = HtmlResponse(url='http://example2.com', body=html2, encoding='utf8')
le = LinkExtractor(tags='script', attrs='src')
links = le.extract_links(response2)
print([link.url for link in links])

# 运行结果:
['http://example2.com/js/app1.js', 'http://example2.com/js/app2.js']
(9)process_value

接收一个形如 func(value) 的回调函数。如果传递了该参数,LinkExtractor 将调用该回调函数对提取的每一个链接(如 a 的 href )进行处理,回调函数正常情况下应返回一个字符串(处理结果),想要抛弃所处理的链接时,返回 None。

例8:在页面 example2.html 中,某些 ahref 属性是一段 JavaScript 代码,代码中包含了链接页面的实际 url 地址,此时应对链接进行处理,提取页面 example2.html 中所有实际链接:

python">from scrapy.http import HtmlResponse
from scrapy.linkextractors import LinkExtractor
import re

html2 = open('LE_Example2.html').read()
response2 = HtmlResponse(url='http://example2.com', body=html2, encoding='utf8')
def process(value):
    m = re.search("javascript:goToPage\('(.*?)'", value)
    # 如果匹配,就提取其中 url 并返回,如果不匹配则返回原值
    if m:
        value = m.group(1)
        return value

le = LinkExtractor(process_value=process)
links = le.extract_links(response2)
print([link.url for link in links])

# 运行结果:
['http://example2.com/doc.html', 'http://example2.com/example.html']

上述文章内容如有错误,谨请各位读者在评论区留言指正!


http://www.niftyadmin.cn/n/1190194.html

相关文章

百度编辑器图片在线流量返回url改动

百度编辑器中返回的是我们server中的url&#xff0c;有时并非我们须要的&#xff0c;比方图文编辑中。我想在线浏览上传过的图片 &#xff0c;那么我返回的应该是腾讯server上面的url。这样才不会被腾讯的过滤器过来掉&#xff0c;全部我们就须要改动在线管理的图片获取路径详细…

爬虫框架Scrapy(9)使用 Exporter 导出数据

文章目录使用 Exporter 导出数据1. 指定数据导出方法&#xff08;1&#xff09;命令行参数指定数据导出方式&#xff08;2&#xff09;配置文件指定数据导出方式2. 添加数据导出格式使用 Exporter 导出数据 在 Scrapy 中&#xff0c;负责导出数据的组件被称为 Exporter&#x…

python的可变类型与不可变类型

首先&#xff0c;我们需要知道在python中哪些是可变数据类型&#xff0c;哪些是不可变数据类型。可变数据类型&#xff1a;列表list和字典dict&#xff1b;不可变数据类型&#xff1a;整型int、浮点型float、字符串型string和元组tuple。 用一句话来概括上述过程就是&#xff1…

爬虫框架Scrapy(10)下载文件与图片

文章目录下载文件与图片&#xff08;一&#xff09;FilesPipeline 和 ImagesPipeline1. FilesPipeline 使用说明2. ImagesPipeline 使用说明&#xff08;二&#xff09;项目实例&#xff1a;下载 matplotlib 例子源码文件1. 页面分析2. 编码实现&#xff08;1&#xff09;创建项…

爬虫框架Scrapy(11)模拟登录

文章目录模拟登录&#xff08;一&#xff09;网站登录实质&#xff08;二&#xff09;发送 Post 请求模拟登录1. 使用 FormRequest2. 实现登录 Spider&#xff08;三&#xff09;携带 Cookies 模拟登录1. 人工获取 Cookie 模拟登录&#xff08;1&#xff09;人工获取 Cookie&am…

pip install 报错

问题描述&#xff0c;在使用pip安装django相关软件包时&#xff0c;提示错误如下&#xff1a; [roottest4 install]# pip install django1.6 Downloading/unpacking django1.6 Cannot fetch index base URL https://pypi.python.org/simple/ Could not find any downloads that…

爬虫框架Scrapy(12)爬取动态页面

文章目录爬取动态页面&#xff08;一&#xff09;Splash 渲染引擎1. render.html 端点2. execute 端点3. 常用属性与方法&#xff08;1&#xff09;Splash 对象的属性&#xff08;2&#xff09;Splash 对象的方法&#xff08;二&#xff09;安装 Scrapy-Scrapy1. 安装 splash 服…

爬虫框架Scrapy(13)保存数据到数据库

文章目录保存数据到数据库&#xff08;一&#xff09;数据保存至 MySQL 数据库1. 安装 pymysql2. 创建数据库与表3. 实现 MySQLPipeline&#xff08;二&#xff09;数据保存至 MongoDB 数据库1. 安装 pymongo2. 实现 MongoDBPipeline&#xff08;三&#xff09;数据保存至 Redi…