Scrapy爬虫框架初试探(二)
定义爬取字段(定义Item)
爬取的主要目标是从非结构性的数据源提取结构性数据。csdnspider类的parse()方法解析出了read_count,title等数据,但是如何将这些数据保证成结构化数据呢,scrapy提供了Item类来满足这样的需求。Item对象是一种简单的容器,用来保存爬取到的数据,Item使用简单的class定义语法以及Filed对象来声明。
在我们创建Scrapy项目的时候,这个类已经给我们创建好了。在项目中找到items文件可以看到CsdnspiderItem类,这里我们声明两个字段read_count,title
CsdnspiderItem文件
在csdnspider中使用,注意要导入CsdnspiderItem
导入方法:from csdnSpider.items import CsdnspiderItem
封装Item对象
代码最后使用了yield关键字提交item,将parse方法造成一个生成器。
构建Item Pipeline
前面说了网页的下载,解析和数据item, 现在我们需要把数据进行持旧化存储,这就要用到Item Pipeline,当Item在Spider中被收集知乎,它就会被传递到Item,Pipeline, 一些组件会按照一定的顺序执行对Item处理。
Item Pipeline主要有以下应用
1、清理HTML数据
2、验证爬取数据的合法性,检查Item是否包含某些字段
3、查重并丢弃
4、将爬取的结果保存多文件或数据库中。
定制Item PIpeline
每个Ite Pipeline组件是一个独立的Python类,必须实现process_item方法,方法原型如下
process_item(self, item, spider)
每个Item Pipeline组件都需要调用这个方法,这给方法必须返回一个item对象,或者抛出DropItem异常,被抛弃的Item将不会被之后的Pipeline组件所处理。
参数说明:
Item对象是被爬取的对象
Spider对象代表着爬取该Item的Spider
我们需要将csdn爬虫爬取的Item存储到本地,定制的Item Pipeline位于csdnspider/pipelines.py声明csdnspiderPipeline类,完整内容如下:
import json
from scrapy.exceptions import DropItem
class CsdnspiderPipeline(object):
def __init__(self):
self.file = open('data.json', 'w')
def process_item(self, item, spider):
if item['title']:
line = json.dumps(dict(item))+"\n"
self.file.write(line)
return item
else:
raise DropItem("Missing title in %s" % item)
process_item方法中,先判断title,如果存在就存下来,否则抛弃。这里有多种存储方式,你页可以把数据存储到execl,数据库中。寒大在存储json的时候用的是'wb'以字节存储,而我们抓取的字段是字符串,所以我们将‘wb’直接改成‘w’。成功存入Json。
激活Item Pipeline
定制完Item Pipeline,它是无法工作的,需要时激活,要启动一个Item Pipeline组件,
必须将它的类添加到settings.py中的ITEM_PIPELINES变量中,代码如下:
ITEM_PIPELINES = {
'csdnSpider.pipelines.CsdnspiderPipeline': 300,
}
ITEM_PIPELINES变量中可以配置很多个Item Pipeline组件,分配给每个类的整型值确定了他们运行的顺序,item按数字从低到高的顺序通过Item Pipeline, 通常数字定义范围是0-1000
激活完成后,执行命令scrapy crawl csdn, 就可以把数据存到data,json文件中
效果图:
(报错了暂时空着吧)
内置存储数据
处理使用Item Pipeline实现存储功能,Scrapy呢你在了一些简单的存储方式,生成一个带有爬取数据的输入出文件,通过输出(feed),并支持多种序列化格式,自带的支持类型有
json
jsonlines
csv
xml
pickle
marshal
说实话pickle和marshal是什么文件我不知道
调用的时候直接输入命令行scrapy crawl csdn -o data.csv 注意后面的文件类型是可以变化的,你也可以输入json,jsonlines等不同格式,可以得到不同文件。
效果图如下
调用文件
效果图如下:
json文件
Scrapy爬虫调试
调方法
scrapy 用三种比较常用的雕塑方式:Parse命令,Scrapy Shell 和logging(使用起来不方便,不介绍)
.Parse命令
检查spider输出的最基本方法是使用Pasre命令,这能让你在函数层检查Spider哥哥部分效果,是十分灵魂且易用
查看特定url爬取到的item命令格式为
scrapy parse --spider=<spidername> -c <parse> -d 2 <item_url>
在命令行中切换到项目目录下输入
scraoy parse --spider=csdn -c parse -d 2 "https://csdn.net/nav/ai"
注意: spider=之间是没有控股的,切记,这是寒大犯的错误
效果图如下
调试2
Request为什么为空呢?我目前还是不知道的(上面说到,将'wb'改成'w'
Pycharm中调试Scrapy
因为使用Pycharm我们可以更清楚的设置断点来爬虫,所以大佬推荐在Pycharm中来调试。Scrapy提供了API让我们在程序中启动爬虫
下面给从事多年条件启动脚本。在吗的爬虫类中天津代码,为了让我们看清楚,放出大佬完整代码,主要看最下面的main方法,然后在代码中使用断点,可以清晰看到我们调试情况
import scrapy
from csdnSpider.items import CsdnspiderItem
from scrapy.crawler import CrawlerProcess
class csdnspiderpage(scrapy.Spider): # 必须继承scrapy.Spider
name = "csdn" # 爬虫名称,这个名称必须是唯一的
allowed = ["csdn.net"] # 允许的域名
start_urls = [
'https://www.csdn.net/nav/ai'
]
def parse(self, response):
datas = response.xpath('//*[@id="feedlist_id"]/li/div')
for data in datas:
read_count = data.xpath('./dl/div[2]/dd[1]/a/span[1]/text()').extract()
title = data.xpath('./div[1]/h2/a/text()').extract()
read_count = read_count[0] if len(read_count) > 0 else ''
title = title[0] if len(title) > 0 else ''
print(read_count, title)
item = CsdnspiderItem(read_count=read_count, title=title) # 封装成Item对象
yield item
pass
if __name__ == '__main__':
process = CrawlerProcess(
{
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/'
'53.0.2785.104 Safari/537.36 Core/1.53.4620.400 QQBrowser/9.7.13014.400'
}
)
process.crawl(csdnspiderpage)
process.start()
Scrapy工作流程
大佬故意把这个架构图放在最后来说,大佬一头雾水,我更别说了,都不敢水。随着大佬的思路来了解这个架构图。
架构图如下:
工作流
再回头看:
1、首先再Spiders中惊喜调度Schedules请求,
2/让母后发起一系列请求Request到Downloader中
3、然后再是Downloader响应Response到Spiders中
4、接着就是数据采集到items中
5、然后Item Pipeline来处理数据
6、接着再进行下一轮请求,直到没有更多的请求,引擎关闭网站
这就是整个Spider的工作流程
总结
我这是把大佬的教程抄了一遍,皮毛都没有掌握。希望再接再厉吧。