scrapy中的数据采集日志管理
不同于原生爬虫代码的是,scrapy是一个相对较成熟的框架,所以并不能直接去执行某一个python文件来执行采集任务,而是要通过脚本命令来实现项目的启动。
一、scrapy的步骤简述及代码实现
1.1 创建scrapy项目
scrapy startproject YourProjectName
首先打开终端(本篇文章中以pycharm中的terminal为例),然后进入到欲创建项目的目录。

命令键入后如上图所示,然后就可以在上图所示的目录中看到新建的项目文件夹。

1.2 创建爬虫文件
创建成功后根据提示来创建爬虫文件,命令如下:
cd myproject01 scrapy genspider example http://example.com

此处要注意格式,genspider后第一个参数为创建的爬虫任务名,第二个为访问域名(可随便填写)。回车后在项目文件夹中的spiders文件夹内可以看到刚刚创建的爬虫文件。

双击打开后如下:

接下来我们以某图片素材网为例进行讲解。
首先把要访问的目标地址添加到起始URL列表中,然后在parse方法中直接输出response查看响应结果。
# spiders.py
import scrapy
class Spider01Spider(scrapy.Spider):
name = "spider01"
allowed_domains = ["xxx.com"]
start_urls = ["https://sc.chinaz.com/tupian/siwameinvtupian.html"]
def parse(self, response):
print(response)
注意,此时先不要开始执行任务,先来到配置文件settings.py
中进行几处修改。
# 第一处变化,添加scrapy中请求时的默认UA
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"
# Obey robots.txt rules
# 第二处变化,将True改为False,表示访问时不按照君子协议进行数据采集
ROBOTSTXT_OBEY = False
# 第三处变化,添加参数LOG_LEVEL,值为ERROR,表示设置项目中日志等级为ERROR,添加后项目启动后只会显示错误信息,其他的调试信息不会再输出
LOG_LEVEL = 'ERROR'
接下来就可以启动项目运行了
scrapy crawl spiderName

可以看到response与requests请求的时候一样返回的是一个响应对象,那么也就意味着我们可以从该对象中拿到响应文本属性。但是要注意,scrapy中的响应对象获取字节类型数据时使用的是body而不是content。

1.3 scrapy中的xpath解析
与原生代码不同的是,在scrapy框架中xpath解析器已经是直接封装到了框架之中,所以使用的时候不用再去导入使用,直接通过响应对象response调用即可。

