Mac使用Scrapy爬虫(二)

上一期介绍了python爬虫框架Scrapy的安装和项目结构,具体内容可参考Mac使用Scrapy爬虫(一)

这一次我们先来小试牛刀,看看Scrapy能爬什么以及怎么爬去

一、最简单的爬虫

先在生成项目文件夹下的spiders文件夹下建立如下 firstCrawl文件:
然后在项目根目录下运行,-o参数会将爬取的内容都放入json文件
$:scrapy crawl myfirstCrawl -o myFirstCrawlData.json(注意这个需要和申明spider类的名字相同)

import scrapy


class QuotesSpider(scrapy.Spider):
    name = "myfirstCrawl"
    # start_urls = [
    #         'http://quotes.toscrape.com/page/1/',
    #         'http://quotes.toscrape.com/page/2/',
    #     ]
    def start_requests(self):
        urls = [
            'http://quotes.toscrape.com/page/1/',
            'http://quotes.toscrape.com/page/2/',
        ]
        for url in urls:
            yield scrapy.Request(url=url, callback=self.parse)

    def parse(self, response):
        ##这里返回值其实是一个迭代器。每执一次,就会从迭代器中取一个元素
         for quote in response.css('div.quote'):
            yield {
                'text': quote.css('span.text::text').extract_first(),
                'author': quote.css('small.author::text').extract_first(),
                'tags': quote.css('div.tags a.tag::text').extract(),
            }
          ##获取下一个需要爬去的地址,这个在迭代器中返回的是一个Request实例。他包含要爬去的地址和所需要进行的回调函数
          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)
              ## 可以使用下面的缩写,来添加下一个需要爬去的内容
              ##  yield response.follow(next_page, callback=self.parse)

以上是申明了一个Spider类,也就是用生成了一个爬虫器,他继承了scrapy下的Scpider类。

  • name:用来标记改spider的名称,该名称在整个项目中唯一
  • start_requests方法:这个方法需要返回一个起始爬去请求组。可以以数组的形式,或者也可以返回一个迭代器。在改方法下,就可以在请求前,或者在请求之后对请求来的内容做一些处理
  • start_urls:同start_requests方法相同,也是需要爬去的地址。但是这个数组只是包含了需要爬取的地址
  • parseh方法:用来处理每个Request请求所得到的Response。他的入参response是TextResponse的一个实例。因此,他包含了请求网页的内容。除了在这里可以进行对页面的处理之外,还可以从返回的内容中提取页面,并交给迭代器继续爬去。同时scrapy的schedule机制会自动甄别url,如果该url已经爬取过,将不会再次爬取

以上代码将所给两个网页爬取过来之后,将去到的数据生成一个迭代器,然后返回。之后数据会被写入myFirstCrawlData.json文件。

二、Scrapy 爬虫运行机理:

爬虫发生了什么?

1.从start_requests函数开始,定义需要爬取的Requests,并且定义对改Requests函数进行处理的回调函数,默认是parse函数。

2.迭代请求得到的Request,进入其回调函数,在这里进行处理。回调函数需要返回,其返回形式可以使一个字典,一个Item对象,一个新的Request请求或者是以上这些内容的一个迭代器。

3.在parse函数中,使用Selector类从Request–contents中提取所需数据。同样,也可以使用pyhton比较火的 BeautifulSoup, lxml 模块进行提取。

4.最后,进行数据持久化,或写入文件中。

三、Scrapy的Spider类:

对于Scrapy,我们的每一个特定网站的爬虫,其实是一个Spider类的实例,或者其子类的实例。
Spider类是最基础的类,其只包含了最基础的start_requests函数和parse函数。即通过start_requests获取请求,之后使用parse函数进行解析。
Spider子类有:

  • CrawlSpider
  • XMLFeedSpider
  • CSVFeedSpider
  • SitemapSpider

下面讲解下区别:

1、CrawlSpider

CrawlSpider使用与爬去有一定规律的网页。他提供了一个Rules机制,可以实现制定好爬虫的Rule规则,之后每一个符合改规则的新的Request会被提取出来。该子类的主要区别是,它具有rules和parse_start_url

  • rules:一个Rule对象的数组或单例,使用Rule来定义爬去的规则,符合该规则的链接都会被提取出来
    Rule(LinkExtractor(allow=('kid\.jpg', ), deny=('vipkid\.jpg', ), callback='parse_item')),
    以上规则会提取页面中匹配了kid.jpg的链接,但是不会匹配包含了vipkid.jpg的链接。可以有多个的Rule,但是实际匹配中,如果匹配成功了一条规则,之后的将默认不会匹配。具体Rule的匹配规则,可见官网 https://doc.scrapy.org/en/latest/topics/spiders.html#generic-spiders
  • parse_item:用来处理从start_urls获取来的初始的爬去Response,他可以返回Item对象,Request对象或他们的迭代形式

实例:

from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor

class MySpider(CrawlSpider):
    name = 'baidu.com'
    allowed_domains = ['baidu.com']
    start_urls = ['http://www.baidu.com']

    rules = (
        Rule(LinkExtractor(allow=('category\.php', ), deny=('subsection\.php', ))),
        Rule(LinkExtractor(allow=('item\.php', )), callback='parse_item'),
    )

    def parse_item(self, response):
        item = scrapy.Item()
        item['id'] = response.xpath('//td[@id="item_id"]/text()').re(r'ID: (\d+)')
        item['name'] = response.xpath('//td[@id="item_name"]/text()').extract()
        item['description'] = response.xpath('//td[@id="item_description"]/text()').extract()
        return item
    原文作者:persiT
    原文地址: https://www.jianshu.com/p/46878ba227d6
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