该实例爬取:http://quotes.toscrape.com/page/1/
一、新建项目
二、明确目标
三、制作爬虫
def parse(self, response): l = ItemLoader(item=QuotesItem(), response=response) l.add_xpath('text', '//div/span/text()') l.add_xpath('author', '//div/small/text()') l.add_xpath('tags', '//div[@class='tags']/a/text()') return l.load_item()
先来弄明白俩个概念:
输入输出处理器:
Item Loader在每个字段中都包含了一个输入处理器和一个输出处理器。
输入处理器收到数据时立刻提取数据 (通过 add_xpath()方法) 之后输入处理器的结果被收集起来并且保存在ItemLoader内(但尚未分配给该Item).
收集到所有的数据后, 调用 ItemLoader.load_item() 方法来填充,并得到填充后的 Item 对象。在这一步中先调用输出处理器来处理之前收集到的数据,然后再存入Item中。输出处理器的结果是被分配到Item的最终值。
内置的处理器
尽管你可以使用可调用的函数作为输入输出处理器,Scrapy提供了一些常用的处理器。有些处理器,如MapCompose(通常用于输入处理器),能把多个函数执行的结果按顺序组合起来产生最终的输出。
以下是常用处理器使用示例:
from scrapy.loader.processors import SelectJmes,TakeFirst,Join,Compose,MapCompose #测试takefirst #返回非空值,常用于单值字段的输出处理器 proc=TakeFirst() print("takefirst:",proc({'','one','two','three'})) #测试join #返回分隔符连接后的值,分隔符默认为空格 proc=Join() print("join:",proc(['one','two','three'])) #测试compose #用给定的多个函数的组合而构造的处理器,每个输入值被传递到第一个函数,然后其输出再传递到第二个函数,直到最后一个函数返回整个处理器的输出 #默认情况下,当遇到none时停止处理 proc=Compose(lambda v:v[0],str.upper) print("compose:",proc(['hello','world'])) #测试mapcompose #与Compose处理器类似,区别在于各个函数结果在内部传递的方式: #输入值是被迭代的处理的,每一个元素被单独传入第一个函数进行处理。处理的结果被|连接起来 #(concatenate)形成一个新的迭代器,并被传入第二个函数,以此类推,直到最后一个函数。 #最后一个函数的输出被连接起来形成处理器的输出。 #每个函数能返回一个值或者一个值列表,也能返回None(会被下一个函数所忽略) #这个处理器提供了方便的方式来组合多个处理单值的函数。因此它常用于输入处理器, #因为用extract()函数提取出来的值是一个unicode strings列表。 def filter_world(x): return None if x=='world' else x proc=MapCompose(filter_world,str.upper) print("mapcompose:",proc([u'hello',u'world',u'this',u'is',u'scrapy']))
输出结果
takefirst: two join: one two three compose: HELLO mapcompose: ['HELLO', 'THIS', 'IS', 'SCRAPY']
下面是一些内置处理器的说明:
1 Identity
class scrapy.loader.processors.Identity
最简单的处理器,不进行任何处理,直接返回原来的数据。无参数。
.2 TakeFirst
class scrapy.loader.processors.TakeFirst
返回第一个非空(non-null/non-empty)值,常用于单值字段的输出处理器。无参数。
示例如下:
>>> from scrapy.loader.processors import TakeFirst
>>> proc = TakeFirst()
>>> proc(['', 'one', 'two', 'three']) 'one'
.3 Join
class scrapy.loader.processors.Join(separator=u’ ‘)
返回用分隔符连接后的值。分隔符默认为空格。不接受Loader contexts。
当使用默认分隔符的时候,这个处理器等同于这个函数:
u' '.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'
4 Compose
class scrapy.loader.processors.Compose(*functions, **default_loader_context)
用给定的多个函数的组合而构造的处理器。每个输入值被传递到第一个函数,然后其输出再传递到第二个函数,诸如此类,直到最后一个函数返回整个处理器的输出。
默认情况下,当遇到None
值的时候停止处理。可以通过传递参数stop_on_none=False
改变这种行为。
使用示例:
>>> from scrapy.loader.processors import Compose
>>> proc = Compose(lambda v: v[0], str.upper)
>>> proc(['hello', 'world'])
'HELLO'
每个函数可以选择接收一个loader_context
参数。
.5 MapCompose
class scrapy.loader.processors.MapCompose(*functions, **default_loader_context)
与Compose处理器类似,区别在于各个函数结果在内部传递的方式:
-
输入值是被迭代的处理的,每一个元素被单独传入第一个函数进行处理。处理的结果被l连接起来(concatenate)形成一个新的迭代器,并被传入第二个函数,以此类推,直到最后一个函数。最后一个函数的输出被连接起来形成处理器的输出。
-
每个函数能返回一个值或者一个值列表,也能返回
None
(会被下一个函数所忽略) -
这个处理器提供了方便的方式来组合多个处理单值的函数。因此它常用与输入处理器,因为用extract()函数提取出来的值是一个unicode strings列表。
下面的例子能说明这个处理器的工作方式:
>>> 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']
与Compose处理器类似,它也能接受Loader context。