Scrapy:学习笔记(2)——Scrapy项目

Scrapy:学习笔记(2)——Scrapy项目

一、建立项目

  建立一个Scrapy项目,并将其命名为“demo”css

scrapy startproject demo
cd demo

  稍等片刻后,Scrapy为咱们生成了一个目录结构:html

  

  其中,咱们目前须要重点关注三个文件:python

  • items.py:设置数据存储模板,用于结构化数据,如:Django的Model。
  • pipelines.py: 定义数据处理行为,如:通常结构化的数据持久化
  • settings.py:配置文件,如:递归的层数、并发数,延迟下载等

1.一、明确爬虫开发的四个步骤

  项目已经建立完成了,为了指导接下来的开发,咱们必须明确Scrapy爬虫的四个步骤:web

  1. 新建项目 (scrapy startproject xxx):新建一个新的爬虫项目
  2. 明确目标 (编写items.py):明确你想要抓取的目标
  3. 制做爬虫 (spiders/xxspider.py):制做爬虫开始爬取网页
  4. 存储内容 (pipelines.py):设计管道存储爬取内容

  因此,接下来咱们须要明确目标。json

 

二、明确目标

  以个人博客网站为例,爬取文章的关键信息(标题、摘要、上传时间、阅读数量)并发

  

2.一、编写items.py文件

  1. 打开 demo 目录下的 items.py。dom

  2. Item 定义结构化数据字段,用来保存爬取到的数据,有点像 Python 中的 dict,可是提供了一些额外的保护来减小错误。scrapy

  3. 能够经过建立一个 scrapy.Item 类, 而且定义类型为 scrapy.Field 的类属性来定义一个 Item(能够理解成相似于 ORM 的映射关系)。ide

  正以下面这样:post

import scrapy


class DemoItem(scrapy.Item):
    # define the fields for your item here like:
    postTitle = scrapy.Field()
    postDate = scrapy.Field()
    postDesc = scrapy.Field()
    postNumber = scrapy.Field()

  

三、制做爬虫

3.一、快速生成爬虫

  Scrapy提供了相关命令来帮助咱们快速生成爬虫结构,执行下面语句,来生成名为basic的爬虫:

scrapy genspider basic web

  它的结构以下:

import scrapy

class BasicSpider(scrapy.Spider):
    name = 'basic'
    allowed_domains = ['web']
    start_urls = ['website']

    def parse(self, response):
        pass

  它肯定了三个强制属性和方法:

  • name = "basic" 这个爬虫的识别名称,必须是惟一的,在不一样的爬虫必须定义不一样的名字。
  • allow_domains = [] 是搜索的域名范围,也就是爬虫的约束区域,规定爬虫只爬取这个域名下的网页,不存在的URL会被忽略。
  • start_urls = () 爬取的URL元祖/列表。爬虫从这里开始抓取数据,因此,第一次下载的数据将会从这些urls开始。其余子URL将会从这些起始URL中继承性生成。
  • parse(self, response) 解析的方法,每一个初始URL完成下载后将被调用,调用的时候传入从每个URL传回的Response对象来做为惟一参数,主要做用以下:
    • 负责解析返回的网页数据(response.body),提取结构化数据(生成item)
    • 生成须要下一页的URL请求。

3.二、取数据

  咱们在前面已经讲解了XPath的基本使用,此处不在赘述。

  这一过程,咱们须要观察网页源代码。首先每一页的博客是根据日期能够分为几大块,而后每一块内依次排列这每一篇文章的各项信息。

  

  根据抽象出的结构,咱们取出数据要爬出的数据:

# -*- coding: utf-8 -*-
import scrapy
import re
from demo.items import DemoItem


class BasicSpider(scrapy.Spider):
    name = 'basic'
    allowed_domains = ['www.cnblogs.com']
    start_urls = ['https://www.cnblogs.com/MrSaver/default.html?page=2']

    def parse(self, response):
        posts = response.xpath('//div[@class="day"]')
        # result = []
        for each_day_post in posts:
            day_postTitles = each_day_post.xpath('./div[@class="postTitle"]/a[@class="postTitle2"]/text()').extract();
            day_postDesc = each_day_post.xpath('./div[@class="postDesc"]/text()').extract();
            if (len(day_postTitles) == 1):
                tmp = DemoItem()
                tmp['postTitle'] = ''.join(day_postTitles)
                tmp['postDesc'] = ''.join(day_postDesc)
                tmp['postNumber'] = getNumber(tmp['postDesc'])
                yield tmp
            else:
                for i in range(len(day_postTitles)):
                    tmp = DemoItem()
                    tmp['postTitle'] = day_postTitles[i]
                    tmp['postDesc'] = day_postDesc[i]
                    tmp['postNumber'] = getNumber(tmp['postDesc'])
                    yield tmp

        #提取出分页器中所涉及的全部链接喂给爬虫
        next_url2 = response.xpath('//div[@id="homepage_top_pager"]/div/a/@href').extract()
        if next_url2 is not None:
            for n_url in next_url2:
                yield response.follow(n_url,callback=self.parse)#scrapy.Request(next_url2, callback=self.parse)


def getNumber(txt):
    pattern = re.compile(r'阅读\((\d+)\)');
    m = pattern.search(txt)
    return m.group(1)

  

四、保存数据

scrapy保存信息的最简单的方法主要有四种,-o 输出指定格式的文件,命令以下:

scrapy crawl basic -o items.json

json lines格式,默认为Unicode编码

scrapy crawl basic -o items.jsonl

csv 逗号表达式,可用Excel打开

scrapy crawl basic -o items.csv

xml格式

scrapy crawl basic -o items.xml    

4.一、关于中文数据的保存

修改输出编码,在settings.py文件中,添加行

FEED_EXPORT_ENCODING = 'gbk'

 

五、找到下一页

  一个典型的爬虫会向两个方向移动

  • 横向:从一个索引页到另外一个索引页。咱们称之为水平爬取
  • 纵向:从一个索引页到其二级页面并抽取Item。咱们称之为垂直爬取

  在水平爬取过程当中,咱们须要取到下一页的地址,一个简单的Demo以下:

next_url = response.xpath('//div[@id="nav_next_page"]/a/@href').extract_first()
if next_url is not None:
  print(next_url)
  next_url = response.urljoin(next_url)
  yield scrapy.Request(next_url, callback=self.parse)

  在提取数据以后,parse()方法查找到下一页的连接,使用urljoin()方法构建完整的绝对URL(由于连接能够是相对的)并向下一页生成新请求,将自身注册为回调以处理下一页的数据提取并保持爬网遍历全部页面

  它建立了一种循环,跟随到下一页的全部连接,直到它找不到 ,可用于爬行博客,论坛和其余具备分页的网站。

5.一、建立请求的快捷方式

  做为建立Request对象的快捷方式,您可使用response.follow:

next_page = response.css('li.next a::attr(href)').get()
if next_page is not None:
  yield response.follow(next_page, callback=self.parse)

  与scrapy.Request不一样,response.follow直接支持相对URL - 无需调用urljoin。请注意,response.follow只返回一个Request实例,你仍然须要yield这个实例。

相关文章
相关标签/搜索