Scrapy筆記四 自動爬取網頁之使用CrawlSpider

  • 2019 年 11 月 23 日
  • 筆記

學習自:http://blog.csdn.net/u012150179/article/details/34913315

原理部分放在後面,首先來實現一下:

原網站中只有寫爬蟲主要的程式碼,這裡我把邊緣程式碼也記錄下來,

0.創建項目:

Python

scapy startproject CSDNBlogCrawlSpider

1

scapy startproject CSDNBlogCrawlSpider

1.item.py

Python

from scrapy.item import Item, Field class CsdnblogcrawlspiderItem(Item): blog_name = Field() blog_url = Field()

123456

from scrapy.item import Item, Field class CsdnblogcrawlspiderItem(Item):     blog_name = Field()    blog_url = Field()

2. pipelines.py

Python

import json import codecs class CsdnblogcrawlspiderPipeline(object): def __init__(self): self.file = codecs.open('log.json',mode='wb',encoding='utf-8') def process_item(self, item, spider): line = json.dumps(dict(item)) + 'n' self.file.write(line.decode("unicode_escape")) return item

1234567891011

import jsonimport codecs class CsdnblogcrawlspiderPipeline(object):    def __init__(self):        self.file = codecs.open('log.json',mode='wb',encoding='utf-8')     def process_item(self, item, spider):        line = json.dumps(dict(item)) + 'n'        self.file.write(line.decode("unicode_escape"))        return item

3. settings.py

Python

# -*- coding: utf-8 -*- BOT_NAME = 'CSDNBlogCrawlSpider' SPIDER_MODULES = ['CSDNBlogCrawlSpider.spiders'] NEWSPIDER_MODULE = 'CSDNBlogCrawlSpider.spiders' COOKIES_ENABLED = False ITEM_PIPELINES = { 'CSDNBlogCrawlSpider.pipelines.CsdnblogcrawlspiderPipeline':301 }

123456789101112

# -*- coding: utf-8 -*- BOT_NAME = 'CSDNBlogCrawlSpider' SPIDER_MODULES = ['CSDNBlogCrawlSpider.spiders']NEWSPIDER_MODULE = 'CSDNBlogCrawlSpider.spiders' COOKIES_ENABLED = False ITEM_PIPELINES = {    'CSDNBlogCrawlSpider.pipelines.CsdnblogcrawlspiderPipeline':301}

4.spiders/text.py

Python

#coding:utf-8 from scrapy.contrib.spiders import CrawlSpider, Rule from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor from scrapy.selector import Selector from CSDNBlogCrawlSpider.items import CsdnblogcrawlspiderItem class CSDNBlogCrawlSpider(CrawlSpider): """繼承自CrawlSpider,實現自動爬取的爬蟲。""" name = "CSDNBlogCrawlSpider" #設置下載延時 download_delay = 2 allowed_domains = ['blog.csdn.net'] #第一篇文章地址 start_urls = ['http://blog.csdn.net/u012150179/article/details/11749017'] #rules編寫法一,官方文檔方式 #rules = [ # #提取「下一篇」的鏈接並**跟進**,若不使用restrict_xpaths參數限制,會將頁面中所有 # #符合allow鏈接全部抓取 # Rule(SgmlLinkExtractor(allow=('/u012150179/article/details'), # restrict_xpaths=('//li[@class="next_article"]')), # follow=True) # # #提取「下一篇」鏈接並執行**處理** # #Rule(SgmlLinkExtractor(allow=('/u012150179/article/details')), # # callback='parse_item', # # follow=False), #] #rules編寫法二,更推薦的方式(自己測驗,使用法一時經常出現爬到中間就finish情況,並且無錯誤碼) rules = [ Rule(SgmlLinkExtractor(allow=('/u012150179/article/details'), restrict_xpaths=('//li[@class="next_article"]')), callback='parse_item', follow=True) ] def parse_item(self, response): print "parse_item>>>>>>" item = CsdnblogcrawlspiderItem() sel = Selector(response) blog_url = str(response.url) blog_name = sel.xpath('//div[@id="article_details"]/div/h1/span/a/text()').extract() item['blog_name'] = [n.encode('utf-8') for n in blog_name] item['blog_url'] = blog_url.encode('utf-8') yield item

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152

