scrapy框架初識(Spider模塊,CrawlSpider模塊的使用)


一.什么是Scrapy?

  Scrapy是一個為了爬取網站數據,提取結構性數據而編寫的應用框架,非常出名,非常強悍。所謂的框架就是一個已經被集成了各種功能(高性能異步下載,隊列,分布式,解析,持久化等)的具有很強通用性的項目模板。對於框架的學習,重點是要學習其框架的特性、各個功能的用法即可。

二.安裝

Linux:
      pip3 install scrapy

  Windows:
      a. pip3 install wheel
      b. 下載twisted http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
      c. 進入下載目錄,執行 pip3 install Twisted‑17.1.0‑cp35‑cp35m‑win_amd64.whl  # 要與b的版本保持一致
      d. pip3 install pywin32
      e. pip3 install scrapy

三.基礎使用

  1.創建項目:scrapy startproject 項目名稱   

項目結構:

project_name/
   scrapy.cfg:
   project_name/
       __init__.py
       items.py
       pipelines.py
       settings.py
       spiders/
           __init__.py

scrapy.cfg   項目的主配置信息。(真正爬蟲相關的配置信息在settings.py文件中)
items.py     設置數據存儲模板,用於結構化數據,如:Django的Model
pipelines    數據持久化處理
settings.py  配置文件,如:遞歸的層數、並發數,延遲下載等
spiders      爬蟲目錄,如:創建文件,編寫爬蟲解析規則

 2.創建爬蟲應用程序:

      cd project_name(進入項目目錄)

      scrapy genspider 應用名稱 爬取網頁的起始url (例如:scrapy genspider qiubai www.qiushibaike.com)

 3.編寫爬蟲文件:在步驟2執行完畢后,會在項目的spiders中生成一個應用名的py爬蟲文件,文件源碼如下:

# -*- coding: utf-8 -*-
import scrapy

class QiubaiSpider(scrapy.Spider):
    name = 'qiubai' #應用名稱
    #允許爬取的域名(如果遇到非該域名的url則爬取不到數據)
    allowed_domains = ['https://www.qiushibaike.com/']
    #起始爬取的url
    start_urls = ['https://www.qiushibaike.com/']

     #訪問起始URL並獲取結果后的回調函數,該函數的response參數就是向起始的url發送請求后,獲取的響應對象.該函數返回值必須為可迭代對象或者NUll 
     def parse(self, response):
        print(response.text) #獲取字符串類型的響應內容
        print(response.body)#獲取字節類型的相應內容

  4.設置修改settings.py配置文件相關配置:

修改內容及其結果如下:
19行:USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' #偽裝請求載體身份

22行:ROBOTSTXT_OBEY = False  #可以忽略或者不遵守robots協議

      5.執行爬蟲程序:scrapy crawl  應用名稱

四.小試牛刀:將糗百首頁中段子的內容和標題進行爬取

import scrapy
from day04.items import Day04Item

class QiubaiSpider(scrapy.Spider):
    name = 'qiubai'
    #allowed_domains = ['https://www.qiushibaike.com/']
    start_urls = ['https://www.qiushibaike.com/text/']

基於管道的持久化儲存
    def parse(self, response):
        # xpath為response中的方法,可以將xpath函數直接作用於該函數中
        odiv = response.xpath('//div[@id="content-left"]/div')
        content_list = []  # 用於儲存解析到的數據
        for div in odiv:
            # xpath函數返回的為列表,列表中存放的數據為Selector類型的數據。
            # 我們解析到的內容被封裝在了Selector對象中,
            # 需要調用extract()函數將解析的內容從Selecor中取出。

            # author = div.xpath('./div[@class="author clearfix"]/a[2]/h2/text()')[0].extract()
            # content = div.xpath('./a/div[@class="content"]/span[1]/text()')[0].extract()

            author = div.xpath('./div/a[2]/h2/text()').extract_first()  # 不用執行[0]操作
            content = div.xpath('./a/div[@class="content"]/span//text()').extract()
            content = "".join(content)

            # 將解析到的內容封裝到字典中
            dic = {
                '作者': author,
                '內容': content
            }
            # 將數據儲存到content_list這個列表中
            content_list.append(dic)

        return content_list
     終端執行爬蟲程序:
         # D:\package\jupyter\day04>scrapy crawl qiubai -o text.csv
         # 測試通不通時,執行:scrapy crawl qiubai --nolog
          #測試查看錯誤信息時,執行:scrapy crawl qiubai

執行爬蟲程序:

 scrapy crawl 爬蟲名稱 :該種執行形式會顯示執行的日志信息
 scrapy crawl 爬蟲名稱 --nolog:該種執行形式不會顯示執行的日志信息

 高級使用

提問:如果想要通過爬蟲程序去爬取”糗百“全站數據新聞數據的話,有幾種實現方法?

方法一:基於Scrapy框架中的Spider的遞歸爬取進行實現(Request模塊遞歸回調parse方法)。

方法二:基於CrawlSpider的自動爬取進行實現(更加簡潔和高效)。

一.簡介

  CrawlSpider其實是Spider的一個子類,除了繼承到Spider的特性和功能外,還派生除了其自己獨有的更加強大的特性和功能。其中最顯著的功能就是”LinkExtractors鏈接提取器“。Spider是所有爬蟲的基類,其設計原則只是為了爬取start_url列表中網頁,而從爬取到的網頁中提取出的url進行繼續的爬取工作使用CrawlSpider更合適。

二.使用

  1.創建scrapy工程:scrapy startproject projectName

  2.創建爬蟲文件:scrapy genspider -t crawl spiderName www.xxx.com

    --此指令對比以前的指令多了 "-t crawl",表示創建的爬蟲文件是基於CrawlSpider這個類的,而不再是Spider這個基類。

  3.觀察生成的爬蟲文件

# -*- coding: utf-8 -*-
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule


class ChoutidemoSpider(CrawlSpider):
    name = 'choutiDemo'
    #allowed_domains = ['www.chouti.com']
    start_urls = ['http://www.chouti.com/']

    rules = (
        Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),
    )

    def parse_item(self, response):
        i = {}
        #i['domain_id'] = response.xpath('//input[@id="sid"]/@value').extract()
        #i['name'] = response.xpath('//div[@id="name"]').extract()
        #i['description'] = response.xpath('//div[@id="description"]').extract()
        return i

  - 2,3行:導入CrawlSpider相關模塊

  - 7行:表示該爬蟲程序是基於CrawlSpider類的

  - 12,13,14行:表示為提取Link規則

  - 16行:解析方法

  CrawlSpider類和Spider類的最大不同是CrawlSpider多了一個rules屬性,其作用是定義”提取動作“。在rules中可以包含一個或多個Rule對象,在Rule對象中包含了LinkExtractor對象

3.1 LinkExtractor:顧名思義,鏈接提取器。 

 LinkExtractor(

         allow=r'Items/'# 滿足括號中“正則表達式”的值會被提取,如果為空,則全部匹配。

         deny=xxx,  # 滿足正則表達式的則不會被提取。


         restrict_xpaths=xxx, # 滿足xpath表達式的值會被提取

         restrict_css=xxx, # 滿足css表達式的值會被提取

         deny_domains=xxx, # 不會被提取的鏈接的domains。 

    )
    - 作用:提取response中符合規則的鏈接。

  3.2 Rule : 規則解析器。根據鏈接提取器中提取到的鏈接,根據指定規則提取解析器鏈接網頁中的內容。 

  Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True)

    - 參數介紹:

      參數1:指定鏈接提取器

      參數2:指定規則解析器解析數據的規則(回調函數)

      參數3:是否將鏈接提取器繼續作用到鏈接提取器提取出的鏈接網頁中。當callback為None,參數3的默認值為true。

  3.3 rules=( ):指定不同規則解析器。一個Rule對象表示一種提取規則。

  3.4 CrawlSpider整體爬取流程:

       a)爬蟲文件首先根據起始url,獲取該url的網頁內容

    b)鏈接提取器會根據指定提取規則將步驟a中網頁內容中的鏈接進行提取

    c)規則解析器會根據指定解析規則將鏈接提取器中提取到的鏈接中的網頁內容根據指定的規則進行解析

    d)將解析數據封裝到item中,然后提交給管道進行持久化存儲    

  4.簡單代碼實戰應用

      4.1 爬取糗事百科糗圖板塊的所有頁碼數據

# -*- coding: utf-8 -*-
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule


class CrawldemoSpider(CrawlSpider):
    name = 'qiubai'
    #allowed_domains = ['www.qiushibaike.com']
    start_urls = ['https://www.qiushibaike.com/pic/']

    #連接提取器:會去起始url響應回來的頁面中提取指定的url
    link = LinkExtractor(allow=r'/pic/page/\d+\?') #s=為隨機數
    link1 = LinkExtractor(allow=r'/pic/$')#爬取第一頁
    #rules元組中存放的是不同的規則解析器(封裝好了某種解析規則)
    rules = (
        #規則解析器:可以將連接提取器提取到的所有連接表示的頁面進行指定規則(回調函數)的解析
        Rule(link, callback='parse_item', follow=True),
        Rule(link1, callback='parse_item', follow=True),
    )

    def parse_item(self, response):
        print(response)

 4.2 爬蟲文件:

# -*- coding: utf-8 -*-
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from qiubaiBycrawl.items import QiubaibycrawlItem
import re
class QiubaitestSpider(CrawlSpider):
    name = 'qiubaiTest'
    #起始url
    start_urls = ['http://www.qiushibaike.com/']

    #定義鏈接提取器,且指定其提取規則
    page_link = LinkExtractor(allow=r'/8hr/page/\d+/')
    
    rules = (
        #定義規則解析器,且指定解析規則通過callback回調函數
        Rule(page_link, callback='parse_item', follow=True),
    )

    #自定義規則解析器的解析規則函數
    def parse_item(self, response):
        div_list = response.xpath('//div[@id="content-left"]/div')
        
        for div in div_list:
            #定義item
            item = QiubaibycrawlItem()
            #根據xpath表達式提取糗百中段子的作者
            item['author'] = div.xpath('./div/a[2]/h2/text()').extract_first().strip('\n')
            #根據xpath表達式提取糗百中段子的內容
            item['content'] = div.xpath('.//div[@class="content"]/span/text()').extract_first().strip('\n')

            yield item #將item提交至管道

  4.2 item文件:

# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html

import scrapy


class QiubaibycrawlItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    author = scrapy.Field() #作者
    content = scrapy.Field() #內容

  4.3 管道文件:

# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html

class QiubaibycrawlPipeline(object):
    
    def __init__(self):
        self.fp = None
        
    def open_spider(self,spider):
        print('開始爬蟲')
        self.fp = open('./data.txt','w')
        
    def process_item(self, item, spider):
        #將爬蟲文件提交的item寫入文件進行持久化存儲
        self.fp.write(item['author']+':'+item['content']+'\n')
        return item
    
    def close_spider(self,spider):
        print('結束爬蟲')
        self.fp.close()

123


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM