📜  如何使用Python Scrapy 跟踪链接?

📅  最后修改于: 2022-05-13 01:54:54.506000             🧑  作者: Mango

如何使用Python Scrapy 跟踪链接?

在本文中,我们将使用 Scrapy 来抓取数据、在链接的网页上展示以及收集这些数据。我们将从网站“https://quotes.toscrape.com/”中抓取数据。

创建 Scrapy 项目

Scrapy 带有一个高效的命令行工具,也称为“Scrapy 工具”。命令用于不同的目的,并接受一组不同的参数和选项。为了编写 Spider 代码,我们首先创建一个 Scrapy 项目,在终端执行以下命令:

scrapy startproject gfg_spiderfollowlink

使用 'startproject' 命令创建一个 Scrapy 项目

这应该在您的当前目录中创建一个“gfg_spiderfollowlink”文件夹。它包含一个“scrapy.cfg”,它是项目的配置文件。文件夹结构如下图——

'gfg_spiderfollowlink'文件夹的文件夹结构

该文件夹包含 items.py、middlerwares.py 和其他设置文件,以及“蜘蛛”文件夹。

'gfg_spiderfollowlink'文件夹的文件夹结构

保持当前配置文件的内容不变。



从一个网页中提取数据

网页抓取的代码写在蜘蛛代码文件中。要创建蜘蛛文件,我们将使用“genspider”命令。请注意,此命令在存在 scrapy.cfg 文件的同一级别执行。

我们正在抓取“http://quotes.toscrape.com/”上的所有报价。因此,我们将运行命令为:

scrapy genspider gfg_spilink "quotes.toscrape.com"

执行'genspider'命令创建一个Spider文件

上述命令将在 'spiders' 文件夹中创建一个蜘蛛文件“gfg_spilink.py”。相同的默认代码如下:

Python3
# Import the required libraries
import scrapy
  
# Spider class name
  
  
class GfgSpilinkSpider(scrapy.Spider):
    # Name of the spider
    name = 'gfg_spilink'
      
    # The domain to be scraped
    allowed_domains = ['quotes.toscrape.com']
      
    # The URLs to be scraped from the domain
    start_urls = ['http://quotes.toscrape.com/']
  
    # Default callback method
    def parse(self, response):
        pass


Python3
# Import the required libraries
import scrapy
  
# Spider class name
  
  
class GfgSpilinkSpider(scrapy.Spider):
    
    # Name of the spider
    name = 'gfg_spilink'
      
    # The domain to be scraped
    allowed_domains = ['quotes.toscrape.com']
      
    # The URLs to be scraped from the domain
    start_urls = ['http://quotes.toscrape.com/']
  
    # Default callback method
    def parse(self, response):
        
        # All quotes have CSS 'class 'attribute as 'quote'
        quotes = response.xpath('//*[@class="quote"]')
          
        # Loop through the quotes
        # selectors to fetch data for every quote
        for quote in quotes:
            
            # XPath expression to fetch
            # text of the Quote title
            # note the 'dot' operator since
            # we are extracting from single 'quote' element
            title = quote.xpath(
                './/*[@class="text"]/text()').extract_first()
              
            # XPath expression to fetch author of the Quote
            authors = quote.xpath('.//*[@itemprop="author"]/text()').extract()
              
            # XPath expression to fetch tags of the Quote
            tags = quote.xpath('.//*[@itemprop="keywords"]/@content').extract()
              
            # Yield the data desired
            yield {"Quote Text ": title, "Authors ": authors, "Tags ": tags}


Python3
# Import the required libraries
import scrapy
  
# Spider class name
class GfgSpilinkSpider(scrapy.Spider):
    
    # Name of the spider
    name = 'gfg_spilink'
      
    # The domain to be scraped
    allowed_domains = ['quotes.toscrape.com']
      
    # The URLs to be scraped from the domain
    start_urls = ['http://quotes.toscrape.com/']
  
    # Default callback method
    def parse(self, response):
        quotes = response.xpath('//*[@class="quote"]')
        for quote in quotes:
  
            # XPath expression to fetch
            # text of the Quote title
            title = quote.xpath('.//*[@class="text"]/text()').extract_first()
              
            # XPath expression to fetch
            # author of the Quote
            authors = quote.xpath('.//*[@itemprop="author"]/text()').extract()
            tags = quote.xpath('.//*[@itemprop="keywords"]/@content').extract()
            yield {"Quote Text ": title, "Authors ": authors, "Tags ": tags}
  
        # Check CSS attribute of the "Next"
        # hyperlink and extract its "href" value
        further_page_url = response.xpath(
            '//*[@class="next"]/a/@href').extract_first()
          
        # Append the "href" value, to the current page,
        # to form a complete URL, of next page
        complete_url_next_page = response.urljoin(further_page_url)
  
        # Make the spider crawl, to the next page,
        # and extract the same data
        # A new Request with the URL is made
        yield scrapy.Request(complete_url_next_page)


我们将从“quotes.toscrape.com”网站上抓取所有引用标题、作者和标签。网站登陆页面如下图所示:

“quotes.toscrape.com”登陆页面

Scrapy 为我们提供了选择器,可以“选择”网页的某些部分。选择器是 CSS 或 XPath 表达式,用于从 HTML 文档中提取数据。在本教程中,我们将使用 XPath 表达式来选择我们需要的细节。

下面我们来了解一下在spider代码中编写选择器语法的步骤:

  • 首先,我们将在 parse() 方法中编写代码。这是蜘蛛类中的默认回调方法,负责处理收到的响应。使用选择器的数据提取代码将在这里编写。
  • 为了编写 XPath 表达式,我们将选择网页上的元素,说右键单击,然后选择 Inspect 选项。这将允许我们查看其 CSS 属性。
  • 当我们右键单击第一个 Quote 并选择 Inspect 时,我们可以看到它具有 CSS 'class' 属性“quote”。同样,网页上的所有其他引号都具有相同的 CSS 'class' 属性。可以在下面看到:

右键单击第一个引号并检查其 CSS“class”属性

因此,对于相同的 XPath 表达式,可以写为 –quotes = response.xpath('//*[@class=”quote”]')。此语法将获取所有具有“quote”的元素作为 CSS 的“class”属性。其他页面上的引号具有相同的 CSS 属性。例如,网站第 3 页上的引号属于 'class' 属性,如下所示 -



网站其他页面上的引用属于相同的 CSS 类属性

我们需要获取所有报价的报价标题、作者和标签。因此,我们将在循环中编写用于提取它们的 XPath 表达式。

  • 引用标题的 CSS 'class' 属性是“文本”。因此,对于相同的 XPath 表达式将是 –quote.xpath('.//*[@class=”text”]/text()').extract_first()。 text() 方法将提取报价标题的文本。 extract_first() 方法将给出第一个匹配值,CSS 属性为“text”。点运算符“.”在开头,表示从单引号中提取数据。
  • 作者元素的 CSS 属性“class”和“itemprop”是“author”。我们可以在 XPath 表达式中使用其中任何一个。语法是 – quote.xpath('.//*[@itemprop="author"]/text()').extract()。这将提取作者姓名,其中 CSS 'itemprop' 属性为 'author'。
  • 标签元素的 CSS 属性“class”和“itemprop”是“keywords”。我们可以在 XPath 表达式中使用其中任何一个。由于有很多标签,对于任何引用,循环遍历它们将是乏味的。因此,我们将从每个引用中提取 CSS 属性“内容”。相同的 XPath 表达式是 – quote.xpath('.//*[@itemprop="keywords"]/@content').extract()。这将从“内容”属性中提取所有标签值,用于引号。
  • 我们使用“yield”语法来获取数据。我们可以使用 'yield' 收集数据并将数据传输为 CSV、JSON 和其他文件格式。

如果我们观察到这里的代码,它将抓取并提取一个网页的数据。代码如下——

蟒蛇3

# Import the required libraries
import scrapy
  
# Spider class name
  
  
class GfgSpilinkSpider(scrapy.Spider):
    
    # Name of the spider
    name = 'gfg_spilink'
      
    # The domain to be scraped
    allowed_domains = ['quotes.toscrape.com']
      
    # The URLs to be scraped from the domain
    start_urls = ['http://quotes.toscrape.com/']
  
    # Default callback method
    def parse(self, response):
        
        # All quotes have CSS 'class 'attribute as 'quote'
        quotes = response.xpath('//*[@class="quote"]')
          
        # Loop through the quotes
        # selectors to fetch data for every quote
        for quote in quotes:
            
            # XPath expression to fetch
            # text of the Quote title
            # note the 'dot' operator since
            # we are extracting from single 'quote' element
            title = quote.xpath(
                './/*[@class="text"]/text()').extract_first()
              
            # XPath expression to fetch author of the Quote
            authors = quote.xpath('.//*[@itemprop="author"]/text()').extract()
              
            # XPath expression to fetch tags of the Quote
            tags = quote.xpath('.//*[@itemprop="keywords"]/@content').extract()
              
            # Yield the data desired
            yield {"Quote Text ": title, "Authors ": authors, "Tags ": tags}

以下链接

到目前为止,我们已经看到了从单个网页中提取数据的代码。我们的最终目标是从所有网页中获取报价的相关数据。为此,我们需要创建我们的蜘蛛,跟踪链接,以便它可以导航到后续页面。超链接通常是通过编写 标签来定义的。 标签的“href”属性指示链接的目的地。我们需要提取“href”属性,以便从一页遍历到另一页。让我们研究一下,如何实现相同的——

我们需要提取 HTML 的 标签的“href”属性。 “href”属性表示链接指向的页面的 URL。因此,我们需要获取相同的内容,并加入我们当前的路径,以便蜘蛛导航,无缝地访问更多页面。对于第一页, 标签的“href”值为“/page/2”,这意味着它链接到第二页。

如果单击并观察第二个网页的“Next”链接,它的 CSS 属性为“next”。对于这个页面, 标签的“href”值是“/page/3”,这意味着它链接到第三页,依此类推。

因此,对于下一个页面链接,XPath 表达式可以被提取为——进一步_page_url = response.xpath('//*[@class=”next”]/a/@href').extract_first()。这将为我们提供“@href”的值,即第一页的“/page/2”。

上面的 URL 不足以让蜘蛛爬到下一页。我们需要通过将响应对象 URL 与上述相对 URL 合并来形成一个绝对 URL。为此,我们将使用 urljoin() 方法。

响应对象 URL 是“https://quotes.toscrape.com/”。为了旅行,到下一页,我们需要加入它,使用相对 URL“/page/2”。相同的语法是 – complete_url_next_page = response.urljoin(further_page_url)。此语法将为我们提供完整路径“https://quotes.toscrape.com/page/2/”。同样,对于第二页,根据网页编号修改为“https://quotes.toscrape.com/page/3/”等。

parse 方法现在将使用这个 'complete_url_next_page ' URL 发出一个新请求。



因此,我们最终的 Request 对象,用于导航到第二页并对其进行抓取,将是 – yield scrapy.Request(complete_url_next_page)。蜘蛛的完整代码如下:

蟒蛇3

# Import the required libraries
import scrapy
  
# Spider class name
class GfgSpilinkSpider(scrapy.Spider):
    
    # Name of the spider
    name = 'gfg_spilink'
      
    # The domain to be scraped
    allowed_domains = ['quotes.toscrape.com']
      
    # The URLs to be scraped from the domain
    start_urls = ['http://quotes.toscrape.com/']
  
    # Default callback method
    def parse(self, response):
        quotes = response.xpath('//*[@class="quote"]')
        for quote in quotes:
  
            # XPath expression to fetch
            # text of the Quote title
            title = quote.xpath('.//*[@class="text"]/text()').extract_first()
              
            # XPath expression to fetch
            # author of the Quote
            authors = quote.xpath('.//*[@itemprop="author"]/text()').extract()
            tags = quote.xpath('.//*[@itemprop="keywords"]/@content').extract()
            yield {"Quote Text ": title, "Authors ": authors, "Tags ": tags}
  
        # Check CSS attribute of the "Next"
        # hyperlink and extract its "href" value
        further_page_url = response.xpath(
            '//*[@class="next"]/a/@href').extract_first()
          
        # Append the "href" value, to the current page,
        # to form a complete URL, of next page
        complete_url_next_page = response.urljoin(further_page_url)
  
        # Make the spider crawl, to the next page,
        # and extract the same data
        # A new Request with the URL is made
        yield scrapy.Request(complete_url_next_page)

在终端上使用命令“crawl”执行 Spider。语法如下——scrapy crawl spider_name。因此,我们可以将我们的蜘蛛运行为——scrapy crawl gfg_spilink。它将通过跟踪链接抓取整个网站,并生成报价数据。输出如下所示 -

Spider 输出来自网页 1 、 2 和其余网页的报价

如果我们查看Spider输出的统计数据,我们可以看到Spider通过链接已经抓取了十多个网页。此外,行情数量接近 100。

终端的 Spider 统计数据,表示抓取的页面数

我们可以收集任何文件格式的数据以进行存储或分析。为了收集相同的内容,在 JSON 文件中,我们可以在 'crawl' 中提及文件名,语法如下:

scrapy crawl gfg_spilink -o spiderlinks.json

上面的命令将在 JSON 文件“spiderlinks.json”中收集整个抓取的行情数据。文件内容如下所示:

所有报价都收集在 JSON 文件中