听完几首歌,开始今天的爬虫课程,这部分主要是对管道使用的介绍,本部分讲完,后面再一个综合案例就结束了,最好今天能够把这部分搞熟,包括案例的理解,可以结合前五篇一起回顾scrapy的特性和那张部件流程图。
课前导入:
目录
1.ItemPipeline的介绍
对于管道的学习,在前面通过对scrapy项目中item的讲解可以知道,这个是用来传递数据的管道,上部分说的对数据进行去重和清洗,就是在这部分完成的,也就是说Item数据对象在spider采集器中被收集到后,传到ItemPipeline,这部分的学习就是讲传到pipeline后的操作。下面用老师的课件进行理解:
对于pipeline的具体应用,后面的演示主要是第四个应用,前三个对于实际应用较为重要,比如对于业务真实数据的采集,是很有必要的。
2.如何自定义ItemPipeline
讲完理论知识,可以来看看怎么构造item pipeline,在scrapy项目中已经生成了一个模板,但需要我们针对自己的实际需要再进行自定义新的类(在同一文件即可,注意命名不要重复)。
在讲这部分的时候,PPT上老师的要点较为简略,跟着讲义补充了更多细节,听到老师说在官方网站上有更多功能的介绍,学习着参看文档,这样更准确,而且更能扩展其他用法。
找到文档部分,想学习一门编程语言或者框架,善用文档。链接贴在这里,【scrapy文档】
3.Scrapy的案例实战
这部分的主要内容是完成csdn上的课程信息爬取,并存储入库。跟着老师的演示完成后,现在来回顾一下几个主要的步骤,包括需要注意的点,仅供参考,如有遗漏,纯属不够熟练,期待进步空间。
- 创建项目 :在指定的项目路径下,打开命令行界面,使用【scrapy startproject csdnedu】;
- 创建爬虫:创建项目成功后,进入项目目录【cd csdnedu】,并使用【scrapy genspider course csdn.edu.net】命令来创建爬虫;
- 爬虫体的完善:此时,已经有一个爬虫项目和具体的爬虫文件course.py在spider文件目录下,使用编译器完成对爬虫文件、Items文件、settings文件的修改,其中爬虫文件的采集规则要针对采集页的网页结构特点以及采集目标的所在位置,有选择性的使用selector、css或re匹配到目标,并使用导入的items中定义好的新item对象,将目标对应值传递给item,最后使用page的特点进行增改,构建新的url并自调爬虫文件中的parse函数完成多页爬取设置;
- 编写存入MySQL:确定可以爬取到采集目标后,确定当前编译环境下装好了pymysql包,导入包对管道文件,也就是pipelines文件进行修改,修改可以新增类MySQLPipeline,其中对open_spider和close_spider两个函数重写,重写内容中open函数中对于sql语句的使用和游标的获取不要忘了,还有函数参数的传递,这个部分侧重可以看下方代码,按我理解的写主要步骤,其中为了将数据库的连接信息可重用,将其写入settings文件 ,并用依赖注入装饰器的方法,将其自调用并实例化传递给spider。这个部分有两个地方容易犯错,第一个是传递过程中SQL语句中“%s”所对应的数据库中属性,不要大写%S,不要写%d,第二个是3306是端口号,不是字符串,切记不要使用“ ”引号传递,直接赋值即可,另外,确定数据库名称及表名和属性值都是提前创建好的,这部分是采集新增操作,需要先创建好再运行项目;
- 调试设置:经过一遍检查,代码确实无误,在settings文件中继续修改,将ItemPipeline及后面的{ }花括号内容取消注释,添加一行新增类的说明,即第4步骤中对于MysqlPipeline,同上行300的一样就行,只是修改300为301。
- 运行检查:差不多就完成了。运行并且查看结果,进行调试。成功看数据库结果,不成功的话看报错的地方,修复。重复以上直到数据库表中出现爬取结果数据。
上方是对于步骤的回忆体,一不小心写多了,过于具体,代码过程中有写注释,可以参看代码理解。以下:
items文件对于目标信息类的设计:
# -*- coding: utf-8 -*-
# items.py文件
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html
import scrapy
class EducsdnItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
# 课程信息item类:课程标题、URL地址、图片、讲师、时长、价格
title = scrapy.Field()
url = scrapy.Field()
pic = scrapy.Field()
teacher = scrapy.Field()
time = scrapy.Field()
price = scrapy.Field()
pass
course文件是爬虫体,关键的部分,其中对于目标网页的解析和页数控制、封装信息传递,都需要放在这个部分,是genspider命令后自动生成的。
# -*- coding: utf-8 -*-
# courses.py文件
import scrapy
import educsdn.items
from educsdn.items import EducsdnItem
class CoursesSpider(scrapy.Spider):
name = 'courses'
allowed_domains = ['edu.csdn.net']
start_urls = ['https://edu.csdn.net/courses/o280_k/p1']
page = 1
def parse(self, response):
# 解析课程信息
dlist =response.selector.css("div.course_item")
# 遍历课程信息并封装到item
for dd in dlist:
item = EducsdnItem()
item['title'] = dd.css("span.ellipsis-2::text").extract_first()
item['url'] = dd.css("a::attr(href)").extract_first() #属性用attr class直接用名字
item['pic'] = dd.css("img::attr(src)").extract_first()
item['teacher'] = dd.css("span.lecname::text").extract_first()
item['time'] = dd.css("span.course_lessons::text").extract_first()
item['price'] = dd.css("i::text").extract_first()
yield item
self.page += 1
if self.page < 3:
next_url = 'https://edu.csdn.net/courses/o280_k/p'+str(self.page)
url = response.urljoin(next_url)
yield scrapy.Request(url=url,callback=self.parse)
可以通过代码运行结果看到,确实采集到了这部分信息。
下面是入库对比:
入库前后,这里有一个问题在于价格的获取都是None,目测有两部分原因,一个是爬虫体内的price选取条件不够准确
,另一个是目标对象中有一部分是会员免费观看课程,所以价格栏没有。前者可以通过代码调试和优化采集规则,后者可以通过异常数据等进行处理。
代码放在github上了,首页个人简介中有。
调整了下代码,将数据过滤了一下,重新跑了一遍。新数据有点好看!
好,这部分练习就到这里,具体代码,放入github上了。
还是那一句!刻意练习,每日精进!冲吧!