scrapy學習筆記(有示例版)
- 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覆旱。該處理器一次只需要一個輸入蘸朋。
和json一起使用>>> 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'}
>>> 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
懶得截圖訪問這里查看