scrapy學習筆記(有示例版)

scrapy學習筆記(有示例版)

我的博客

1.使用scrapy

ps:linux環(huán)境

安裝:sudo install Scrapy

1.1創(chuàng)建工程

$ scrapy startproject Spider
就創(chuàng)建屬于自己的項目
同時生成一個Spider目錄:

Spider
    |- scrapy.cfg                        項目部署文件
    |- Spider                     該項目的python模塊羡亩,可以在這里加入代碼
        |- __init__.py                 
        |- items.py                       主要是將爬取的非結構性的數(shù)據(jù)源提取結構性數(shù)據(jù)
        |- middlewares.py          
        |- pipelines.py                  將爬取的數(shù)據(jù)進行持久化存儲
        |-  __pycache__  
        |-  settings.py                  配置文件
        |-  spiders                       放置spider代碼的目錄
            |-  __init__.py 
            |-  __pycache__

1.2創(chuàng)建爬蟲模塊

import scrapy
class Spider(scrapy.Spider):                       #創(chuàng)建的Spider是繼承scrapy.Spider類
    name = "Spider"                                      #爬蟲的名稱(必須是項目里面唯一的)
    allowed_domain = ["xxx.com"]                #允許的域名(就是這個爬蟲爬取鏈接的范圍)
    start_urls = ["http://xxx.com/xxx/xxx"]     #開始爬取的鏈接
    
    def parse(self, response):                     
        pass

在spiders文件夾創(chuàng)建出這份代碼及刻,除了以上解釋外讥珍,里面的parse()是一個Spider方法腐宋,被調用時狸剃,每個初始url響應后返回的Response對象庆杜,將會作為唯一的參數(shù)傳遞給該方法梧兼。該方法負責解析返回的數(shù)據(jù)女仰,提取數(shù)據(jù)以及生成需要進一步處理的url的Responst對象

1.3網(wǎng)頁解析

創(chuàng)建完爬蟲模塊后就可以進行網(wǎng)頁解析了,Scrapy有自己的一套數(shù)據(jù)提取機制轧抗,成為選擇器(selector),它們通過特定的XPath或者CSS表達式來選擇HTML文件中的某個部分,Scrapy選擇器構建與lxml庫上瞬测,這意味著它們在速度和解析準確性上非常相似横媚。當然纠炮,也可以使用自己的,比如BeautifulSoup進行解析

Selector對象有四個基本的方法

  • xpath(query):傳入XPath表達式query灯蝴,返回該表達式所對應的所有節(jié)點的selector list列表
  • css(query):傳入CSS表達式query恢口,返回該表達式所對應的所有節(jié)點的selector list列表
  • extract(): 序列化該節(jié)點為Unicode字符串并返回list列表。
  • re(regex):根據(jù)傳入的正則表達式對數(shù)據(jù)進行提取穷躁,返回Unicode字符串列表耕肩。regex可以是一個已編譯的正則,也可以是一個將為re.compile(regex)編譯為正則表達式的字符串问潭。

在spider類的parse()方法中猿诸,其中一個參數(shù)是response。所以使用選擇器有兩種方法

  • 將response傳入Selector:Selector(response).xpath()
    Selector(response).xpath('//span/text()').extract()
    
  • 或者直接調用:response.xpath()
    response.xpath('//span/text()').extract()
    

Scrapy提供了一個簡便的方式來查看表達式是否正確
打開命令行窗口后輸入:
$ scrapy shell "http://xxx.com"
或者響應后
>>>response.xpath('//span/text()').extract()
就可以抽取出響應的數(shù)據(jù)了狡忙,返回的是Unicode格式

示例代碼中extract()是提取里面的文本梳虽,并返回一個 SelectorList實例
如果只想提取第一個匹配的元素,可以調用選擇器 .extract_first()灾茁,如果獲取不到則返回None
可以通過使用extract_first(default='xxx')來自定義返回數(shù)值

了解了這些后可以寫出一個parse()的代碼
假設這個網(wǎng)頁我們要提取的數(shù)據(jù)有標題窜觉,時間,評論北专,鏈接禀挫,且他們在網(wǎng)頁的xxx里面

def parse(self, response):
    papers = response.xpath(".//*[@class='xxx']") 
    for paper in papers:
        url = paper.xpath(".//*[@class='title']/a/@href").extract()[0]
        title = paper.xpath(".//*[@class='title']/a/text()").extract()[0]
        time = paper.xpath(".//*[@class='ttime']/a/text())".extract()[0]
        content = paper.xpath(".//*[@class='content']/a/text()").extract()[0]
        item = SpiderItem(url=url, title=title, time=time,title=title, content=content)
        yield item
        yield scrapy.Request(url=url, callnack=self.parse)

yield item是把所有獲得的數(shù)據(jù)封裝起來,存放在Spideritem
yield scrapy.Request(url=url, callnack=self.parse)則是把獲取到的url利用request對象構造為請求再利用callback回調到自己指定的Spideritem

1.4 item

Scrapy提供Item類。 Item對象是用于收集所抓取的數(shù)據(jù)的簡單容器拓颓。它們提供了一個類似字典的 API语婴,具有用于聲明其可用字段的方便的語法
在items.py文件輸入

class SpiderItem(scrapt.Item):
    url = scrapy.Field()
    time = scrapy.Field()
    title = scrapy.Field()
    content = scrapy.Field()

就創(chuàng)建好了,如果要拓展item就在原始item上來拓展item

class newSpiderItem(SpiderItem):
    xxx = scrapy.Field()

1.5Item Pipeline

當item在Spider中被手機后录粱,它將會傳遞到Item PipeLine腻格,利用Item PipeLine來進行數(shù)據(jù)保存
先上一個示例代碼

import json
from scrapy.exceptions import DropItem
class SpiderPipeline(object):
    def __init__(self):
        self.file = open('xxx.json','w')
    def process_item(self,item,spider):
        if item['title']:
            line = json.dumps(dict(item)) + "\n"
            self.file.write(line)
            return item
        else:
            raise DropItem("沒有找到標題"+title)

之后在setting.py的ITEM_PIPELINES變了中進行激活

ITEM_PIPELINES = {
       'Spider.pipelines.spiderPipeline':300}

process_item()方法可以用來判斷是來自于哪個爬蟲,item是被爬取對象啥繁,spider是爬取該item的Spider
Dropitem是一個錯誤捕獲
300是判斷運行順序菜职,范圍為0~1000

除此之外,Scrapy內置了一些簡單的存儲方式生成一個帶有爬取數(shù)據(jù)的輸出文件自帶的類型有:

  • JSON
  • JSON lines
  • CSV
  • XMl
  • Pickle
  • Marshal
    食用方法:將命令行切換到項目目錄旗闽,比如想保存為csv格式酬核,輸入命令:
    $ scrapy crawl Spider -o papers.csv
    就可以讓Spider采集到的數(shù)據(jù)保存為papers.csv文件了

1.6運行

$ scrapy crawl Spider

就可以運行爬蟲了,其中Spider就是我們定義的name
更過命令這里

也可以在spider.py文件添加一下代碼運行

if __name =='__main__':
    process = CrawlerProcess(get_project_settings())
    process.crawl('spider')
    process.start()

2.深入Scrapy

通過以上運行一個爬蟲肯定會覺得還不如自己寫代碼來爬蟲适室,但Scrapy框架還有很多厲害的地方

2.1Spider

2.1.1Spider

繼承于Spider是最簡單的spider嫡意,常用屬性為:

  • name
    定義此爬蟲名稱的字符串。爬蟲名稱是爬蟲如何由Scrapy定位(和實例化)捣辆,因此它必須是唯一的蔬螟。但是,沒有什么能阻止你實例化同一個爬蟲的多個實例汽畴。這是最重要的爬蟲屬性旧巾,它是必需的耸序。
  • allowed_domains
    允許此爬蟲抓取的域的字符串的可選列表,指定一個列表可以抓取鲁猩。
  • start_urls
    當沒有指定特定網(wǎng)址時坎怪,爬蟲將開始抓取的網(wǎng)址列表。
  • custom_settings
    運行此爬蟲時將從項目寬配置覆蓋的設置字典廓握。詳情在這里
  • crawler
    此屬性from_crawler()在初始化類后由類方法設置搅窿,并鏈接Crawler到此爬蟲實例綁定到的對象。
    Crawlers在項目中封裝了很多組件隙券,用于單個條目訪問(例如擴展男应,中間件,信號管理器等)
  • settings
    運行此爬蟲的配置是尔。
  • logger
    用Spider創(chuàng)建的Python記錄器name殉了。
  • start_requests()
    此方法必須返回一個可迭代對象,該方法只被調用一次拟枚。
    主要用于在啟動階段需要post登錄某個網(wǎng)站時才使用
    示例代碼:
    import scrapy
    class Spider(scrapy.Spider):                       #創(chuàng)建的Spider是繼承scrapy.Spider類
        name = "Spider"                                      #爬蟲的名稱(必須是項目里面唯一的)
        allowed_domain = ["xxx.com"]                #允許的域名(就是這個爬蟲爬取鏈接的范圍)
        def start_requests(self):
            return [scrapy.FromRequest("httP://www.xxx.com/login",
                                                                 formdata={'user':'xxx','pass':'xxx'},
                                                                 callback=self.login)]
        def login(self, response):
            pass
    

2.1.2CrawlSpidel

CrawlCpider除了從Spider繼承過來的屬性外薪铜,還提供了一個新的屬性rules,rules是一個包含一個或多個Rule對象的集合恩溅,每個Rule對爬取網(wǎng)站的動作定義了特定的規(guī)則隔箍。如果多個Rule匹配了相同的鏈接,則根據(jù)它們在rules屬性中被定義的順序脚乡,第一個會被使用蜒滩。
Rule類的原型為:

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

參數(shù)說明

link_extractor 是一個LinkExtractor對象,定義了如何從爬取到的頁面提取鏈接奶稠。
callback回調函數(shù)接受一個response作為一個參數(shù)俯艰,應避免使用parse作為回調函數(shù)
cb_kwargs包含傳遞給回調函數(shù)的參數(shù)的字典
follow是一個布爾值,指定了根據(jù)規(guī)則從respose提取的鏈接是否需要跟進
process_links是一個可調用的或一個字符串(在這種情況下锌订,將使用具有該名稱的爬蟲對象的方法)竹握,將使用指定從每個響應提取的每個鏈接列表調用該方法link_extractor。這主要用于過濾目的辆飘。
process_request 是一個可調用的或一個字符串(在這種情況下啦辐,將使用具有該名稱的爬蟲對象的方法),它將被此規(guī)則提取的每個請求調用蜈项,并且必須返回一個請求或無(過濾出請求)

link_extractor里面也大有乾坤芹关,參數(shù)有:

allow: 提取滿足正則表達式的鏈接
deny: 排除正則表達式匹配的鏈接,優(yōu)先級高于allow
allow_domains: 允許的域名紧卒,可以是str,list
deny_domains:排除的域名侥衬,同上
restrict_xpaths: 提取滿足xpath選擇條件的鏈接,可以是str,list
restrict_css: 提取滿足css選擇條件的鏈接,可以是str,list
tags: 提取指定標記下的鏈接轴总,默認從a和area中提取贬媒,可以是str或list。
attrs: 提取滿足擁有屬性的鏈接肘习,默認為href,類型為list
unique:鏈接是否去重坡倔,類型為boolean
process_value: 值處理函數(shù)(這個函數(shù)是對已經(jīng)捕獲的函數(shù)進行修補)
以上詳細在這里
關于process_value可以看這兩個函數(shù)示例(來自于stackoverflow):

import scrapy
from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors import LinkExtractor

class dmozItem(scrapy.Item):
    basic_url = scrapy.Field()

class dmozSpider(CrawlSpider):
    name = "dmoz"
    allowed_domains = ["scrapy.org"]
    start_urls = [
        "http://scrapy.org/",
    ]

    def clean_url(value):
        return value.replace('/../', '/')

    rules = (
        Rule(
            LinkExtractor(
                allow=('\S+/'),
                restrict_xpaths=(['.//ul[@class="navigation"]/a[1]',
                                  './/ul[@class="navigation"]/a[2]',
                                  './/ul[@class="navigation"]/a[3]',
                                  './/ul[@class="navigation"]/a[4]',
                                  './/ul[@class="navigation"]/a[5]']),
                process_value=clean_url
            ),
            callback='first_level'),
    )

    def first_level(self, response):
        taco = dmozItem()
        taco['basic_url'] = response.url
        return taco
def process_value(value):
    unique_id = re.search(r"/item/(\d+)", value).group(1)
    if unique_id in already_crawled_site_ids:
        return None
    return value

rules = [Rule(SgmlLinkExtractor(allow=['/item/\d+']), 'parse_item', process_value=process_value)]

2.1.3 XMLFeedSpider

XMLFeedSpider設計用于通過以特定節(jié)點名稱迭代XML訂閱源來解析XML訂閱源漂佩。迭代器可以選自:iternodes,xml和html罪塔。iternodes為了性能原因投蝉,建議使用迭代器,因為xml和迭代器html一次生成整個DOM為了解析它征堪。但是瘩缆,html當使用壞標記解析XML時,使用作為迭代器可能很有用佃蚜。

要設置迭代器和標記名稱庸娱,必須定義以下類屬性:

  • iterator
    定義要使用的迭代器的字符串。它可以是:

    • 'iternodes' - 基于正則表達式的快速迭代器
    • 'html'- 使用的迭代器Selector熟尉。請記住,這使用DOM解析洲脂,并且必須加載所有DOM在內存中斤儿,這可能是一個大飼料的問題
    • 'xml'- 使用的迭代器Selector。請記住恐锦,這使用DOM解析往果,并且必須加載所有DOM在內存中,這可能是一個大飼料的問題
      它默認為:'iternodes'一铅。
  • itertag
    一個具有要迭代的節(jié)點(或元素)的名稱的字符串陕贮。示例:
    itertag = 'product'

  • namespaces
    定義該文檔中將使用此爬蟲處理的命名空間的元組列表。在 與將用于自動注冊使用的命名空間 的方法馅闽。(prefix, uri)prefixuriregister_namespace()
    示例代碼:

    class YourSpider(XMLFeedSpider):
    
        namespaces = [('n', 'http://www.sitemaps.org/schemas/sitemap/0.9')]
        itertag = 'n:url'
    
  • adapt_response(response)
    一種在爬蟲開始解析響應之前飘蚯,在響應從爬蟲中間件到達時立即接收的方法。它可以用于在解析之前修改響應主體福也。此方法接收響應并返回響應(它可以是相同的或另一個)局骤。

  • parse_node(response, selector)
    對于與提供的標記名稱(itertag)匹配的節(jié)點,將調用此方法暴凑。接收Selector每個節(jié)點的響應和 峦甩。覆蓋此方法是必需的。否則,你的爬蟲將不工作凯傲。此方法必須返回一個Item對象犬辰,一個 Request對象或包含任何對象的迭代器。

  • process_results(response, results)
    對于由爬蟲返回的每個結果(Items or Requests)冰单,將調用此方法幌缝,并且它將在將結果返回到框架核心之前執(zhí)行所需的任何最后處理,例如設置項目ID诫欠。它接收結果列表和產(chǎn)生那些結果的響應涵卵。它必須返回結果列表

2.2 Item Loader

Item Loader提供了一種便捷的方式填充抓取到的items。雖然items可以使用自帶的類字典形式API填充荒叼,但是itemsLoader提供了更便捷的API可以分析原始數(shù)據(jù)并對item進行賦值轿偎。也就是Items提供保存捉取數(shù)據(jù)的容器,而Item Loader提供的是填充容器的機制被廓,且可以方便的被拓展坏晦,重寫不同字段的解析規(guī)則,這對大型的爬蟲項目后期維護非常有利嫁乘,拓展新的功能更加方便昆婿。
以下是Item和Item Loader的對比代碼:

class SpiderItem(scrapt.Item):
    url = scrapy.Field()
    time = scrapy.Field()
    title = scrapy.Field()
    content = scrapy.Field()
def parse(self, response):
    i = ItemLoader(item=Product(), response=response)
    l.add_xpath('title', '//div[@class="title1"]')
    l.add_xpath('title', '//div[@class="title2"]')
    l.add_xpath('time', '//div[@class="time"]')
    l.add_xpath('content', '//div[@class="content"]')
    return l.load_item()

可以發(fā)現(xiàn)的是ItemsLoader里面的name字段可以從頁面中兩個不同的XPAth位置提取,之后分配給name字段亦渗。下面類似操作后把所有數(shù)據(jù)收集起來挖诸,再使用l.load_item將數(shù)據(jù)實際填充到Item中

2.2.1 輸入與輸出處理器

Item Loder實現(xiàn)數(shù)據(jù)的收集處理和填充的功能都是通過輸入與輸出處理器來實現(xiàn)的,他們的功能是:

  • Item Loder在每個字段中都包含了一個輸入處理器和輸出處理器
  • 輸入處理器收到response后時立刻通過add_xpath(),add_css()或者add_value()等方法提取數(shù)據(jù)法精,經(jīng)過輸入處理器的結果被手機起來并且保存在Item Loder內多律,
  • 收集到所有的數(shù)據(jù)后,調用Item Loder.load_item()方法來填充并返回item對象搂蜓。load_item()方法內部先調用輸出處理器來處理收集到的數(shù)據(jù)狼荞,最后把結果存入Item中。

下面是2個栗子:

from scrapy.loader import ItemLoader
from scrapy.loader.processors import TakeFirst, MapCompose, Join

class ProductLoader(ItemLoader):

    default_output_processor = TakeFirst()

    name_in = MapCompose(unicode.title)
    name_out = Join()

    price_in = MapCompose(unicode.strip)

    # ...

可以看到帮碰,輸入處理器使用_in后綴聲明相味,而輸出處理器使用_out后綴聲明。您還可以使用ItemLoader.default_input_processor和 ItemLoader.default_output_processor屬性聲明默認輸入/輸出 處理器殉挽。
輸入和輸出處理器可以在Item Loader定義中聲明丰涉,這種方式聲明輸入處理器是很常見的。但是斯碌,還可以在item中聲明:

import scrapy
from scrapy.loader.processors import Join, MapCompose, TakeFirst
from w3lib.html import remove_tags

def filter_price(value):
    if value.isdigit():
        return value

class Product(scrapy.Item):
    name = scrapy.Field(
        input_processor=MapCompose(remove_tags),
        output_processor=Join(),
    )
    price = scrapy.Field(
        input_processor=MapCompose(remove_tags, filter_price),
        output_processor=TakeFirst(),
    )

以上說了三種處理器聲明方式:

  • ItemLoader類中聲明類似field_in和field_out的屬性
  • itemd 的字段中聲明
  • ItemLoader默認處理器ItemLoader.default_input_processor和 ItemLoader.default_output_processor
    這三種方式響應優(yōu)先級是從上到下依次遞減

2.2.2 Item Loader Context

所有輸入和輸出處理器之間共享的任意鍵/值的dict一死。它可以在聲明,實例化或使用Item Loader時傳遞傻唾。它們用于修改輸入/輸出處理器的行為投慈。

例如承耿,假設有一個parse_length接收文本值并從中提取長度的函數(shù):

def  parse_length (text , loader_context ):
    unit  =  loader_context 伪煤。get ('unit' 加袋, 'm' )
    #...長度解析代碼在這里... 
    return  parsed_length

通過接受一個loader_context參數(shù),該函數(shù)顯式地告訴Item Loader它能夠接收一個Item Loader上下文抱既,因此Item Loader在調用它時傳遞當前活動的上下文职烧,因此處理器功能(parse_length在這種情況下)可以使用它們。
有幾種方法可以修改Item Loader上下文值:

  • 通過修改當前活動的Item Loader上下文(context屬性):
    loader = ItemLoader(product)
    loader.context['unit'] = 'cm'
    
  • On Item Loader實例化(Item Loader構造函數(shù)的關鍵字參數(shù)存儲在Item Loader上下文中):
    loader = ItemLoader(product, unit='cm')
    
  • On Item Loader聲明防泵,對于那些支持使用Item Loader上下文實例化的輸入/輸出處理器阳堕。MapCompose是其中之一:
    class ProductLoader(ItemLoader):
        length_out = MapCompose(parse_length, unit='cm')
    

2.2.3 重用和拓展 Item Loader

隨著你的項目越來越大,越來越多的爬蟲择克,維護成為一個根本的問題,特別是當你必須處理每個爬蟲的許多不同的解析規(guī)則前普,有很多異常肚邢,但也想重用公共處理器。

項目加載器旨在減輕解析規(guī)則的維護負擔拭卿,同時不會失去靈活性骡湖,同時提供了擴展和覆蓋它們的方便的機制。因此峻厚,項目加載器支持傳統(tǒng)的python類繼承响蕴,以處理特定爬蟲(或爬蟲組)的差異。

例如惠桃,假設某個特定站點以三個短劃線(例如)包含其產(chǎn)品名稱浦夷,并且您不希望最終在最終產(chǎn)品名稱中刪除那些破折號」纪酰—Plasma TV—

以下是如何通過重用和擴展默認產(chǎn)品項目Loader(ProductLoader)來刪除這些破折號:

from scrapy.loader.processors import MapCompose
from myproject.ItemLoaders import ProductLoader

def strip_dashes(x):
    return x.strip('-')

class SiteSpecificLoader(ProductLoader):
    name_in = MapCompose(strip_dashes, ProductLoader.name_in)

另一種擴展項目加載器可能非常有用的情況是劈狐,當您有多種源格式,例如XML和HTML呐馆。在XML版本中肥缔,您可能想要刪除CDATA事件。下面是一個如何做的例子:

from scrapy.loader.processors import MapCompose
from myproject.ItemLoaders import ProductLoader
from myproject.utils.xml import remove_cdata

class XmlProductLoader(ProductLoader):
    name_in = MapCompose(remove_cdata, ProductLoader.name_in)

對于輸出處理器汹来,更常用的方式是在item字段元數(shù)據(jù)里聲明续膳,因為通常它們依賴于具體的字段而不是網(wǎng)站

2.2.4 內置的處理器

除了可以使用可調用的函數(shù)作為輸入輸出處理器,Scrapy提供了一些常用的處理器收班,下面是一些內置的處理器

  • Identity
    類原型: class scrapy.loader.processors.Identity
    最簡單的處理器坟岔,不進行任何處理,直接返回原來的數(shù)據(jù),無參數(shù)
  • TakeFirst
    類原型: class scrapy.loader.processors.TakeFirst
    從接收到的值中返回第一個非空值/非空值闺阱,因此它通常用作單值字段的輸出處理器炮车。它不接收任何構造函數(shù)參數(shù),也不接受Loader上下文
    >>> from scrapy.loader.processors import TakeFirst
    >>> proc = TakeFirst()
    >>> proc(['', 'one', 'two', 'three'])
    'one'
    
  • Join
    類原型: class scrapy.loader.processors.Join(separator=u'')
    返回用分隔符separatoe連續(xù)后的值,分隔符seeparator默認為空格瘦穆。不接受Loader contexts纪隙。當使用默認分隔符的時候,這個處理器等同于Python字符串對象中join方法:''.join
    >>> from scrapy.loader.processors import Join
    >>> proc = Join()
    >>> proc(['one', 'two', 'three'])
    u'one two three'
    >>> proc = Join('<br>')
    >>> proc(['one', 'two', 'three'])
    u'one<br>two<br>three'
    
  • Compose
    類原型: class scrapy.loader.processors.Compose(functions,*default_loader_context)
    由給定函數(shù)的組合構成的處理器扛或。這意味著該處理器的每個輸入值都被傳遞給第一個函數(shù)绵咱,并且該函數(shù)的結果被傳遞給第二個函數(shù),依此類推熙兔,直到最后一個函數(shù)返回該處理器的輸出值悲伶。
    默認情況下,停止進程None值住涉◆镲保可以通過傳遞關鍵字參數(shù)來更改此行為stop_on_none=False
    >>> from scrapy.loader.processors import Compose
    >>> proc = Compose(lambda v: v[0], str.upper)
    >>> proc(['hello', 'world'])
    'HELLO'
    
  • MapCompose
    類原型: class scrapy.loader.processors.MapCompose(functions,*default_loader_context)
    和Compose類似,也是用給定的多個方法的組合來構造處理器舆声,不同的是內部結果在方法見傳遞的方式:
    • 該處理器的輸入值被迭代花沉,并且第一函數(shù)被應用于每個元素。這些函數(shù)調用的結果(每個元素一個)被連接以構造新的迭代媳握,然后用于應用第二個函數(shù)碱屁,等等,直到最后一個函數(shù)被應用于收集的值列表的每個值遠蛾找。最后一個函數(shù)的輸出值被連接在一起以產(chǎn)生該處理器的輸出娩脾。
    • 每個特定函數(shù)可以返回值或值列表,這些值通過應用于其他輸入值的相同函數(shù)返回的值列表展平打毛。函數(shù)也可以返回None柿赊,在這種情況下,該函數(shù)的輸出將被忽略幻枉,以便在鏈上進行進一步處理闹瞧。
    • 此處理器提供了一種方便的方法來組合只使用單個值(而不是iterables)的函數(shù)。由于這個原因展辞, MapCompose處理器通常用作輸入處理器奥邮,因為數(shù)據(jù)通常使用選擇器的 extract()方法提取,選擇器返回unicode字符串的列表罗珍。
    >>> def filter_world(x):
    ...     return None if x == 'world' else x
    ...
    >>> from scrapy.loader.processors import MapCompose
    >>> proc = MapCompose(filter_world, unicode.upper)
    >>> proc([u'hello', u'world', u'this', u'is', u'scrapy'])
    [u'HELLO, u'THIS', u'IS', u'SCRAPY']
    
  • SelectJmes
    類原型: class scrapy.loader.processors.SelectJmes(json_path)
    使用提供給構造函數(shù)的json路徑查詢值洽腺,并返回輸出。需要運行jmespath覆旱。該處理器一次只需要一個輸入蘸朋。
    >>> from scrapy.loader.processors import SelectJmes, Compose, MapCompose
    >>> proc = SelectJmes("foo") #for direct use on lists and dictionaries
    >>> proc({'foo': 'bar'})
    'bar'
    >>> proc({'foo': {'bar': 'baz'}})
    {'bar': 'baz'}
    
    和json一起使用
    
    >>> import json
    >>> proc_single_json_str = Compose(json.loads, SelectJmes("foo"))
    >>> proc_single_json_str('{"foo": "bar"}')
    u'bar'
    >>> proc_json_list = Compose(json.loads, MapCompose(SelectJmes('foo')))
    >>> proc_json_list('[{"foo":"bar"}, {"baz":"tar"}]')
    [u'bar']
    

2.3 Item Pipeline

前面已經(jīng)說了Item Pipeline的基本用法了,現(xiàn)在看的是如何利用item Pipeline來進行數(shù)據(jù)存儲

2.3.1內置圖片和文件下載

item Pipeline提供了一些可以重用的Pipeline扣唱,其中有filesPipeline和imagesPipeline藕坯,他們都實現(xiàn)了以下特性:

  • 避免重新下載最近已經(jīng)下載過的數(shù)據(jù)
  • 指定存儲的位置和方式

此外团南,imagesPipeline還提供了二位的特性:

  • 將所有下載的圖片轉換成通用的格式(jpg)和模式(rgb)
  • 粗略圖生成
  • 檢測圖像的寬/高,確保他們滿足最小限制

使用FIlesPipeline方法如下:
1)在setting.py的ITEM_PIPELINES中添加一條'scrapy.pipelines.files.FilesPipeline':1
2)在item中添加兩個字段炼彪,比如:
file_urls = scrapy.Field()
files = scrapy.Field()
3)在setting.py文件中添加下載路徑吐根,文件url所在的item字段,和文件結果信息所在item字段辐马,比如:
FILES_STORE = '/HOME/XXX/SPIDER'
FILES_URLS_FIELD ='file_urls'
FILES_RESULT_FIELD = 'files'
使用files_expires設置文件過期時間拷橘,示例如下:
FILES_EXPIRES = 30 #30天過期

使用ImagesPIpeline方法如下:
1)在setting.py的ITEM_PIPELINES中添加一條'scrapy.pipelines.images.ImagesPipeline':1
2)在item中添加兩個字段,比如:
image_urls = scrapy.Field()
images = scrapy.Field()
3 )在setting.py文件中添加下載路徑喜爷,文件url所在的item字段冗疮,和文件結果信息所在item字段,比如:
IMAGES_STORE = '/HOME/XXX/SPIDER'
IMAGES_URLS_FIELD ='file_urls'
IMAGES_RESULT_FIELD = 'files'
除此之外檩帐,使用IMAGES_THUMS制作縮略圖术幔,并這是縮略圖尺寸大小,并使用IMAGES_EXPIRES設置文件過期時間湃密,示例如下:
IMAGES_THUMBS = {
'small':(50, 50),
'big': (270,270),
}
IMAGES_EXPIRES = 30 #30天過期

除此之外特愿,Item Pipeline還有三個方法非常常用

  • open_spider(self, spider)
    當spider被開啟時,這個方法被調用
  • close_spider(self, spider)
    當spider被關閉是勾缭,這個方法被調用
  • from_crawler(cls, crawler)
    這個類方法從Crawles屬性中創(chuàng)建一個pipeline實例,Crawle對象能夠接觸所有Scrapy的核心組件目养,比如setting

以下是一個存儲到MongoDB的示例代碼:

import pymongo



class ZhihuspiderPipeline(object):

    def __init__(self, mongo_url, mongo_db):
        self.mongo_url = mongo_url
        self.mongo_db = mongo_db

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            mongo_url=crawler.settings.get('MONGO_URL'),
            mongo_db=crawler.settings.get('MONGO_DATABASE', 'items')
        )

    def open_spider(self, spider):
        self.client = pymongo.MongoClient(self.mongo_url)
        self.db = self.client[self.mongo_db]

    def close_spider(self, spider):
        self.client.close()
    
    def process_item(self, item, spider):
        self.db.UserInfo.insert(dict(item))
        return item

代碼中首先通過from_crawler方法俩由,獲取setting中的MongoDB的URL和數(shù)據(jù)庫名稱,從而創(chuàng)建一個MongoPIpeline實例,在SPider開始運行是,在open_spider方法中建立數(shù)據(jù)庫連接趟径,當Spider關閉是俄周,在close_spider方法中關閉數(shù)據(jù)庫連接。
當是想括,這里配置的Pipeline會作用于所有的Spider,假如項目中有很多Spider在運行,處理起來就會很麻煩煞躬。所以通過process_item(self,item,spider)中的SPider參數(shù)判斷是來自于哪個爬蟲,不過還有更好的方法:
就是配置SPider類中的suctom_settings對象逸邦,為每一個Spider配置不同的pipeline

