python爬虫五
scrapy框架
相对于很多人来说request并不能满足他们的需求或者说需求太多,导致代码过于复杂,本着简便众人的思想python大牛们携万物可封装的理念为我们封装了scrapy高性能异步爬虫框架,让我们使用起来更加得心应手,在这里我们将对scrapy进行简单地介绍,过于底层的东西我们不去探讨。
安装:
对于Linux系统下的小伙伴可以直接
pip install scrapy
对于win系统下的小伙伴么需要下载安装相关依赖
a. pip3 install wheel
b. 下载twisted http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
c. 进入下载目录,执行
pip3 installTwisted‑17.1.0‑cp35‑cp35m‑win_amd64.whl
d. pip3 install pywin32e. pip3 install scrapy
官网的介绍特别少,其实在我自己看来还可以更少,这是一个高度封装好的爬虫框架,我们可以通过重写其中的类方法或者干脆在其基础上增加函数来完成我们想要的功能,非常强大且使用广泛。
接下来我们创建第一个项目,本文是基于pycharm使用。
scrapy创建:
scrapy startproject 项目名
创建之后我们得到一个项目文件夹
project_name/ scrapy.cfg: #项目主配置信息 project_name/ __init__.py items.py #设置数据存储模板 有点类似Django中应用下models的功能 pipelines.py #管道文件,主要用于执行数据持久化存储 settings.py #配置文件,我们设置的大多配置都在这个文件中 spiders/ #爬虫文件夹将所要执行的文件放在其中 __init__.py
我们得到了一个如此结构的项目文件夹,之后就是进入spiders创建一个我们爬虫文件
cd 项目名 scrapy genspider 文件名 初始路径 #这里的初始路径可以随意写一下,但是必须的
在命令行执行上述命令之后我们得到了一个模板文件
import scrapy class FirstSpider(scrapy.Spider): name = 'first' # allowed_domains = ['www.baidu.com'] #允许爬取的域名,其他域名无法获取数据,一般来说如果不是需求特殊我们都注释掉这行 start_urls = ['https://www.baidu.com/'] #起始url你的爬虫将从这里开启 def parse(self, response): '''回调函数,处理响应结果''' print(response)
当我们通过命令行执行项目 scrapy crawl 应用名时发现遇到了阻碍,原因是我们的配置文件中存在一些无伤大雅的东西
19行:USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' #伪装请求载体身份
22行:ROBOTSTXT_OBEY = False #可以忽略或者不遵守robots协议
修改之后我们就能获得百度响应数据了,如此我们的第一个scrapy项目结束
import scrapy class QiubaiSpider(scrapy.Spider): name = 'qiubai' allowed_domains = ['https://www.qiushibaike.com/'] start_urls = ['https://www.qiushibaike.com/'] def parse(self, response): #xpath为response中的方法,可以将xpath表达式直接作用于该函数中 odiv = response.xpath('//div[@id="content-left"]/div') content_list = [] #用于存储解析到的数据 for div in odiv: #xpath函数返回的为列表,列表中存放的数据为Selector类型的数据。我们解析到的内容被封装在了Selector对象中,需要调用extract()函数将解析的内容从Selecor中取出。 author = div.xpath('.//div[@class="author clearfix"]/a/h2/text()')[0].extract() content=div.xpath('.//div[@class="content"]/span/text()')[0].extract() #将解析到的内容封装到字典中 dic={ '作者':author, '内容':content } #将数据存储到content_list这个列表中 content_list.append(dic) return content_list
我们进行数据爬取的最终目的就是将数据存储进行分析或者其他方式的使用,所以持久化存储就成了比较重要的一环,而scrapy已经为我们封装好了高速高效且将简便的方式管道执行。
持久化流程: 1.爬虫文件爬取到数据后,需要将数据封装到items对象中。 2.使用yield关键字将items对象提交给pipelines管道进行持久化操作。 3.在管道文件中的process_item方法中接收爬虫文件提交过来的item对象,然后编写持久化存储的代码将item对象中存储的数据进行持久化存储 4.settings.py配置文件中开启管道
在讲解实力之前先与大家分享几个我的失误,首先items一定要声明好模板,否则传到管道是无法进行持久化的,二是要用生成器不能return,最后比较重要的就是一定要在settings中开启管道,因为默认情况下是关闭的,一定要开启切记。
import scrapy from secondblood.items import SecondbloodItem class QiubaidemoSpider(scrapy.Spider): name = 'qiubaiDemo' allowed_domains = ['www.qiushibaike.com'] start_urls = ['http://www.qiushibaike.com/'] def parse(self, response): odiv = response.xpath('//div[@id="content-left"]/div') for div in odiv: # xpath函数返回的为列表,列表中存放的数据为Selector类型的数据。我们解析到的内容被封装在了Selector对象中,需要调用extract()函数将解析的内容从Selecor中取出。 author = div.xpath('.//div[@class="author clearfix"]//h2/text()').extract_first() author = author.strip('\n')#过滤空行 content = div.xpath('.//div[@class="content"]/span/text()').extract_first() content = content.strip('\n')#过滤空行 #将解析到的数据封装至items对象中 item = SecondbloodItem() item['author'] = author item['content'] = content yield item#提交item到管道文件(pipelines.py) - items文件:items.py import scrapy class SecondbloodItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() author = scrapy.Field() #存储作者 content = scrapy.Field() #存储段子内容 - 管道文件:pipelines.py # -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html class SecondbloodPipeline(object): #构造方法 def __init__(self): self.fp = None #定义一个文件描述符属性 #下列都是在重写父类的方法: #开始爬虫时,执行一次 def open_spider(self,spider): print('爬虫开始') self.fp = open('./data.txt', 'w') #因为该方法会被执行调用多次,所以文件的开启和关闭操作写在了另外两个只会各自执行一次的方法中。 def process_item(self, item, spider): #将爬虫程序提交的item进行持久化存储 self.fp.write(item['author'] + ':' + item['content'] + '\n') return item #结束爬虫时,执行一次 def close_spider(self,spider): self.fp.close() print('爬虫结束') - 配置文件:settings.py #开启管道 ITEM_PIPELINES = { 'secondblood.pipelines.SecondbloodPipeline': 300, #300表示为优先级,值越小优先级越高 }