scrapy基础使用
简介:
Scrapy:为了爬去网站数据而编写的一款应用框架,即集成了相应功能且具有很强通用性的项目模板。
功能:
- 高性能异步下载
- 解析操作
- 持久化存储等
- 代理和cookie
- 日志等级和请求传参
- CrawlSpider
- 基于redis的分布式爬虫
安装:linux用pip install scrapy安装即可,win安装查找其他资料
基础使用:
1.创建一个工程
命令:scrapy startproject firstBlood
目录结构:
pipelines.py 处理数据持久化处理相关操作
items.py 设置数据存储模板,用于结构化数据,入django的model
scrapy.cfg 项目主配置文件(无需修改)
settings.py 配置文件
spiders 爬虫目录,使用scrapy genspider命令创建的文件会存放在这里
2.在工程目录下创建一个爬虫文件
- 进入工程目录
- scrapy genspider 爬虫文件名称 起始url
- scrapy genspider qiushibaike https://www.qiushibaike.com/
import scrapy class FirstSpider(scrapy.Spider): #爬虫文件的名称:可以通过爬虫文件的名称定位到某一个具体的爬虫文件 name="qiushibaike" #允许的域名:只可以爬去指定域名下的页面数据 allowed_domains=['www.qiushibaike.com'] #起始url:当前工程将要爬取的页面对应的url,可以添加多个url,但需符合allowed_domains start_urls=["https://www.qiushibaike.com/"] #解析方法:当执行工程的时候,获取的页面数据将由parse方法来负责解析 def parse(self,response): #response:根据起始url列表发起请求,请求成功后返回的响应对象 #parse的返回值必须为迭代器对象或者空 #获取响应页面中的页面数据 page_text=response.text print(page_text)
3.编写配置文件
#不遵循robots协议 ROBOTSTXT_OBEY=False #对请求身份进行伪装 USER_AGENT="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0"
4.启动
scrapy crawl 文件名称
#参数:
--nolog 禁用日志输
数据解析
需求:爬取糗事百科中段子内容和作者
- 创建一个工程:scrapy startproject qiubaiPro
- 创建爬虫文件:
- cd qiubaiPro
- scrapy genspider qiubai www.qiushibaike.com/text
- 编写爬虫文件:数据解析建议使用xpath,scrapy已经集成xpath接口
# -*- coding: utf-8 -*- import scrapy class QiubaiSpider(scrapy.Spider): name = 'qiubai' allowed_domains = ['www.qiushibaike.com/text'] start_urls = ['http://www.qiushibaike.com/text/'] def parse(self, response): div_list=response.xpath("//div[@id='content-left']/div") for div in div_list: author=div.xpath("./div/a[2]/text()") #非直系节点,用// content=div.xpath(".//div[@class='content']/span/text()")
- 配置文件编写,禁用ROBOTSTXT协议,修改User-Agent
- 执行工程
数据持久化
存储方式:
存储到磁盘
- 基于终端指令存储
- parse返回一个可迭代类型的对象(存储解析到的页面内容)
- 使用终端指令完成数据存储到指定磁盘文件中的操作 scrapy crawl qiubai -o qiubai.csv --nolog
# -*- coding: utf-8 -*- import scrapy class QiubaiSpider(scrapy.Spider): name = 'qiubai' #allowed_domains = ['www.qiushibaike.com'] start_urls = ['https://www.qiushibaike.com/text/'] def parse(self, response): div_list=response.xpath("//div[@id='content-left']/div") #用于返回可迭代器对象 data_list=[] for div in div_list: #xpath解析到的指定内容被存储到了selecter对象,可以用extract()方法提取数据值 #author=div.xpath("./div/a[2]/h2/text()").extract()[0] #推荐使用extract_first()方法,extract()[0]会可能会出错,如没有获取到内容就会出现index错误 author=div.xpath("./div/a[2]/h2/text()").extract_first() #非直系节点,用// content=div.xpath(".//div[@class='content']/span/text()").extract()[0] data_dict={ "author":author, "content":content } data_list.append(data_dict) return data_list
- 基于管道存储
- 代码实现流程
- 将解析到的页面数据,存储到items中
import scrapy from qiubaiPro.items import QiubaiproItem class QiubaiSpider(scrapy.Spider): name = 'qiubai' #allowed_domains = ['www.qiushibaike.com'] start_urls = ['https://www.qiushibaike.com/text/'] def parse(self, response): div_list=response.xpath("//div[@id='content-left']/div") for div in div_list: #推荐使用extract_first()方法,extract()[0]会可能会出错,如没有获取到内容就会出现index错误 author=div.xpath("./div/a[2]/h2/text()").extract_first() #非直系节点,用// content=div.xpath(".//div[@class='content']/span/text()").extract()[0] item=QiubaiproItem() item["author"]=author item["content"]=content #将item对象用yield提交给管道文件 yield item
#items.py文件 import scrapy class QiubaiproItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() author=scrapy.Field() content=scrapy.Field()
- 使用yield将items对象提交给管道文件进行处理
- 在pipelines文件中编写代码完成数据存储相关的操作
#pipelines文件 class QiubaiproPipeline(object): #接收爬虫文件提交过来的item对象,并且对item对象中存储的页面数据进行持久化操作 #参数:item:接收到的item对象 def process_item(self, item, spider): author=item["author"] content=item["content"] with open("./qiubai_pipe.txt","w",encoding="utf-8") as fp: fp.write(author+":"+content+"\n\n\n") return item
-
修改版的pipelines.py
#pipelines.py class QiubaiproPipeline(object): fp=None #在整个爬虫过程中,该方法只会在爬虫开始的时候调用一次 def open_spider(self,spider): self.fp=open("./qiubai_pipe.txt","w",encoding="utf-8") #接收爬虫文件提交过来的item对象,并且对item对象中存储的页面数据进行持久化操作 #参数:item:接收到的item对象 #每当爬虫给管道提交一次item,则该方法执行一次 def process_item(self, item, spider): author=item["author"] content=item["content"] self.fp.write(author+":"+content+"\n\n\n") #关闭爬虫会调用一次 def close_spider(self,spider): self.fp.close()
- 在配置文件中开启管道操作,然后启动爬虫操作 scrapy crawl qiubai --nolog
#settings.py文件 # See https://doc.scrapy.org/en/latest/topics/item-pipeline.html #300表示优先级 ITEM_PIPELINES = { 'qiubaiPro.pipelines.QiubaiproPipeline': 300, }
- 将解析到的页面数据,存储到items中
- 代码实现流程
存储到数据库
编码流程:
- 将解析到的页面数据,存储到items中
- 使用yield将items对象提交给管道文件进行处理
- 在pipelines文件中编写代码完成数据存储相关的操作
- 在配置文件中开启管道操作,然后启动爬虫操作 scrapy crawl qiubai --nolog
mysql存储pipelines文件编写
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#pipelines.py import pymysql class QiubaiproPipeline(object): #编写想数据库中存储数据的相关代码 conn=None #链接数据库 def open_spider(self,spider): self.conn=pymysql.Connect(host="127.0.0.1",port=3306,user="root",password="123456.com",db="qiubai") def process_item(self, item, spider): SQL="insert into qiubai values('%s','%s')" % (item['author'],item['content']) self.cursor=self.conn.cursor() try: self.cursor.execute(sql) self.conn.commit() except Exception as e: print(e) self.conn.rollback() return item #关闭游标和链接 def close_spider(self,spider): self.cursor.close() self.conn.close()
redis存储pipelines文件编写
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import redis class QiubaiproPipeline(object): #编写想数据库中存储数据的相关代码 conn=None #链接redis数据库 def open_spider(self,spider): self.conn=redis.Redis(host="127.0.0.1",port=6379) def process_item(self, item, spider): data={ "author":item["author"], "content":item["content"] } self.conn.lpush("qiubai",data) return item #关闭链接 def close_spider(self,spider): self.conn.close()
数据存储到多个平台
在pipelines文件中自定义处理类管道类
#数据存储到本地文件中 class QiuBaiByFiles(object): def process_item(self, item, spider): print("写入到文件中") return item #数据存储到MySQL数据库中 class QiuBaiByMysql(object): def process_item(self, item, spider): print("写入到MySQL中") return item #数据存储到Redis数据库中 class QiuBaiByRedis(object): def process_item(self, item, spider): print("写入到Redis中") return item
在settings.py文件中注册处理类
ITEM_PIPELINES = { # 'qiubaiPro.pipelines.QiubaiproPipeline': 300, 'qiubaiPro.pipelines.QiuBaiByFiles': 300, 'qiubaiPro.pipelines.QiuBaiByMysql': 400, 'qiubaiPro.pipelines.QiuBaiByRedis': 500, }