class MySpider(CrawlSpider):
    custom_settings = {
        'ITEM_PIPELINES':{
            'test.pipelines.TestPipeline.TestPipeline':1,
        }
    }

2.4 請求與響應

在編寫Spider的模塊中接觸最緊密的是請求和響應恩沛。

2.4.1Request對象

一個Request對象代表著一個HTTP請求,通常在Spider類中產(chǎn)生缕减,然后傳遞給下載器雷客,最后返回一個響應
類原型:class scrapy.http.Request(url[, callback, method='GET', headers, body, cookies, meta, encoding='utf-8', priority=0, dont_filter=False, errback])
構造參數(shù)說明:

  • url(string) - 此請求的網(wǎng)址
  • callback(callable) - 將使用此請求的響應(一旦下載)作為其第一個參數(shù)調用的函數(shù)。如果請求沒有指定回調桥狡,parse()將使用spider的 方法搅裙。請注意皱卓,如果在處理期間引發(fā)異常,則會調用errback部逮。
  • method(string) - 此請求的HTTP方法娜汁。默認為’GET’。
  • meta(dict) - 屬性的初始值Request.meta甥啄。如果給定存炮,在此參數(shù)中傳遞的dict將被淺復制。
  • body(str或unicode) - 請求體蜈漓。如果unicode傳遞了a穆桂,那么它被編碼為 str使用傳遞的編碼(默認為utf-8)。- 如果 body沒有給出融虽,則存儲一個空字符串享完。不管這個參數(shù)的類型,存儲的最終值將是一個str(不會是unicode或None)有额。
  • headers(dict) - 這個請求的頭般又。dict值可以是字符串(對于單值標頭)或列表(對于多值標頭)。如果 None作為值傳遞巍佑,則不會發(fā)送HTTP頭茴迁。
  • cookie(dict或list) - 請求cookie。這些可以以兩種形式發(fā)送萤衰。
  • encoding(string) - 此請求的編碼(默認為’utf-8’)堕义。此編碼將用于對URL進行百分比編碼,并將正文轉換為str(如果給定unicode)脆栋。
  • priority(int) - 此請求的優(yōu)先級(默認為0)倦卖。調度器使用優(yōu)先級來定義用于處理請求的順序。具有較高優(yōu)先級值的請求將較早執(zhí)行椿争。允許負值以指示相對低優(yōu)先級怕膛。
  • dont_filter(boolean) - 表示此請求不應由調度程序過濾。當您想要多次執(zhí)行相同的請求時忽略重復過濾器時使用秦踪。小心使用它褐捻,或者你會進入爬行循環(huán)。默認為False椅邓。
  • errback(callable) - 如果在處理請求時引發(fā)任何異常舍扰,將調用的函數(shù)。這包括失敗的404 HTTP錯誤等頁面希坚。

cookies參數(shù)設置的兩種方法
使用字典

request_with_cookies = Request(url="http://www.example.com",
                            cookies={'currency': 'USD', 'country': 'UY'})

使用字典列表發(fā)送

request_with_cookies = Request(url="http://www.example.com",
                              cookies=[{'name': 'currency',
                                       'value': 'USD',
                                       'domain': 'example.com',
                                       'path': '/currency'}]) 

當某些網(wǎng)站返回Cookie(在響應中)時边苹,這些Cookie會存儲在該域的Cookie中,并在將來的請求中再次發(fā)送裁僧。這是任何常規(guī)網(wǎng)絡瀏覽器的典型行為个束。但是慕购,如果由于某種原因,想要避免與現(xiàn)有Cookie合并茬底,可以設置Requ.meta中dont_merge_cookies字段的值沪悲。示例如下

request_with_cookies = Request(url="http://www.example.com",
                              cookies={'currency': 'USD', 'country': 'UY'},
                              meta={'dont_merge_cookies': True})

errback的使用方法示例:

import scrapy

from scrapy.spidermiddlewares.httperror import HttpError
from twisted.internet.error import DNSLookupError
from twisted.internet.error import TimeoutError, TCPTimedOutError

class ErrbackSpider(scrapy.Spider):
   name = "errback_example"
   start_urls = [
       "http://www.httpbin.org/",              # HTTP 200 expected
       "http://www.httpbin.org/status/404",    # Not found error
       "http://www.httpbin.org/status/500",    # server issue
       "http://www.httpbin.org:12345/",        # non-responding host, timeout expected
       "http://www.httphttpbinbin.org/",       # DNS error expected
   ]

   def start_requests(self):
       for u in self.start_urls:
           yield scrapy.Request(u, callback=self.parse_httpbin,
                                   errback=self.errback_httpbin,
                                   dont_filter=True)

   def parse_httpbin(self, response):
       self.logger.info('Got successful response from {}'.format(response.url))
       # do something useful here...

   def errback_httpbin(self, failure):
       # log all failures
       self.logger.error(repr(failure))

       # in case you want to do something special for some errors,
       # you may need the failure's type:

       if failure.check(HttpError):
           # these exceptions come from HttpError spider middleware
           # you can get the non-200 response
           response = failure.value.response
           self.logger.error('HttpError on %s', response.url)

       elif failure.check(DNSLookupError):
           # this is the original request
           request = failure.request
           self.logger.error('DNSLookupError on %s', request.url)

       elif failure.check(TimeoutError, TCPTimedOutError):
           request = failure.request
           self.logger.error('TimeoutError on %s', request.url)

下面寫的是Request的子類 FormRquest類,專門用來處理html表單阱表,尤其對隱藏表單的處理非常方便殿如,適合用來完成登錄操作
類原型:class scrapy.http.FormRequest(url[, formdata, ...])
其中構造參數(shù)formdata可以是字典,也可以是可迭代的(key,value)元祖最爬,代表著需要提交的表單數(shù)據(jù)涉馁。
示例如下:

return [FormRequest(url="http://www.example.com/post/action",
                    formdata={'name': 'John Doe', 'age': '27'},
                    callback=self.after_post)]

通常網(wǎng)站通過<input type="hidden">實現(xiàn)對某些表單字段的預填充,就像知乎的隱藏表單的_xfv數(shù)值爱致,Scray在FromRequest類提供了一個類方法from_reponse來解決隱藏表單這個問題烤送。方法原型如下:

classmethod from_response(response[, formname=None, formid=None, formnumber=0, formdata=None, formxpath=None, formcss=None, clickdata=None, dont_click=False, ...])

參數(shù)說明:

  • response(Responseobject) - 包含將用于預填充表單字段的HTML表單的響應
  • formname(string) - 如果給定,將使用name屬性設置為此值的形式糠悯。
  • formid(string) - 如果給定帮坚,將使用id屬性設置為此值的形式。
  • formxpath(string) - 如果給定互艾,將使用匹配xpath的第一個表單试和。
  • formcss(string) - 如果給定,將使用匹配css選擇器的第一個形式纫普。
  • formnumber(integer) - 當響應包含多個表單時要使用的表單的數(shù)量阅悍。第一個(也是默認)是0。
  • formdata(dict) - 要在表單數(shù)據(jù)中覆蓋的字段局嘁。如果響應元素中已存在字段,則其值將被在此參數(shù)中傳遞的值覆蓋晦墙。
  • clickdata(dict) - 查找控件被點擊的屬性悦昵。如果沒有提供,表單數(shù)據(jù)將被提交晌畅,模擬第一個可點擊元素的點擊但指。除了html屬性,控件可以通過其相對于表單中其他提交表輸入的基于零的索引抗楔,通過nr屬性來標識棋凳。
  • dont_click(boolean) - 如果為True,表單數(shù)據(jù)將在不點擊任何元素的情況下提交连躏。

下面是一個實現(xiàn)登錄功能的示例代碼:

import scrapy

class LoginSpider(scrapy.Spider):
    name = 'example.com'
    start_urls = ['http://www.example.com/users/login.php']

    def parse(self, response):
        return scrapy.FormRequest.from_response(
            response,
            formdata={'username': 'john', 'password': 'secret'},
            callback=self.after_login
        )

    def after_login(self, response):
        # check login succeed before going on
        if "authentication failed" in response.body:
            self.logger.error("Login failed")
            return

2.4.2 Response對象

Response對象代表著HTTP響應剩岳,Response通常是從下載器獲取然后交給Spider處理:
類原型:class scrapy.http.Response(url[, status=200, headers=None, body=b'', flags=None, request=None])
構造參數(shù)說明:

  • url(string) - 此響應的URL
  • status(integer) - 響應的HTTP狀態(tài)。默認為200入热。
  • headers(dict) - 這個響應的頭拍棕。dict值可以是字符串(對于單值標頭)或列表(對于多值標頭)晓铆。
  • body(str) - 響應體。它必須是str绰播,而不是unicode骄噪,除非你使用一個編碼感知響應子類,如 TextResponse蠢箩。
  • flags(list) - 是一個包含屬性初始值的 Response.flags列表链蕊。如果給定,列表將被淺復制谬泌。
  • request(Requestobject) - 屬性的初始值Response.request滔韵。這代表Request生成此響應。
  • meta(dict):用來初始化Response.meta

