目錄
CrawlSpider簡介
rules
parse_start_url(response)
Rule(爬取規則)
Link Extractors
CrawlSpider實戰
建立項目
定義Item
建立CrawlSpider
編寫Pipeline
啟動爬蟲
CrawlSpider簡介
class scrapy.spiders.CrawlSpider
CrawlSpider 是 Spider 的一個子類,不僅天生就繼承了Spider的所有特性,還在Spider的基礎上提供了一些擴充能力:允許使用者定義一些規則(Rule)來跟進那些需要繼續爬取的URL(連結)。
除了從Spider繼承過來的屬性外,CrawlSpider 還提供了一個新的屬性:
rules
一個包含一個(或多個) Rule 對象的集合(list)。 每個 Rule 對爬取網站的一類URL連結定義了特定表現。 如果多個Rule比對了相同的連結,則根據他們在本屬性中被定義的順序,第一個會被使用。
CrawlSpider 也提供了一個可複寫(overrideable)的方法:
parse_start_url(response)
當start_url的請求傳回時,該方法被調用。 該方法分析最初的傳回值并必須傳回一個 Item 對象或者 一個 Request 對象或者 一個可疊代的包含二者對象。
Rule(爬取規則)
class scrapy.spiders.Rule(link_extractor, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=None)
scrapy.spiders.Rule各項參數:
- link_extractor 是一個 Link Extractor 對象,用于定義需要提取的連結。
- callback 是一個callable 或 string ( 該spider 中同名的函數将作為回調函數被調用)。 從link_extractor中每擷取到比對的連結時将會調用該函數。該回調函數接受一個response作為其第一個參數, 并傳回一個包含 Item 以及(或) Request 對象(或者這兩者的子類)的清單(list)。
- cb_kwargs 包含傳遞給回調函數的參數(keyword argument)的字典。
- follow 是一個布爾(boolean)值,指定了根據該規則從response提取的連結是否需要跟進。 如果 callback 為 None, follow 預設設定為 True ,否則預設為 False 。
- process_links 是一個callable或string(該spider 中同名的函數将作為回調函數被調用)。 從link_extractor 中擷取到連結清單時将會調用該函數。該方法主要用來過濾。
- process_request 是一個callable或string(該spider 中同名的函數将作為回調函數被調用)。 該規則提取到每個request時都會調用該函數。該函數必須傳回一個request或者None。 (用來過濾request)
警告:當編寫爬蟲規則時,請避免使用 parse 作為回調函數。 由于 CrawlSpider 使用 parse 方法來實作其邏輯,如果 您覆寫了 parse 方法,crawl spider 将會運作失敗。
Link Extractors
class scrapy.linkextractors.LinkExtractor
Link Extractors 用來從網頁(scrapy.http.Response 對象)中抽取最終将會被follow 的連結。
Link Extractors常用參數:
- allow 滿足括号中“正規表達式”的URL會被提取,如果為空,則全部比對
- deny 滿足括号中“正規表達式”的URL一定不提取(優先級高于 allow )
- allow_domains 會被提取的連結的 domains
- deny_domains 一定不會被提取連結的domains
- restrict_xpaths 使用 xpath表達式,和 allow 共同作用過濾連結,即 xpath 滿足範圍内的 URL 會被提取
Scrapy提供了 scrapy.linkextractors import LinkExtractor , 但你可以通過實作一個簡單的接口建立自己定制的Link Extractor來滿足需求。
每個link extractor有唯一的公共方法是 extract_links ,它接收一個 Response 對象,并傳回一個 scrapy.link.Link 對象。Link Extractors,要執行個體化一次并且 extract_links 方法會根據不同的response調用多次提取連結。
CrawlSpider實戰
本文将以爬取起點中文網中所有的免費文章(标題、簡介、作者、文章位址)為例對CrawlSpider的用法進行示例。
建立項目
打開一個 Windows指令行視窗,切換到你打算存儲代碼的目錄中(本例中是 D:\scrapy),運作下列指令:
d:\scrapy>scrapy startproject qidian_crawl
執行完該指令後,将會建立包含下列内容的 qidian_crawl 目錄:

