scrapy框架
-
架构
- 爬虫文件夹:spider
- 管道文件: pipelines.py
- 中间件文件: middlewares.py
- item模块:items.py
- 设置文件 :settings.py
-
相关命令
- 创建scrapy项目:scrapy startproject 项目名
- 创建爬虫文件:
- cd 项目名
- scrapy genspider 爬虫文件名 www.xxx.com
- 执行爬虫文件:scrapy crawl 爬虫文件名
- 不查看日志:scrapy crawl 爬虫文件名 -nolog
- 项目初始化:
- 配置settings:
- UA伪装
- 关闭robot.txt协议
- 添加日志配置LOG_LEVEL
- 配置settings:
- 持久化存储方式
- 基于终端指定的存储
- scrapy crawl 爬虫文件 -o xxx.csv(json,xml,csv....)
- 基于管道持久化存储
- 文件存储
- MySql存储
- Redis存储
- 基于终端指定的存储
需求1:scrapy爬取不得姐首页中段子的内容和作者
1.先创建一个爬虫项目,在命令行输入
scrapy startproject budejiepro
进入项目目录,创建一个爬虫文件命名budejie
cd budejiepro scrapy genspider first www.xxx.com
在项目的spiders中生成一个first.py的爬虫文件
2.开始爬虫之间我们先将setting.py文件中的`ROBOTSTXT_OBEY=True`改成**False**,否则scrapy会根据robots 协议来拒绝访问,我们还需要设置ua,这个准备爬取网站钱需要做的!!
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36' # Obey robots.txt rules ROBOTSTXT_OBEY = False
3.我们打开爬虫文件budejie.py,开始对网页进行爬取
我们一开始配置的爬取网页的起始url为www.xxx.com,这里我们需要手动去修改,也可以一开始就配置正确的url,这里类下的allowed_domains是指允许自动发送请求的域名,只要在这个列表里面的url,scrapy才会自动发送请求,start_urls是起始url,scrapy会自动向起始url发送请求,并且获取响应数据.parse方法是用来实现解析数据,我们接下来的数据解析都在这里面完成
- 我们分析段子和作者所在的标签位置,这里就不做累赘说明,和之前的通用爬虫步骤一样
但是要注意的是,我们爬取出来的作者和段子打印出来的数据会发现他是放在一个selector的选择器内,且这个选择器是放在一个列表内的,所以我们需要利用extract()来取
author = li.xpath('./div[1]/div[2]/a/text()').extract()[0] author = li.xpath('./div[1]/div[2]/a/text()').extract_first()
问题:持久化存储,目前数据只在终端出现 ,返回的数据如果要进行持久化存储,需要封装到一个字典里面
# -*- coding: utf-8 -*- import scrapy class BudejieSpider(scrapy.Spider): name = 'budejie' # allowed_domains = ['www.xxx.com'] start_urls = ['http://www.budejie.com/text/'] def parse(self, response): """ 在这里实现数据解析 :param response: :return: """ li_list = response.xpath('//div[@class="j-r-list"]/ul/li') name_list = list() for li in li_list: #xpath解析方法返回的是一个Selected标签,需要使用.extract()方法获取里面的文本数据 # 如果能够确定返回的列表里面只有一个Selecter标签的话,就可以直接使用extract_first()方法获取文本 # author = li.xpath('./div[1]/div[2]/a/text()').extract()[0] author = li.xpath('./div[1]/div[2]/a/text()').extract_first() content = li.xpath('./div[2]/div/a/text()').extract_first() # 返回的数据如果要进行持久化存储,需要封装到一个字典里面 dic ={ "author":author, "content":content } name_list.append(dic) return name_list
需求2:需求:scrapy管道持久化储存校花网title和img_url
- 爬取思路(忽略基本配置等操作)
1.校花网的爬取其实和前面的不得姐的爬取思路是一致的,这次爬取的难点在于如何管道持久化存储,上面不得姐的例子我们是基于终端指令的持久化存储,通常要将数据封装到一个字典中返回,在通过终端指令的形式写入指定格式的文件中进行持久化操作;现在我们可以轻松的利用scrapy框架为我们设计的高效,便捷的持久化操作,我们可以直接拿来用
2.管道持久化存储会涉及到两个py文件
items.py(数据结构模板文件,定义数据属性)
pipelines.py(管道文件,用来接收数据items,进行持久化操作)
3 持久化流程
校花.py爬取到网站数据后,需要将数据封装到items对象中
我们在校花.py文件中使用yield关键字将items对象提交给pipelines管道持久化操作
在管道文件中的process_item方法中接收爬虫文件提交过来的item对象,然后编写持久化存储的代码将item对象中存储的数据进行持久化存储
settings.py配置文件中开启管道
# 首先先在setting.py文件中配置UA伪装,关闭robots.txt协议的日志设置 USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36' # Obey robots.txt rules ROBOTSTXT_OBEY = False LOG_LEVLE="ERROR" #这一步是配置文件中开启管道 ITEM_PIPELINES = { 'xiaohuapro.pipelines.XiaohuaproPipeline': 300,}
import scrapy from xiaohuapro.items import XiaohuaproItem class XiaohuaSpider(scrapy.Spider): name = 'xiaohua' # allowed_domains = ['www.xxx.com'] start_urls = ['http://www.521609.com/meinvxiaohua/'] def parse(self, response): li_list = response.xpath('//div[@class="index_img list_center"]/ul/li') for li in li_list: title = li.xpath('./a[2]/text()| ./a[2]/b/text()').extract_first() img_url = "http://www.521609.com" + li.xpath('./a[1]/img/@src').extract_first() print(title,img_url) # 从items.py文件中导入XiaohuaproItem类,并实例化一个item对象 item = XiaohuaproItem() # # # 需要将爬取到的数据添加到对象中的属性中,其实可以讲item对象理解成为一个字典,通过字典的草错将数据存储 item["title"] = title item["img_url"] = img_url # # 如何将item对象提交到管道?yield生成器知识~~ # # 只需要使用yield关键字就可以将item对象提交到管道 # #这个操作必须要放在循环里面,向管道提交多次数据 # yield item
import scrapy class XiaohuaproItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() title = scrapy.Field() img_url = scrapy.Field()
import pymysql import redis class XiaohuaproPipeline(object): f = None def open_spider(self,spider): print("开始爬虫") self.f = open('./xiaohua.txt',"w",encoding="utf-8") def process_item(self, item, spider): """ 在这里实现管道持久化存储 由于爬虫文件中会多次向管道提交数据,所以这个方法会执行很多次 :param item: 就是items.py文件中scrapy.Item类实例化的一个对象 :param spider: :return: """ title = item["title"] img_url = item["img_url"] self.f.write(title+":"+img_url+"\n") return item def close_spider(self, spider): self.f.close() print("结束爬虫") class MysqlPipeline(object): conn = None cursor = None def open_spider(self,spider): print("开始爬虫") self.conn = pymysql.Connect(host = "10.0.3.156",port=3306,user="root",password="",db="qishi8",charset="utf8") def process_item(self, item, spider): """ 在这里实现管道持久化存储 由于爬虫文件中会多次向管道提交数据,所以这个方法会执行很多次 :param item: 就是items.py文件中scrapy.Item类实例化的一个对象 :param spider: :return: """ self.cursor = self.conn.cursor() title = item["title"] img_url = item["img_url"] sql = "insert into xiaohua values('{}','{}')".format(title,img_url) try: self.cursor.execute(sql) except Exception as e: self.cursor.rollback() self.conn.commit() return item def close_spider(self, spider): self.cursor.close() self.conn.close() print("结束爬虫")