Day:007(2) | Python爬虫:高效数据抓取的编程技术(scrapy框架使用)

Scrapy 数据的提取

Scrapy有自己的数据提取机制。它们被称为选择器。我们可以通过使用的选择器re、xpath、css提取数据

提示

不用再安装与引入Xpath,BS4

获得选择器

Response对象获取
正常使用
python 复制代码
response.selector.xpath('//span/text()').get()
response.selector.css('span::text').get()
response.selector.re('<span>')
快捷使用
python 复制代码
response.xpath('//span/text').get()
response.css('span::text').get()

创建对象

python 复制代码
from scrapy.selector import Selector

通过text参数 初始化

python 复制代码
body = '<html><body><span>good</span></body></html>'
Selector(text=body).xpath('//span/text()').get()

通过response参数 初始化

python 复制代码
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上,使用双引号:

python 复制代码
scrapy shell "https://scrapy.org"

Scrapy 保存数据到文件

  • 用Python原生方式保存
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,命令如下:

python 复制代码
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 抛弃数据

案例代码

python 复制代码
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()
python 复制代码
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)
  • 避免重新下载最近已经下载过的图片
  • 缩略图生成
  • 检测图像的宽/高,确保它们满足最小限制

使用图片管道

python 复制代码
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)
    • 修改文件名与保存路径

代码

python 复制代码
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的默认基础设置

注意

如果想要修改以下的某些设置,应该避免直接修改下列内容,

而是修改其对应的自定义内容

python 复制代码
{
  
'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 即可

提示

有时添加了一些自定义的组件,无法应用到效果,可以从执行

顺序方面入手

执行顺序:输值越小,优先级越高

相关推荐
零意@7 分钟前
ubuntu切换不同版本的python
windows·python·ubuntu
思忖小下19 分钟前
Python基础学习_01
python
q567315231 小时前
在 Bash 中获取 Python 模块变量列
开发语言·python·bash
是萝卜干呀1 小时前
Backend - Python 爬取网页数据并保存在Excel文件中
python·excel·table·xlwt·爬取网页数据
代码欢乐豆1 小时前
数据采集之selenium模拟登录
python·selenium·测试工具
狂奔solar1 小时前
yelp数据集上识别潜在的热门商家
开发语言·python
Tassel_YUE1 小时前
网络自动化04:python实现ACL匹配信息(主机与主机信息)
网络·python·自动化
聪明的墨菲特i2 小时前
Python爬虫学习
爬虫·python·学习
努力的家伙是不讨厌的3 小时前
解析json导出csv或者直接入库
开发语言·python·json
云空3 小时前
《Python 与 SQLite:强大的数据库组合》
数据库·python·sqlite