#coding:utf-8from scrapy.contrib.spiders import CrawlSpider, Rulefrom scrapy.contrib.linkextractors.sgml import SgmlLinkExtractorfrom scrapy.selector import Selectorfrom CSDNBlogCrawlSpider.items import CsdnblogcrawlspiderItem  class CSDNBlogCrawlSpider(CrawlSpider):     """繼承自CrawlSpider,實現自動爬取的爬蟲。"""     name = "CSDNBlogCrawlSpider"    #設置下載延時    download_delay = 2    allowed_domains = ['blog.csdn.net']    #第一篇文章地址    start_urls = ['http://blog.csdn.net/u012150179/article/details/11749017']     #rules編寫法一,官方文檔方式    #rules = [    #    #提取「下一篇」的鏈接並**跟進**,若不使用restrict_xpaths參數限制,會將頁面中所有    #    #符合allow鏈接全部抓取    #    Rule(SgmlLinkExtractor(allow=('/u012150179/article/details'),    #                          restrict_xpaths=('//li[@class="next_article"]')),    #         follow=True)    #    #    #提取「下一篇」鏈接並執行**處理**    #    #Rule(SgmlLinkExtractor(allow=('/u012150179/article/details')),    #    #     callback='parse_item',    #    #     follow=False),    #]     #rules編寫法二,更推薦的方式(自己測驗,使用法一時經常出現爬到中間就finish情況,並且無錯誤碼)    rules = [        Rule(SgmlLinkExtractor(allow=('/u012150179/article/details'),                              restrict_xpaths=('//li[@class="next_article"]')),             callback='parse_item',             follow=True)    ]     def parse_item(self, response):         print "parse_item>>>>>>"        item = CsdnblogcrawlspiderItem()        sel = Selector(response)        blog_url = str(response.url)        blog_name = sel.xpath('//div[@id="article_details"]/div/h1/span/a/text()').extract()         item['blog_name'] = [n.encode('utf-8') for n in blog_name]        item['blog_url'] = blog_url.encode('utf-8')         yield item

5.原理部分(以下部分,可以去原作者網站中學習)

1.CrawlSpider

(1)概念與作用:

它是Spider的派生類,首先在說下Spider,它是所有爬蟲的基類,對於它的設計原則是只爬取start_url列表中的網頁,而從爬取的網頁中獲取link並繼續爬取的工作CrawlSpider類更適合。

(2)使用:

它與Spider類的最大不同是多了一個rules參數,其作用是定義提取動作。在rules中包含一個或多個Rule對象,Rule類與CrawlSpider類都位於scrapy.contrib.spiders模組中。

  1. class scrapy.contrib.spiders.Rule (
  2. link_extractor, callback=None,cb_kwargs=None,follow=None,process_links=None,process_request=None )

link_extractor為LinkExtractor,用於定義需要提取的鏈接。

callback參數:當link_extractor獲取到鏈接時參數所指定的值作為回調函數。

 callback參數使用注意:

當編寫爬蟲規則時,請避免使用parse作為回調函數。於CrawlSpider使用parse方法來實現其邏輯,如果您覆蓋了parse方法,crawlspider將會運行失敗。

follow:指定了根據該規則從response提取的鏈接是否需要跟進。當callback為None,默認值為true。

process_links:主要用來過濾由link_extractor獲取到的鏈接。

process_request:主要用來過濾在rule中提取到的request。

2.LinkExtractor

(1)概念:

顧名思義,鏈接提取器。

(2) 作用:

response對象中獲取鏈接,並且該鏈接會被接下來爬取。

(3) 使用:

通過SmglLinkExtractor提取希望獲取的鏈接。

  1. classscrapy.contrib.linkextractors.sgml.SgmlLinkExtractor(
  2. allow=(),deny=(),allow_domains=(),deny_domains=(),deny_extensions=None,restrict_xpaths=(),tags=(『a』,『area』),attrs=(『href』),canonicalize=True,unique=True,process_value=None)

主要參數:

allow:滿足括弧中「正則表達式」的值會被提取,如果為空,則全部匹配。

deny:與這個正則表達式(或正則表達式列表)不匹配的URL一定不提取。

allow_domains:會被提取的鏈接的domains。

deny_domains:一定不會被提取鏈接的domains。

restrict_xpaths:使用xpath表達式,和allow共同作用過濾鏈接。

三.RUN!

shell中驗證

  1. 開始編寫程式碼之前,使用scrapyshell查看使用SmglLinkExtractor在網頁中獲取到的鏈接:
    1. scrapy shell http://blog.csdn.net/u012150179/article/details/11749017
  2. 繼續import相關模組:fromscrapy.contrib.linkextractors.sgml import SgmlLinkExtractor現在使用SgmlLinkExtractor查看在當前網頁中獲得的鏈接:
    1. item=SgmlLinkExtractor(allow=(『/u012150179/article/details』)).extract_links(response)

    其中item為包含Link()對象的列表,現在顯示其中的text元素(就是獲取到的文章鏈接對應的文章標題):

    1. for i in item:
    2. print i.text

    對照網頁可以得到此時獲取的是當前網頁中所有滿足allow條件的鏈接,不僅包含「下一篇」的鏈接,還有網頁側邊欄「閱讀排行「、」評論排行「中的文章鏈接。為了只獲得」下一篇「文章鏈接,這就要進行所有鏈接的篩選,引入參數restrict_xpaths,繼續:

    1. item= SgmlLinkExtractor(allow=(『/u012150179/article/details』),restrict_xpaths=(『//li[@class=」next_article」]』)).extract_links(response)

    這是在如上查看結果,便提取出了「下一篇」文章鏈接。注意:在shell中並不對提取到的link進行跟進。 在這裡不得不提的就是scrapy shell是對調試、驗證很有用的交互工具。應該掌握。 在shell中進行了驗證後進入寫程式碼階段。

原創文章,轉載請註明: 轉載自URl-team

本文鏈接地址: Scrapy筆記四 自動爬取網頁之使用CrawlSpider