定義Item
在 items.py 中定義所需爬取的文章字段(标題、簡介、作者、文章位址)。
import scrapy
class QidianCrawlItem(scrapy.Item):
title = scrapy.Field() # 标題
intro = scrapy.Field() # 簡介
author = scrapy.Field() # 作者
url = scrapy.Field() # 文章位址
建立CrawlSpider
CrawlSpider 的建立方法跟普通的Spider類似,在Windows指令行執行如下指令完成建立:
d:\scrapy>cd qidian_crawl
d:\scrapy\qidian_crawl>scrapy genspider -t crawl qidian qidian.com
執行完該指令後,将會在 qidian_crawl 的 spiders 目錄下生成一個 qidian.py 檔案 :
我們要在 qidian.py 檔案中編寫爬取網站的連結URL提取和處理規則。
# -*- coding: utf-8 -*-
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from qidian_crawl.items import QidianCrawlItem
class QidianSpider(CrawlSpider): # 繼承自 class CrawlSpider(Spider)
name = 'qidian' # 爬蟲名稱,啟動爬蟲時使用:scrapy crawl <爬蟲名稱>
allowed_domains = ['qidian.com'] # 允許爬取的範圍
'''
爬蟲的起始位址,其響應可使用 parse_start_url(response) 進行專門處理。
'''
start_urls = [
'https://www.qidian.com/free/all?orderId=&vip=hidden&style=1&pageSize=20&siteid=1&pubflag=0&hiddenField=1&page=1']
def start_requests(self): # 啟動時設定 Cookies ,Spider 的特性
cookies = 'e1=%7B%22pid%22%3A%22qd_P_xiangqing%22%2C%22eid%22%3A%22%22%7D; e2=%7B%22pid%22%3A%22qd_P_xiangqing%22%2C%22eid%22%3A%22%22%2C%22l1%22%3A4%7D; _csrfToken=0oIxR8Di1jdqyiUCGJAhBLcm6a0kyMuvmrq0vyjI; newstatisticUUID=1556264399_358226677; e2=%7B%22pid%22%3A%22qd_P_free%22%2C%22eid%22%3A%22qd_C44%22%7D; e1=%7B%22pid%22%3A%22qd_P_limitfree%22%2C%22eid%22%3A%22qd_E01%22%2C%22l1%22%3A4%7D'
cookies = {i.split('=')[0]: i.split('=')[1] for i in cookies.split('; ')}
yield scrapy.Request(self.start_urls[0], cookies=cookies)
'''
連結URL的提取和處理規則
'''
rules = (
Rule(LinkExtractor(allow=r'//book.qidian.com/info/\d+'), callback='parse_item', follow=False),
Rule(LinkExtractor(
allow=r'//www\.qidian\.com/free/all\?orderId=&vip=hidden&style=1&pageSize=20&siteid=1&pubflag=0&hiddenField=1&page=\d+'),
follow=True),
)
def parse_item(self, response): # 回調函數
item = QidianCrawlItem()
item['url'] = response.request._url
item['title'] = response.xpath("//div[@class='book-info ']/h1/em/text()").extract_first()
item['author'] = response.xpath("//div[@class='book-info ']/h1/span/a/text()").extract_first()
item['intro'] = response.xpath("//div[@class='book-info ']//p[@class='intro']/text()").extract_first()
yield item
編寫Pipeline
CrawlSpider中收集的Item将會被傳遞到Item Pipeline中再次進行處理,在這裡我們将提取到的QidianCrawlItem資料儲存到檔案中。
# -*- coding: utf-8 -*-
from qidian_crawl.items import QidianCrawlItem
import json
class QidianCrawlPipeline(object):
def process_item(self, item, spider):
if isinstance(item, QidianCrawlItem): # 僅處理 QidianCrawlItem ,其他Item不予處理,直接傳回
# 将文章資料儲存到檔案
with open('qidian.txt', 'a', encoding='utf-8') as f:
json.dump(dict(item), f, ensure_ascii=False, indent=2)
return item
在settings.py 中激活 Pipeline,并設定好 User-Agent 。
# Configure item pipelines
# See https://doc.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
'qidian_crawl.pipelines.QidianCrawlPipeline': 300,
}
# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
# Obey robots.txt rules
ROBOTSTXT_OBEY = False
啟動爬蟲
至此示例項目就算配置完成了,在Windows指令行執行如下指令來啟動爬蟲:
d:\scrapy\qidian_crawl>scrapy crawl qidian
待程式執行完成後,會在Scrapy項目的根目錄下生成一個qidian.txt文本檔案。
qidian.txt 中的前兩條文章内容如下: