- CrawlSpider:Scrapy提供的一个通用Spider
- 官方文档链接:http://scrapy.readthedocs.io/en/latest/topics/spiders.html#crawlspider
- 在Spider里,使用数据结构Rule表示用来实现页面的提取的爬取规则;Rule里包含提取和跟进页面的配置,Spider会根据Rule来确定当前页面中的哪些链接需要继续爬取、哪些页面的爬取结果需要用哪个方法解析等
- CrawlSpider继承自Spider类,它还提供了一个非常重要的属性和方法。
- rules:爬取规则属性,是包含一个或多个Rule对象的列表,每个Rule对爬取网站的动作都做了定义,CrawlSpider会读取rules的每一个Rule并进行解析
- parse_start_url():一个可重写的方法;当start_urls里对应的Request得到Response时,该方法被调用,它会分析Response并必须返回Item对象或者Request对象
- Rule的定义
1 class scrapy.contrib.spiders.Rule(link_extractor, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=None) 2 3 # link_extractor:是Link Extractor对象,Spider通过它可以知道从爬取的页面中提取哪些链接,提取出的链接会自动生成Request,它又是一个数据结构,一般常用LxmlLinkExtractor对象作为参数 4 # callback:即回调函数,每次从link_extractor中获取到链接时,该函数将会调用。该回调函数接收一个response作为其第一个参数,并返回一个包含Item或Request对象的列表 5 # 注意:避免使用parse()作为回调函数。由于CrawlSpider使用parse()方法来实现其逻辑,如果parse()方法覆盖了,CrawlSpider将会运行失败 6 # cb_kwargs:字典,它包含传递给回调函数的参数 7 # follow:布尔值,即True或False,它指定根据该规则从response提取的链接是否需要跟进;如果callback参数为None,follow默认设置为True,否则默认为False 8 # process_links:指定处理函数,从link_extractor中获取到链接列表时,该函数将会调用,它主要用于过滤 9 # process_request:同样是指定处理函数,根据该Rule提取到每个Request时,该函数都会调用,对Request进行处理;该函数必须返回Request或者None
- LxmlLinkExtractor对象
1 # LxmlLinkExtractor对象 2 scrapy.linkextractors.lxmlhtml.LxmlLinkExtractor(allow=(), deny=(), allow_domains=(), deny_domains=(), deny_extensions=None, restrict_xpaths=(), restrict_css=(), tags=('a', 'area'), attrs=('href', ), canonicalize=False, unique=True, process_value=None, strip=True) 3 4 # allow是一个正则表达式或正则表达式列表,它定义了从当前页面提取出的链接哪些是符合要求的,只有符合要求的链接才会被跟进 5 # deny则与allow相反 6 # allow_domains定义了符合要求的域名,只有此域名的链接才会被跟进生成新的Request,它相当于域名白名单 7 # deny_domains则相反,相当于域名黑名单 8 # restrict_xpaths定义了从当前页面中XPath匹配的区域提取链接,其值是XPath表达式或XPath表达式列表 9 # restrict_css定义了从当前页面中CSS选择器匹配的区域提取链接,其值是CSS选择器或CSS选择器列表 10 # 文档的参数说明:http://scrapy.readthedocs.io/en/latest/topics/link-extractors.html#module-scrapy.linkextractors.lxmlhtml
- Item Loader:提供的一系列API可以分析原始数据对Item进行赋值;Item提供的是保存抓取数据的容器,而Item Loader提供的是填充容器的机制
1 class scrapy.loader.ItemLoader([item, selector, response, ] **kwargs) 2 3 # 返回一个新的Item Loader来填充给定的Item。 4 # 如果没有给出Item,则使用中的类自动实例化default_item_class,传入selector和response参数来使用选择器或响应参数实例化 5 # item:它是Item对象,可以调用add_xpath()、add_css()或add_value()等方法来填充Item对象 6 # selector:它是Selector对象,用来提取填充数据的选择器 7 # response:它是Response对象,用于使用构造选择器的Response 8 # 一个比较典型的Item Loader实例 9 from scrapy.loader import ItemLoader 10 from project.items import Product 11 12 def parse(self, response): 13 loader = ItemLoader(item=Product(), response=response) # 用该Item和Response对象实例化ItemLoader 14 # 用add_xpath()、add_css()、add_value()等方法对不同属性依次赋值,最后调用load_item()方法实现Item的解析 15 # 调用add_xpath()方法把来自两个不同位置的数据提取出来,分配给name属性 16 loader.add_xpath('name', '//div[@class="product_name"]') 17 loader.add_xpath('name', '//div[@class="product_title"]') 18 loader.add_xpath('price', '//p[@id="price"]') 19 loader.add_css('stock', 'p#stock]') 20 # Item Loader每个字段中都包含了一个Input Processor(输入处理器)和一个Output Processor(输出处理器) 21 # Input Processor收到数据时立刻提取数据,Input Processor的结果被收集起来并且保存在ItemLoader内,但是不分配给Item 22 # 收集到所有的数据后,load_item()方法被调用来填充再生成Item对象 23 # 在调用时会先调用Output Processor来处理之前收集到的数据,然后再存入Item中,这样就生成了Item 24 loader.add_value('last_updated', 'today') 25 return loader.load_item()
- 内置的的Processor
- Identity:是最简单的Processor,不进行任何处理,直接返回原来的数据
- TakeFirst:TakeFirst返回列表的第一个非空值,类似extract_first()的功能,常用作Output Processor
1 from scrapy.loader.processors import TakeFirst 2 3 processor = TakeFirst() 4 # 经过此Processor处理后的结果返回了第一个不为空的值 5 print(processor(['', 1, 2, 3])) # 1
- Join:相当于字符串的join()方法,可以把列表拼合成字符串,字符串默认使用空格分隔
1 from scrapy.loader.processors import Join 2 3 processor = Join() 4 print(processor(['one', 'two', 'three'])) # one two three 5 processor = Join(',') 6 print(processor(['one', 'two', 'three'])) # one,two,three
- Compose:是用给定的多个函数的组合而构造的Processor,每个输入值被传递到第一个函数,其输出再传递到第二个函数,依次类推,直到最后一个函数返回整个处理器的输出
1 from scrapy.loader.processors import Compose 2 3 processor = Compose(str.upper, lambda s: s.strip()) 4 print(processor(' hello world')) # HELLO WORLD
- MapCompose:与Compose类似,MapCompose可以迭代处理一个列表输入值
1 from scrapy.loader.processors import MapCompose 2 3 processor = MapCompose(str.upper, lambda s: s.strip()) 4 print(processor(['Hello', 'World', 'Python'])) # ['HELLO', 'WORLD', 'PYTHON']
- SelectJmes:可以查询JSON,传入Key,返回查询所得的Value;需要先安装Jmespath库才可以使用它
1 pip install jmespath
1 from scrapy.loader.processors import SelectJmes 2 3 proc = SelectJmes('foo') 4 processor = SelectJmes('foo') 5 print(processor({'foo': 'bar'})) # bar