Scrapy 数据的提取
Scrapy有自己的数据提取机制。它们被称为选择器。我们可以通过使用的选择器re、xpath、css提取数据
提示
不用再安装与引入Xpath,BS4
获得选择器
Response对象获取
正常使用
response.selector.xpath('//span/text()').get()
response.selector.css('span::text').get()
response.selector.re('<span>')
快捷使用
response.xpath('//span/text').get()
response.css('span::text').get()
创建对象
from scrapy.selector import Selector
通过text参数 初始化
body = '<html><body><span>good</span></body></html>'
Selector(text=body).xpath('//span/text()').get()
通过response参数 初始化
from scrapy.selector import Selector
from scrapy.http import HtmlResponse
response =HtmlResponse(url='http://example.com',body=body)
Selector(response=response).xpath('//span/text()').get()
'good'
选择器的方法
S.N. | 方法 & 描述 |
extract()、getall() | 它返回一个unicode字符串以及所选数据 |
extract_first()、get() | 它返回第一个unicode字符串以及所选数据 |
re() | 它返回Unicode字符串列表,当正则表达式被赋予作为参数时提取 |
xpath() | 它返回选择器列表,它代表由指定XPath表达式参数选择的节点 |
css() | 它返回选择器列表,它代表由指定CSS表达式作为参数所选择的节点 |
Scrapy Shell的使用
Scrapy Shell是一个交互式shell,可以在不运行spider项目时,快速调试 scrapy 代码。
提示
一般用于测试xpath或css表达式,查看它们是否能提取想要的数据
注意
当从命令行运行Scrapy Shell时,记住总是用引号括住url,否则
url包含参数(即 & 字符)不起作用。在Windows上,使用双引号:
scrapy shell "https://scrapy.org"
Scrapy 保存数据到文件
- 用Python原生方式保存
with open("movie.txt", 'wb') as f:
for n, c in zip(movie_name,
movie_core):
str = n+":"+c+"\n"
f.write(str.encode())
- 使用Scrapy内置方式
scrapy 内置主要有四种:JSON,JSON lines,CSV,XML
最常用的导出结果格为JSON,命令如下:
scrapy crawl dmoz -o douban.json -t json
参数设置:
- -o 后面导出文件名
- -t 后面导出的类型
可以省略,但要保存的文件名后缀,写清楚类型
注意
将数据解析完,返回数据,才可以用命令保存,代码如下,格
式为dict或item类型
- return data
- yield data
Item Pipeline的使用
当数据在Spider中被收集之后,可以传递到Item Pipeline中统一进行处理。
特点
每个item pipeline就是一个普通的python类,包含的方法名如下:
| 含义 | 是否必须实现 |
process_item(self,item,spider) | 用于处理接收到的item | 是 |
open_spider(self,spider) | 表示当spider被开启的时候调用这个方法 | 否 |
close_spider(self,spider) | 当spider关闭时候这个方法被调用 | 否 |
功能
- 接收item
在 process_item 方法中保存
- 是否要保存数据
取决于是否编写代码用于保存数据
- 决定此Item是否进入下一个pipeline
- return item 数据进入下一个pipeline
- drop item 抛弃数据
案例代码
class SaveFilePipeline:
def open_spider(self,spider):
self.file = open('douban5.txt','w')
def process_item(self, item, spider):
self.file.write(f'name:{item.get("name")} score:{item.get("score")}\n')
def close_spider(self,spider):
self.file.close()
from scrapy.exceptions import DropItem
class XSPipeline:
def open_spider(self,spider):
self.file =
open('xs.txt','w',encoding='utf-8')
def process_item(self, item, spider):
if item.get('title'):
self.file.write(item.get('title'))
self.file.write('\n')
return item
else:
raise DropItem(f"Missing title
in {item}")
def close_spider(self,spider):
self.file.close()
Scrapy 使用ImagePipeline 保存图片
Scrapy提供了一个 ImagePipeline,用来下载图片这条管道,图片管道 ImagesPipeline 提供了方便并具有额外特性的功能,比如:
- 将所有下载的图片转换成通用的格式(JPG)和模式(RGB)
- 避免重新下载最近已经下载过的图片
- 缩略图生成
- 检测图像的宽/高,确保它们满足最小限制
使用图片管道
scrapy.pipelines.images.ImagesPipeline
使用 ImagesPipeline ,典型的工作流程如下所示::
- 在一个爬虫中,把图片的URL放入 image_urls 组内(image_urls是个列表)
- URL从爬虫内返回,进入图片管道
- 当图片对象进入 ImagesPipeline,image_urls 组内的URLs将被Scrapy的调度器和下载器安排下载
- settings.py文件中配置保存图片路径参数 IMAGES_STORE
- 开启管道
注意
需要安装pillow4.0.0以上版本
pip install pillow==9.2.0
问题
报错:twisted.python.failure.Failure OpenSSL.SSL.Error
解决方案
pip uninstall cryptography
pip install cryptography==36.0.2
Scrapy 自定义ImagePipeline
问题
使用官方默认图片管道,有如下几个问题:
- 文件名不友好
- 存储图片URL的参数名称与类型太固定
解决方案
自定义ImagePipeline,扩展
自定义图片管道
- 继承 scrapy.pipelines.images import ImagesPipeline
- 实现 get_media_requests(self, item, info) 方法
- 发送请求,下载图片
- 转发文件名
- 实现 file_path(self,request,response=None,info=None,*,item=None)
- 修改文件名与保存路径
代码
import re
class Scrapy05Pipeline:
def process_item(self, item, spider):
return item
from scrapy.pipelines.images import ImagesPipeline
from scrapy.http.request import Request
class MyImagePipeline(ImagesPipeline):
def get_media_requests(self, item,info):
return Request(item['image_url'])
def file_path(self, request,response=None, info=None, *, item=None):
# 处理文件名中的特殊字符
# name =item.get('name').strip().replace('\r\n\t\t', '').replace('(','').replace(')','').replace('/','_')
name = re.sub('/','_',re.sub('[\s()]','',item.get('name')))
return f'{name}.jpg'
Scrapy 中settings配置的使用
Scrapy允许自定义设置所有Scrapy组件的行为,包括核心、扩展、管道和spider本身。
官网-参考配置
设置 — Scrapy 2.5.0 文档 (osgeo.cn)https://www.osgeo.cn/scrapy/topics/settings.html
配置文档
- BOT_NAME
默认: 'scrapybot'
Scrapy项目实现的bot的名字。用来构造默认 User-Agent,同时也用来log。
当你使用 startproject 命令创建项目时其也被自动赋值。
- CONCURRENT_ITEMS
默认: 100
Item Processor(即 Item Pipeline) 同时处理(每个response的)item的最大值
- CONCURRENT_REQUESTS
默认: 16
Scrapy downloader 并发请求(concurrent requests)的最大值。
- CONCURRENT_REQUESTS_PER_DOMAIN
默认: 8
对单个网站进行并发请求的最大值。
- CONCURRENT_REQUESTS_PER_IP
默认: 0
对单个IP进行并发请求的最大值。如果非0,则忽略
CONCURRENT_REQUESTS_PER_DOMAIN 设定, 使用该设定。 也就是说,并发限制将针对IP,而不是网站。
该设定也影响 DOWNLOAD_DELAY: 如果CONCURRENT_REQUESTS_PER_IP 非0,下载延迟应用在IP而不是网站上。
- FEED_EXPORT_ENCODING ='utf-8'
设置导出时文件的编码
- DEFAULT_REQUEST_HEADERS
默认:
{
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en',
}
Scrapy HTTP Request使用的默认header。由
DefaultHeadersMiddleware 产生。
- DOWNLOADER_MIDDLEWARES
默认:: {}
保存项目中启用的下载中间件及其顺序的字典
- DOWNLOAD_DELAY
默认: 0
下载器在下载同一个网站下一个页面前需要等待的时间。该选项可以用来限制爬取速度, 减轻服务器压力。同时也支持小数
- DOWNLOAD_TIMEOUT
默认: 180
下载器超时时间(单位: 秒)
- ITEM_PIPELINES
默认: {}
保存项目中启用的pipeline及其顺序的字典。该字典默认为空,值(value)任意。 不过值(value)习惯设定在0-1000范围内
- DEPTH_LIMIT
默认: 0
类: scrapy.spidermiddlewares.depth.DepthMiddleware
允许为任何站点爬行的最大深度。如果为零,则不会施加任何限制。
- LOG_ENABLED
默认: True
是否启用logging
- LOG_ENCODING
默认: 'utf-8'
logging使用的编码。
- LOG_FILE
默认: None
logging输出的文件名。如果为None,则使用标准错误输出(standard error)。
- LOG_FORMAT
默认: '%(asctime)s [%(name)s] %(levelname)s: %(message)s'
日志的数据格式
- LOG_DATEFORMAT
默认: '%Y-%m-%d %H:%M:%S'
日志的日期格式
- LOG_LEVEL
默认: 'DEBUG'
log的最低级别。可选的级别有: CRITICAL、 ERROR、WARNING、INFO、DEBUG
- LOG_STDOUT
默认: False
如果为 True ,进程所有的标准输出(及错误)将会被重定向到log中
- ROBOTSTXT_OBEY
默认: True
是否遵循robots协议
- USER_AGENT
默认: "Scrapy/VERSION (+http://scrapy.org/)"
爬取的默认User-Agent,除非被覆盖
Scrapy默认BASE设置
scrapy对某些内部组件进行了默认设置,这些组件通常情况下是不能被修改的,但是我们在自定义了某些组件以后,比如我们设置了自定义的middleware中间件,需要按照一定的顺序把他添加到组件之中,这个时候需要参考scrapy的默认设置,因为这个顺序会影响scrapy的执行,下面列出了scrapy的默认基础设置
注意
如果想要修改以下的某些设置,应该避免直接修改下列内容,
而是修改其对应的自定义内容
{
'scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware': 100,
'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware': 300,
'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware': 350,
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': 400,
'scrapy.downloadermiddlewares.retry.RetryMiddleware': 500,
'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware': 550,
'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware': 580,
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 590,
'scrapy.downloadermiddlewares.redirect.RedirectMiddleware': 600,
'scrapy.downloadermiddlewares.cookies.CookiesMiddleware': 700,
'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 750,
'scrapy.downloadermiddlewares.chunked.ChunkedTransferMiddleware': 830,
'scrapy.downloadermiddlewares.stats.DownloaderStats': 850,
'scrapy.downloadermiddlewares.httpcache.HttpCacheMiddleware': 900,
}
如果需要关闭下载处理器,为其赋值为 None 即可
提示
有时添加了一些自定义的组件,无法应用到效果,可以从执行
顺序方面入手
执行顺序:输值越小,优先级越高