可以看到此处返回的不是直观的解析内容,而是一个selector选择器对象,如果要取出起data值的话,要借助于extract()、extract_first()、get()、getall()
方法进行提取,其中extract()
与getall()
方法为提取出所有匹配成功的数据,即列表中有几个选择器对象就提取几个选择器对象的data。extract_first()
和get()
为提取出列表中第一个数据。此处不再演示,自行测试即可。
二、scrapy中的翻页操作
在scrapy中翻页的操作代码与原生有所不同,但是原理是一样的,就是先找到下一页的URL然后对其发起请求。
翻页的三种方式:
# 1.将多个URL置于起始URL列表之中
start_urls = ["https://sc.chinaz.com/tupian/siwameinvtupian.html",
"https://sc.chinaz.com/tupian/siwameinvtupian_2.html",
"https://sc.chinaz.com/tupian/siwameinvtupian_3.html"]使用response.follow实现翻页
# 2.使用response.follow实现翻页
import scrapy
class Spider01Spider(scrapy.Spider):
name = "spider01"
allowed_domains = ["chinaz.com"]
start_urls = ["https://sc.chinaz.com/tupian/siwameinvtupian.html"]
def parse(self, response):
print(response)
# print(response.body.decode())
# title = response.xpath('/html/body/div[3]/div[2]/div[1]/div/a/@title').getall()
# print(title)
next_page = "https://sc.chinaz.com/tupian/" + response.xpath('//*[@class="nextpage"]/@href').extract_first()
print(next_page)
yield response.follow(url=next_page, callback=self.parse)
# 如此翻页会直到最后一页的时候才会停下,follow方法中的url即为解析到的下一页的url,callback表示的是回调的方法,此处即回调到parse方法。如果需要停止,则添加控制参数即可。
# 3.构造手动请求对象,与follow类似,在拿到下一页的URL之后构造新的手动请求对象。
import scrapy
class Spider01Spider(scrapy.Spider):
name = "spider01"
allowed_domains = ["chinaz.com"]
start_urls = ["https://sc.chinaz.com/tupian/siwameinvtupian.html"]
page = 1
def parse(self, response):
print(response)
# print(response.body.decode())
# title = response.xpath('/html/body/div[3]/div[2]/div[1]/div/a/@title').getall()
# print(title)
next_page = "https://sc.chinaz.com/tupian/" + response.xpath('//*[@class="nextpage"]/@href').extract_first()
# print(next_page)
if self.page < 3: # 共3页
self.page += 1
yield response.follow(url=next_page, callback=self.parse) # 构造手动请求对象
# 与follow类似,在拿到下一页的URL之后构造新的手动请求对象。
import scrapy
class Spider01Spider(scrapy.Spider):
name = "spider01"
allowed_domains = ["chinaz.com"]
start_urls = ["https://sc.chinaz.com/tupian/siwameinvtupian.html"]
page = 1
def parse(self, response):
print(response)
# print(response.body.decode())
# title = response.xpath('/html/body/div[3]/div[2]/div[1]/div/a/@title').getall()
# print(title)
next_page = "https://sc.chinaz.com/tupian/" + response.xpath('//*[@class="nextpage"]/@href').extract_first()
# print(next_page)
if self.page < 3: # 共3页
self.page += 1
# yield response.follow(url=next_page, callback=self.parse)
yield scrapy.Request(url=next_page, callback=self.parse) # 构建手动请求对象
# 手动请求对象的构建方式适用于详情页的数据解析。此处不再详讲。
三、scrapy中的日志管理
日志就是记录了项目运行期间各个操作的记录文本,其中记录了包括异常、警告、输入输入等操作信息。
3.1 日志级别
python的内置日志记录定义了5个不同的级别,以指示给定日志消息的严重性。以下为标准的日志等级,按降序排列:
- logging.CRITICAL -对于严重错误(严重性最高)
- logging.ERROR -对于常规错误
- logging.WARNING -用于警告消息
- http://logging.INFO -以获取信息性消息
- logging.DEBUG -用于调试消息(最低严重性)
3.2 消息记录
import logging
logging.warning('This is a warning')
在标准的5个级别中,有一个用于发布日志消息的快捷方式,还有一个常规的 logging.log 方法,该方法将给定的级别作为参数。如果需要,最后一个示例可以重写为:
import logging
logging.log(logging.WARNING, "This is a warning")
除此之外,还可以创建不同的“记录器”来封装消息。(例如,常见的做法是为每个模块创建不同的记录 器)。这些记录器可以独立配置,并且允许层次结构。
前面的实例是在后台使用根记录器,其是一个顶级记录器,所有消息都在其中传播(除非另有规定)。使 用 logging 帮助程序只是显式获取根记录器的快捷方式,因此这也是相当于最后一段代码:
import logging
logger = logging.getLogger()
logger.warning('This is a warning')
可以使用不同的记录器,只需将其名称 logging.getLogger 功能:
import logging
logger = logging.getLogger('mycustomlogger')
logger.warning("This is a warning")
3.3 日志记录配置
以下参数的配置与刚刚添加的LOG_LEVEL
方式一致,参数有如下:
LOG_FILE :用于日志记录输出的文件名
LOG_FILE_APPEND :如果False指定的日志文件LOG_FILE将被覆盖(如果有,则丢弃以前运行的输 出)
LOG_ENABLED :是否启用日志记录,默认True
LOG_ENCODING :用于日志记录的编码
LOG_LEVEL :要记录的最低级别。可用级别包括:严重、错误、警告、信息、调试
LOG_FORMAT :用于格式化日志消息的字符串。
LOG_DATEFORMAT :用于格式化日期/时间的字符串
LOG_STDOUT :默认为False,如果为True,进程的所有标准输出(和错误)都将重定向到日志
LOG_SHORT_NAMES :默认False,如果为True,日志只包含根路径。如果设置为False然后显示负责日志输出的组件
其余参数介绍见scrapy官方文档