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這個實例。

相關文章
相關標籤/搜索