scrapy初识
-
什么是框架?
- 所谓的框架简单通用解释就是就是一个具有很强通用性并且集成了很多功能的项目模板,该模板可被应用在不同的项目需求中。也可被视为是一个项目的半成品。
-
如何学习框架?
- 对于刚接触编程或者初级程序员来讲,对于一个新的框架,只需要掌握该框架的作用及其各个功能的使用和应用即可,对于框架的底层实现和原理,在逐步进阶的过程中在慢慢深入即可。
-
什么是scrapy?
- Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架,非常出名,非常强悍。其内部已经被集成了各种功能(高性能异步下载,队列,分布式,解析,持久化等)。对于框架的学习,重点是要学习其框架的特性、各个功能的用法即可。
scrapy基本使用
-
环境安装:
- linux和mac操作系统:
- pip install scrapy
- windows系统:
- pip install wheel
- 下载twisted,下载地址为http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
- 安装twisted:pip install Twisted‑17.1.0‑cp36‑cp36m‑win_amd64.whl
- pip install pywin32
- pip install scrapy
- 测试:在终端里录入scrapy指令,没有报错即表示安装成功!
- linux和mac操作系统:
-
scrapy使用流程:
- 创建工程:
- scrapy startproject ProName
- 进入工程目录:
- cd ProName
- 创建爬虫文件:
- scrapy genspider spiderName www.xxx.com
- 编写相关操作代码
- 执行工程:
- scrapy crawl spiderName
- 创建工程:
爬虫文件剖析:
import scrapy
class QiubaiSpider(scrapy.Spider):
name = 'qiubai' #应用名称
#允许爬取的域名(如果遇到非该域名的url则爬取不到数据,一般使用的时候把它注释)
allowed_domains = ['https://www.qiushibaike.com/']
#起始爬取的url
start_urls = ['https://www.qiushibaike.com/']
#访问起始URL并获取结果后的回调函数,该函数的response参数就是向起始的url发送请求后,获取的响应对象.该函数返回值必须为可迭代对象或者NUll
def parse(self, response):
print(response.text) #获取字符串类型的响应内容
print(response.body) #获取字节类型的相应内容
配置文件settings.py修改:
#添加如下内容:
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36' #伪装请求载体身份
ROBOTSTXT_OBEY = False #可以忽略或者不遵守robots协议
LOG_LEVEL = 'ERROR' #在终端只显示错误等级的日志
scrapy基于xpath数据解析操作
爬取糗事百科的段子数据
import scrapy
class SecondSpider(scrapy.Spider):
name = 'second'
# allowed_domains = ['www.second.com']
start_urls = ['https://www.qiushibaike.com/text/']
def parse(self, response):
# xpath为response中的方法,可以将xpath表达式直接作用于该函数中
# 解析:作者的名称+段子内容
div_list = response.xpath('//*[@id="content"]/div/div[2]')
'''
[<Selector xpath='//*[@id="content"]/div/div[2]' data='<div class="col1 old-style-col1">\n\n\n\n...'>]
'''
for div in div_list:
# xpath返回的是列表,但是列表元素一定是Selector类型的对象
# extract可以将Selector对象中data参数存储的字符串提取出来
author = div.xpath('.//div[1]/a[2]/h2/text()')[0].extract()
author = author.strip('\n') # 过滤空行
# 列表调用了extract之后,则表示将列表中每一个Selector对象中data对应的字符串提取了出来
content = div.xpath('.//a/div/span//text()').extract()
content = ''.join(content)
content = content.strip('\n') #过滤空行
print(author,content)
scrapy的数据持久化存储
基于终端指令的持久化存储
保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的形式写入指定格式的文件中进行持久化操作。
import scrapy
class SecondSpider(scrapy.Spider):
name = 'second'
# allowed_domains = ['www.second.com']
start_urls = ['https://www.qiushibaike.com/text/']
def parse(self, response):
# 解析:作者的名称+段子内容
div_list = response.xpath('//*[@id="content"]/div/div[2]')
'''
[<Selector xpath='//*[@id="content"]/div/div[2]' data='<div class="col1 old-style-col1">\n\n\n\n...'>]
'''
all_data = [] # 存储所有解析到的数据
for div in div_list:
# xpath返回的是列表,但是列表元素一定是Selector类型的对象
# extract可以将Selector对象中data参数存储的字符串提取出来
author = div.xpath('.//div[1]/a[2]/h2/text()')[0].extract()
author = author.strip('\n') # 过滤空行
# 列表调用了extract之后,则表示将列表中每一个Selector对象中data对应的字符串提取了出来
content = div.xpath('.//a/div/span//text()').extract()
content = ''.join(content)
content = content.strip('\n') #过滤空行
# 将解析到的内容封装到字典中
dic = {
'author':author,
'content':content
}
# 将数据存储到all_data这个列表中
all_data.append(dic)
return all_data
输入指令:scrapy crawl second -o ./second.csv即可存储
执行指令:
执行输出指定格式进行存储:将爬取到的数据写入不同格式的文件中进行存储
- scrapy crawl 爬虫名称 -o xxx.json
- scrapy crawl 爬虫名称 -o xxx.xml
- scrapy crawl 爬虫名称 -o xxx.csv
基于终端指令:
----- 要求:只可以将parse方法的返回值存储到本地的文本文件中
----- 注意:持久化存储对应的文本文件的类型只可以为:‘json’, ‘jsonlines’, ‘jl’, ‘csv’, ‘xml’, ‘marshal’, 'pickle
----- 指令:scrapy crawl xxx -o filePath
----- 好处:简介高效便捷
----- 缺点:局限性比较强(数据只可以存储到指定后缀的文本文件中)
基于管道的持久化存储操作
推荐使用这种方式。
scrapy框架中已经为我们专门集成好了高效、便捷的持久化操作功能,我们直接使用即可。要想使用scrapy的持久化操作功能,我们首先来认识如下两个文件:
items.py:数据结构模板文件。定义数据属性。
pipelines.py:管道文件。接收数据(items),进行持久化操作。
持久化流程:
1.爬虫文件爬取到数据后,需要将数据封装到items对象中。
2.使用yield关键字将items对象提交给pipelines管道进行持久化操作。
3.在管道文件中的process_item方法中接收爬虫文件提交过来的item对象,然后编写持久化存储的代码将item对象中存储的数据进行持久化存储
4.settings.py配置文件中开启管道
爬虫文件:second.py
import scrapy
# 导入items.py中的QiutuItem类
from qiutu.items import QiutuItem
class SecondSpider(scrapy.Spider):
name = 'second'
# allowed_domains = ['www.second.com']
start_urls = ['https://www.qiushibaike.com/text/']
def parse(self, response):
# 解析:作者的名称+段子内容
div_list = response.xpath('//*[@id="content"]/div/div[2]')
'''
[<Selector xpath='//*[@id="content"]/div/div[2]' data='<div class="col1 old-style-col1">\n\n\n\n...'>]
'''
for div in div_list:
# xpath返回的是列表,但是列表元素一定是Selector类型的对象
# extract可以将Selector对象中data参数存储的字符串提取出来
author = div.xpath('.//div[1]/a[2]/h2/text()')[0].extract()
# 列表调用了extract之后,则表示将列表中每一个Selector对象中data对应的字符串提取了出来
author = author.strip('\n') #过滤空行
content = div.xpath('.//a/div/span//text()').extract()
content = ''.join(content) # 将列表变为字符串
content = content.strip('\n') #过滤空行
# 将解析到的数据封装至items对象中
item = QiutuItem() # 实例化 QiutuItem类
item['author'] = author # 将author中的内容添加到item对象的author属性中
item['content'] = content
# 提交item到管道文件(pipelines.py)
yield item
items文件:items.py
import scrapy
class QiutuItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
author = scrapy.Field() #存储作者
content = scrapy.Field() #存储段子内容
管道文件:pipelines.py
class QiutuPipeline(object):
# 定义一个文件描述符属性
fp = None
# 重写父类的一个方法:
# 开始爬虫时,执行一次
def open_spider(self,spider):
print('开始爬虫.......')
self.fp = open('./spider.txt','w',encoding='utf-8')
# 因为该方法会被执行调用多次,所以文件的开启和关闭操作写在了另外两个只会各自执行一次的方法中。
# 专门用来处理item类型对象
# 该方法可以接收爬虫文件提交过来的item对象
# 该方法每接收到一个item就会被调用一次
def process_item(self, item, spider):
author = item['author']
content = item['content']
# 将爬虫程序提交的item进行持久化存储
self.fp.write(author+': \n'+content+'\n')
return item
# 重写父类的一个方法:结束爬虫时,执行一次
def close_spider(self,spider):
print('爬虫结束!')
self.fp.close()
配置文件settings.py:
ITEM_PIPELINES = {