關于參數(shù)的其他補充:

  • request
    Request生成此響應的對象呵萨。在響應和請求通過所有下載中間件后奏属,此屬性在Scrapy引擎中分配。特別地潮峦,這意味著:
    HTTP重定向將導致將原始請求(重定向之前的URL)分配給重定向響應(重定向后具有最終URL)囱皿。
    Response.request.url并不總是等于Response.url
    此屬性僅在爬蟲程序代碼和 Spider Middleware中可用,但不能在Downloader Middleware中使用(盡管您有通過其他方式可用的請求)和處理程序response_downloaded忱嘹。
  • meta
    的快捷方式Request.meta的屬性 Response.request對象(即self.request.meta)嘱腥。
    與Response.request屬性不同,Response.meta 屬性沿重定向和重試傳播拘悦,因此您將獲得Request.meta從您的爬蟲發(fā)送的原始屬性齿兔。
    也可以看看
    Request.meta 屬性
  • flags
    包含此響應的標志的列表。標志是用于標記響應的標簽础米。例如:’cached’分苇,’redirected ‘等等。它們顯示在Response(_ str_ 方法)的字符串表示上屁桑,它被引擎用于日志記錄医寿。
  • copy()
    返回一個新的響應,它是此響應的副本蘑斧。
  • replace([ url靖秩,status,headers竖瘾,body沟突,request,flags捕传,cls ] )
    返回具有相同成員的Response對象惠拭,但通過指定的任何關鍵字參數(shù)賦予新值的成員除外。該屬性Response.meta是默認復制庸论。
  • urljoin(url )
    通過將響應url與可能的相對URL 組合構造絕對url求橄。
    這是一個包裝在urlparse.urljoin今野,它只是一個別名,使這個調用:
    urlparse.urljoin(response.url, url)

同樣的罐农,Response有一個子類TextResponse,多了一個智能編碼的功能条霜。
類原型:class scrapy.http.TextResponse(url[, encoding[, ...]])
構造參數(shù)encoding是一個包含編碼的字符串,如果使用一個unicode編碼的body構造出TextResponse實例涵亏,那body屬性會使用encoding進行編碼宰睡。
TextResponse類除了具有Response屬性,還擁有自己的屬性:

  • encoding:包含編碼的字符串气筋。編碼的優(yōu)先級由高到低如下所示:
    1)首先選用構造器中傳入的encoding
    2)選用http頭中Content-Type字段的編碼拆内。如果編碼無效,則被忽略宠默,繼續(xù)嘗試下面的規(guī)則
    3)選用響應body中的編碼
    4)最后猜測響應的編碼麸恍,這種方式是比較脆弱
  • selector:以當前響應為目標的選擇器實例。
    TextResponse類除了支持Response中的方法搀矫,還支持以下方法response
  • body_as_unicode():返回unicode編碼的響應body內容抹沪。等價于:
    response.body.decode(response.encoding)
  • xpath(query):等價于TextResponse.selector.xpath(query).示例如下:
    response.xpath('//p')
  • css(query):等價于TextResponse.selector.css(query).示例如下:
    response.css('//p')

2.5下載器中間件

下載器中間件是介于Scrapy的request/response處理的鉤子框架,是用于全局修改Scrapy的request和response瓤球,可以幫助我們定制自己的爬蟲系統(tǒng)
激活哦下載器中間件的方法如下
在setting.py里面的DOWNLOADER_MIDDLEWARES修改融欧,示例如下:
DOWNLOADER_MIDDLEWARES = {
‘myproject.middlewares.CustomDownloaderMiddleware': 543,
}
后面數(shù)值的設置要看自己的需求,越接近0越靠近引擎卦羡,越接近1000越靠近下載器噪馏,數(shù)字設置一般看自己需要先用到哪些中間件,就把數(shù)字設定得比哪個中間件大
中間件組建定義了以下python類绿饵,可以根據(jù)這些類來編寫自己的中間件

  • process_request(request,spider)
  • process_response(request,response,spider)
  • process_exception(request,exception,spider)

2.5.1process_request(request,spider)

當每個request通過下載中間件時欠肾,該方法被調用,返回值必須為none拟赊,response對象刺桃,request對象中的一個或raise IgnoreRequest異常
參數(shù)說明:
Request:處理的request
Spider:該Request對應的Spider
返回值:如果返回None,Scrapy將繼續(xù)處理該Request,執(zhí)行其他中間件的相應方法要门,直到合適的下載器處理函數(shù)被調用虏肾,該Request被執(zhí)行(其Response下載)
如果返回Response對象廓啊,SCrapy不會調用下面2個方法欢搜,或相應的下載方法,將返回該response谴轮。已安裝的中間件的process_response()方法則會在每個respon返回時被調用
如果返回request對象炒瘟,Scrapy則停止調用process_request方法并重新調度放回的Request。當新返回的Request被執(zhí)行后第步,相應地中間件鏈將會根據(jù)下載的Response被調用
如果是Raise IgnoreRequest異常疮装,則安裝的下載中間件的process_exception()方法會被調用缘琅。如果沒有任何一個方法處理該異常,則Request的errback方法會被調用廓推。如果沒有代碼處理拋出的異常刷袍,則該異常被忽略且不記錄

2.5.2process_request(request,response,spider)

該方法主要用來處理產(chǎn)生的Response返回值必須為none,response對象樊展,request對象中的一個或raise IgnoreRequest異常
參數(shù)說明:
Request:處理的request
response:處理的response
Spider:該Request對應的Spider
返回值:
如果返回Response對象呻纹,可以與傳入的respon相同,也可以是新的對象专缠,該Response會被鏈中的其他中間見的process_reponse()方法處理
如果返回request對象雷酪,Scrapy則停止調用process_request方法并重新調度放回的Request。當新返回的Request被執(zhí)行后涝婉,相應地中間件鏈將會根據(jù)下載的Response被調用
如果是Raise IgnoreRequest異常哥力,則安裝的下載中間件的process_exception()方法會被調用。如果沒有任何一個方法處理該異常墩弯,則Request的errback方法會被調用吩跋。如果沒有代碼處理拋出的異常,則該異常被忽略且不記錄

2.5.3process_request(request,exceptionmspider)

當下載處理器或process_request()拋出異常最住,比如IgnoreRequest異常時钞澳,Scrapy調用process_exception().process_exception()應該返回none,response對象涨缚,request對象中的一個
參數(shù)說明:
Request:處理的request
exception:拋出的異常
Spider:該Request對應的Spider
返回值:
如果返回None,Scrapy將會繼續(xù)處理該異常轧粟,接著調用已安裝的其他中間件的process_exception()方法,知道所有中間件都被調用完畢脓魏,則調用默認的異常處理
如果返回response對象兰吟,則已安裝的中間級鏈的process_response()方法被調用。Scrapy將不會調用任何其他中間件的process_exception()方法
如果返回Request對象茂翔,則返回的request將會被重新調用下載混蔼,這將停止中間級的process_exception()方法執(zhí)行,類似于返回respon對象的處理

下面是自定義下載器中間件的兩個栗子:

設置User-Agent字段珊燎,需要自己在setting,py中設置User-Agent列表

class RandomUserAgent(object):
    def __init__(self,agents):
        self.agents =agents
        
    @classmethod
    def from_crawler(cls,crawler):
        return cls(crawler.settings.getlist('USER_AGENTS'))
    
    def process_request(self,request,spider):
        request.headers.setdefault('User-Agent', random.choice(self.agents))

動態(tài)設置request代理ip,需要自己在setting,py中設置IPlist列表

class RandomProxy(object):
    def __init__(self,iplist):
        self.iplist=iplist

    @classmethod
    def from_crawler(cls,crawler):
        return cls(crawler.settings.getlist('IPLIST'))

    def process_request(self, request, spider):
        proxy = random.choice(self.iplist)
        request.meta['proxy'] =proxy

2.6Spider中間件

這個看官方文檔就好了 ——這里

3.部署

這里都是編寫完爬蟲代碼后的其他一些應用惭嚣,不完全屬于部署

3.1分布式下載器:Crawlea

官方提供了一個分布式下載器,用來幫助我們躲避反爬蟲的措施悔政。首先在官網(wǎng)注冊晚吞。之后拿到APIKEY用作驗證
不過是需要錢的
官網(wǎng):https://app.scrapinghub.com/account/login/?next=/next=/account/login
安裝:pip install scrapy-crawlera
之后修改setting.py
DOWNLOADER_MIDDLEWARES ={'scrapy_crawlera.CrawleraMiddleware':300}
CRAWLERA_ENABLED = True
CRAWLERA_APIKEY = '<API key>'

3.2Scrapyd

是的。官方又提供了一個部署爬蟲非常有用的工具谋国,Scrapyd是運行Scrapy爬蟲的服務程序槽地,它吃屎以http命令方式通過json api進行發(fā)布、刪除、啟動捌蚊、停止爬蟲程序的操作集畅,而且它可以同時管理多個爬蟲,每個爬蟲還可以有多個版本缅糟,也是部署分布式爬蟲有效手段
安裝:pipi install scrapyd
使用:輸入scrapyd啟動挺智,在瀏覽器輸入:http://127.0.0.1:6800/就可以看到界面了
API使用示例如下:

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

import requests
import json 

baseUrl ='http://127.0.0.1:6800/'
daemUrl ='http://127.0.0.1:6800/daemonstatus.json'
listproUrl ='http://127.0.0.1:6800/listprojects.json'
listspdUrl ='http://127.0.0.1:6800/listspiders.json?project=%s'
listspdvUrl= 'http://127.0.0.1:6800/listversions.json?project=%s'
listjobUrl ='http://127.0.0.1:6800/listjobs.json?project=%s'
delspdvUrl= 'http://127.0.0.1:6800/delversion.json'

#http://127.0.0.1:6800/daemonstatus.json
#查看scrapyd服務器運行狀態(tài)
r= requests.get(daemUrl)
print '1.stats :\n %s \n\n'  %r.text  

#http://127.0.0.1:6800/listprojects.json
#獲取scrapyd服務器上已經(jīng)發(fā)布的工程列表
r= requests.get(listproUrl)
print '1.1.listprojects : [%s]\n\n'  %r.text
if len(json.loads(r.text)["projects"])>0 :
    project = json.loads(r.text)["projects"][0]

#http://127.0.0.1:6800/listspiders.json?project=myproject
#獲取scrapyd服務器上名為myproject的工程下的爬蟲清單
listspd=listspd % project
r= requests.get(listspdUrl)
print '2.listspiders : [%s]\n\n'  %r.text 
if json.loads(r.text).has_key("spiders")>0 :
    spider =json.loads(r.text)["spiders"][0]


#http://127.0.0.1:6800/listversions.json?project=myproject
##獲取scrapyd服務器上名為myproject的工程下的各爬蟲的版本
listspdvUrl=listspdvUrl % project
r = requests.get(listspdvUrl)
print '3.listversions : [%s]\n\n'  %rtext 
if len(json.loads(r.text)["versions"])>0 :
    version = json.loads(r.text)["versions"][0]

#http://127.0.0.1:6800/listjobs.json?project=myproject
#獲取scrapyd服務器上的所有任務清單,包括已結束窗宦,正在運行的逃贝,準備啟動的。
listjobUrl=listjobUrl % proName
r=requests.get(listjobUrl)
print '4.listjobs : [%s]\n\n'  %r.text 


#schedule.json
#http://127.0.0.1:6800/schedule.json -d project=myproject -d spider=myspider
#啟動scrapyd服務器上myproject工程下的myspider爬蟲迫摔,使myspider立刻開始運行沐扳,注意必須以post方式
schUrl = baseurl + 'schedule.json'
dictdata ={ "project":project,"spider":spider}
r= reqeusts.post(schUrl, json= dictdata)
print '5.1.delversion : [%s]\n\n'  %r.text 


#http://127.0.0.1:6800/delversion.json -d project=myproject -d version=r99'
#刪除scrapyd服務器上myproject的工程下的版本名為version的爬蟲,注意必須以post方式
delverUrl = baseurl + 'delversion.json'
dictdata={"project":project ,"version": version }
r= reqeusts.post(delverUrl, json= dictdata)
print '6.1.delversion : [%s]\n\n'  %r.text 

#http://127.0.0.1:6800/delproject.json -d project=myproject
#刪除scrapyd服務器上myproject工程句占,注意該命令會自動刪除該工程下所有的spider沪摄,注意必須以post方式
delProUrl = baseurl + 'delproject.json'
dictdata={"project":project  }
r= reqeusts.post(delverUrl, json= dictdata)
print '6.2.delproject : [%s]\n\n'  %r.text 

3.3Scrapyd-client

懶得截圖訪問這里查看

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市纱烘,隨后出現(xiàn)的幾起案子杨拐,更是在濱河造成了極大的恐慌,老刑警劉巖擂啥,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哄陶,死亡現(xiàn)場離奇詭異,居然都是意外死亡哺壶,警方通過查閱死者的電腦和手機屋吨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來山宾,“玉大人至扰,你說我怎么就攤上這事∽拭蹋” “怎么了敢课?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長绷杜。 經(jīng)常有香客問我直秆,道長,這世上最難降的妖魔是什么鞭盟? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任圾结,我火速辦了婚禮,結果婚禮上懊缺,老公的妹妹穿的比我還像新娘疫稿。我一直安慰自己,他們只是感情好鹃两,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布遗座。 她就那樣靜靜地躺著,像睡著了一般俊扳。 火紅的嫁衣襯著肌膚如雪途蒋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天馋记,我揣著相機與錄音号坡,去河邊找鬼。 笑死梯醒,一個胖子當著我的面吹牛宽堆,可吹牛的內容都是我干的。 我是一名探鬼主播茸习,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼畜隶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了号胚?” 一聲冷哼從身側響起籽慢,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎猫胁,沒想到半個月后箱亿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡弃秆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年届惋,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片菠赚。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡盼樟,死狀恐怖,靈堂內的尸體忽然破棺而出锈至,到底是詐尸還是另有隱情晨缴,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布峡捡,位于F島的核電站击碗,受9級特大地震影響,放射性物質發(fā)生泄漏们拙。R本人自食惡果不足惜稍途,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望砚婆。 院中可真熱鬧械拍,春花似錦突勇、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至迄损,卻和暖如春定躏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背芹敌。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工痊远, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人氏捞。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓碧聪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親液茎。 傳聞我的和親對象是個殘疾皇子矾削,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內容