创建一个Scrapy项目会在项目目录下自动创建多个.py文件,他们各自承担不同的作用。

数据封装
对抓取的零散数据如何维护,在之间的例子中我们使用了python的dict。
yield {
# xpath 语法 @ATTR 为选中为名ATTR的属性节点
'name': book.xpath('h3/a/@title').get(),
'price': book.css('p.price_color::text').get(),
}
但是字典存在一定的缺陷,所以Scrapy提供了两个类允许用户自定义数据类,并封装起来。
● Item基类:自定义数据类(如BookItem)的基类。
● Field类:用来描述自定义数据类包含哪些字段(如name、price等)
可在item.py文件中实现自定义数据
from scrapy import Item, Field
class BookItem(Item):
name = Field()
price = Field()
在spider中导入自定义数据类,并修改代码
from ..items import BookItem
class BooksSpider(scrapy.Spider):
...
def parse(self, response):
for books in response.css('article.product_pod'):
book = BookItem()
book['name'] = books.xpath('h3/a/@title').extract_first()
book['price'] = books.css('p.price_color::text').extract_first()
yield book
...
Item支持字典接口,因此BookItem在使用上和Python字典类似,可按上述方式创建BookItem对象 book['name'] = books.xpath('h3/a/@title').extract()
数据处理
在Scrapy中,Item Pipeline是处理数据的组件,一个Item Pipeline就是一个包含特定接口的类,通常只负责一种功能的数据处理,在一个项目中可以同时启用多个Item Pipeline,它们按指定次序级联起来,形成一条数据处理流水线。 以下是Item Pipeline的几种典型应用:
● 清洗数据。
● 验证数据的有效性。
● 过滤掉重复的数据。
● 将数据存入数据库。
实现
重写pipelines.py文件,将价格单位重英镑改为人民币
class PriceConverterPipeline(object):
exchange_rate=8.5309
def process_item(self,item,spider):
# 提取item的price字段(如£53.74)
# 去掉前面英镑符号£,转换为float类型,乘以汇率
price=float(item['price'] [1:])*self.exchange_rate
# 保留2位小数,赋值回item的price字段
item['price']='¥%.2f'%price
return item
可以看出,process_item方法是Item Pipeline的核心,对该方法还需再做两点补充说明:
- 如果process_item在处理某项item时返回了一项数据(Item或字典),返回的数据会递送给下一级Item Pipeline(如果有)继续处理。
- 如果process_item在处理某项item时抛出(raise)一个DropItem 异常(scrapy.exceptions.DropItem),该项item便会被抛弃,不再递送给后面的Item Pipeline继续处理,也不会导出到文件。通常, 我们在检测到无效数据或想要过滤数据时,抛出DropItem异常。
除了必须实现的process_item方法外,还有3个比较常用的方法,可根据需求选择实现:
- open_spider(self, spider) Spider打开时(处理数据前)回调该方法,通常该方法 用于在开始处理数据之前完成某些初始化工作,如连接数据库。
- close_spider(self, spider) Spider关闭时(处理数据后)回调该方法,通常该方法 用于在处理完所有数据之后完成某些清理工作,如关闭数据库。
- from_crawler(cls, crawler) 创建Item Pipeline对象时回调该类方法。通常,在该方法 中通过crawler.settings读取配置,根据配置创建Item Pipeline对象。 在后面的例子中,我们展示了以上方法的应用场景。
配置
因为Item Pipeline是可选的组件,所以想要启用Item Pipeline,需要在配置文件settings.py中进行配置:
ITEM_PIPELINES = {'example.pipelines.PriceConverterPipeline': 300, }
ITEM_PIPELINES是一个字典,我们把想要启用的Item Pipeline添加到这个字典中,其中每一项的键是每一个Item Pipeline类的导入路径,值是一个0~1000的数字,同时启用多个Item Pipeline时,Scrapy根据这些数值决定各Item Pipeline处理数据的先后次序,数值小的在前。
more example
过滤重复数据
# 过滤重复数据,以name为依据
class DuplicatesPipeline(object):
def __init__(self):
self.book_set = set()
def process_item(self, item, spider):
name = item['name']
if name in self.book_set:
raise DropItem("Duplicate book found: %s" %item)
self.book_set.add(name)
return item
数据存储到mongodb
from scrapy.item import Item
import pymongo
class MongoDBPipeline(object):
DB_URI = 'mongodb://localhost:27017/'
DB_NAME = 'scrapy_data'
def open_spider(self, spider):
self.client = pymongo.MongoClient(self.DB_URI)
self.db = self.client[self.DB_NAME]
def close_spider(self, spider):
self.client.close()
def process_item(self, item, spider):
collection=self.db[spider.name]
post=dict(item)if isinstance(item, Item)else item
collection.insert_one(post)
return item
ITEM_PIPELINES={ 'example.pipelines.PriceConverterPipeline':300, 'example.pipelines.DuplicatesPipeline':350,
'example.pipelines.MongoDBPipeline':400,
}
使用LinkExtractor提取链接
获取连接有两种方式
- Selecor
- LinkExtractor
Selector
因为链接也是页面中的数据,所以可以使用与提取数据相同的方法进行提取,在提取少量(几个)链接或提取规则比较简单时,使用Selector就足够了。
LinkExtractor
from scrapy.linkextractors import LinkExtractor
class BooksSpider(scrapy.Spider):
...
def parse(self, response):
...
le = LinkExtractor(restrict_css='ul.pager li.next')
links = le.extract_links(response)
if links:
next_url = links[0].url
yield scrapy.Request(next_url,callback=self.parse)
描述规则
参数 | 描述 |
---|---|
allow | 接收一个正则表达式或一个正则表达式列表,提取绝对url与正则表达式匹配的链接,如果该参数为空(默认),就提取全部链接。 |
deny | 接收一个正则表达式或一个正则表达式列表,与allow相反,排除绝对url与正则表达式匹配的链接。 |
allow_domains | 接收一个域名或一个域名列表,提取到指定域的链接。 |
deny_domains | 接收一个域名或一个域名列表,与allow_domains相反, 排除到指定域的链接。 |
restrict_xpaths | 接收一个XPath表达式或一个XPath表达式列表,提取 XPath表达式选中区域下的链接。 |
restrict_css | 接收一个CSS选择器或一个CSS选择器列表,提取CSS选择器选中区域下的链接。 |
tags | 接收一个标签(字符串)或一个标签列表,提取指定标签内的链接,默认为[‘a’, ‘area’]。 |
attrs | 接收一个属性(字符串)或一个属性列表,提取指定属性内的链接,默认为[‘href’]。 |
process_value | 接收一个形如func(value)的回调函数。如果传递了该参数,LinkExtractor将调用该回调函数对提取的每一个链接(如a的href)进行处理,回调函数正常情况下应返回一个字符串(处理结果),想要抛弃所处理的链接时, 返回None。 |
数据导出
数据导出有两种方式
- 命令行
- 配置文件
运行scrapy crawl命令通过-t指定到处类型,-o导出路径
scrapy crawl books -t csv -o books1.data