-
所谓框架就是一个被集成了很多功能且具有很强通用性的项目模板
-
学习框架就是学习集成好的各种功能的特性和作用 进阶探索框架的底层
-
scrapy是一个专门用于异步爬虫的框架。
- 高性能的数据分析、请求发送、持久化存储、全站数据爬取、中间件,分布式...
-
环境安装
- mac和linux pip install scrapy
- window分5个步骤
- 1.pip3 install wheel
- 2.下载twisted http://www.lfd.uci.edu/~gohlke/pythonlibs/#teisted
1,2步是为第3步服务的 twisted就是一个异步的架构 - 3.安装twisted
进入下载目录 执行 pip install Twisted-20.3.0-cp38-cp38m-win_amd64.whl
twisted是异步架构 被作用在scrapy中
如果安装报错 需要更换另一版本安装即可 - 4.pip install pywin32
- 5.pip install scrapy
- 6.测试 在cmd中scrapy,如果没报错,安装成功
-
scrapy的基本使用
-
创建一个工程
- Console 是python控制台 Terminal是终端 命令行模式
- 执行 scrapy startproject ProName(项目名,在选定的目录下创建)
- 目录结构
- spiders 文件夹叫爬虫目录 必须存放一个爬虫源文件
- settings.py 工程的配置文件
- cd 到ProName目录 创建一个爬虫源文件
- scrapy genspider spiderName www.xxx.com(生成一个spiderName.py文件,源文件创造好了)
- 编写对应的代码在爬虫文件中(后继操作,暂时不用)
-
执行工程
- scrapy crawl spiderName 是创建的py文件
- 执行工程后 默认会输出工程所有的日志信息
- 指定类型日志的输出:
- 1.settings.py中加入 LOG_LEVEL = 'ERROR' 打印日志会消失
- 2.在settings.py中 ROBOTSTXT_OBEY=False 要改成True 不改的话,目前测试https能返回正常response http不能返回
- 3.可以把User-Agent写在配置文件中
- 最后 重新执行scrapy crawl spiderName 要在ProName路径下执行
- 碰到了连接超时问题 暂时没解决
- windows下 其实是自己创建的网址无法访问报错 拓展知识
- netstat -ano|findstr 端口号 (查看在用端口) 随后 taskkill /pid PID(进程号) /f 杀掉端口
- windows下 其实是自己创建的网址无法访问报错 拓展知识
- scrapy crawl spiderName 是创建的py文件
-
爬虫文件内容阐述
- name 爬虫文件名称 该文件的唯一标识
- start_urls 起始url列表 存储的都是url url可以被自动进行get请求的发送
- parse方法 请求后的数据解析操作
-
文件说明
- scrapy.cfg 项目的配置信息,主要为Scrapy命令行工具提供一个基础的配置信息。(真正爬虫相关的配置信息在settings.py文件中)
- items.py 设置数据存储模板,用于结构化数据,如:Django的Model
- pipelines 数据处理行为,如:一般结构化的数据持久化
- settings.py 配置文件,如:递归的层数、并发数,延迟下载等
= spiders 爬虫目录,如:创建文件,编写爬虫规则
-
settings.py 需要做的操作
- 1.禁止robots ROBOTSTXT_OBEY = False
- 2.指定日志类型 LOG_LEVEL = 'ERROR'
- 3.UA伪装 USER_AGENT = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE'
-
数据解析
- 用scrapy自己的xpath做解析 代码写完后 在终端执行scrapy crawl spidername
- 得到的结果是selector对象 需要的字符串对象被存储在data属性中
- 取出方式 变量名2 = 变量名1.xpath()[0].extract() extract就是将属性值取出
- 正式书写是 xpath().extract_first() 意思是将列表中第一个元素表示的selector对象中的data值取出
- 直接使用列表调用extract() 可以将列表中每个列表元素表示的selector中的data取出 结果为列表
-
持久化存储
-
基于终端指令:
- 局限:该种方式只可以将parse方法的返回值存储到本地指定后缀的文本文件中
- 命令:scrapy crawl spiderName -o ./qiubai.csv
- 注意:持久化存储对应的文本文件类型只能为:json jsonlines jl csv xml marshal pickle
- 优点:简洁便捷高效
简单代码 点击查看
class FirstSpider(scrapy.Spider): # 爬虫文件名称: 当前源文件的唯一标识 name = 'duanzi' # 允许的域名 这里是做域名限定的 所以通常会把allowed_domains注释掉 # allowed_domains = ['www.baidu.com'] # 起始的url列表 只可以存储url # 作用:列表中存储的url都会被进行get请求的发送 start_urls = ['https://duanzixing.com/微段子/'] # 数据解析 parse方法调用的次数完全取决于请求的次数 response表示的就是服务器返回的响应对象 # 将解析到的数据做持久化存储 def parse(self, response): article_list = response.xpath('/html/body/section/div/div/article') all_data = [] for article in article_list: # title = article.xpath('.//h2/a/text()')[0].extract() title = article.xpath('.//h2/a/text()').extract_first() dic = { 'title': title, } all_data.append(dic) return all_data # 终端执行 scrapy crawl duanzi -o duanzi.csv
-
基于管道(重点)(步骤):
-
1.在爬虫文件中进行数据解析
-
2.在item.py中定义相关的属性
- 步骤1中解析出了几个字段的数据 在此就定义几个属性
Filed()定义好的属性当做是一个万能类型的属性
name=scrapy.Field()
- 步骤1中解析出了几个字段的数据 在此就定义几个属性
-
3.在爬虫文件中将解析的数据封装存储到item类型的对象中
-
在代码文件中 既scrapy genspider spiderName www.xxx.com创建的文件中
from 文件夹名称.items import items文件中的类名 -
随后实例化一个item类型的对象 将解析到的数据存储到该对象中
在类方法中 item = items中的类名()
注意 item调用属性不能用. 只能用item[''] = 获取到的数据
如 item['title'] = title操作实例 点击查看
def parse(self, response): all_data = [] # 数据解析名称和内容 article_lst = response.xpath('') for article in article_lst: title = article.xpath().extract_first() # 实例化一个item类型的对象 将解析到的数据存储到该对象中 item = duanziproItem() # 不可以通过.的形式调用属性 item['title'] = title
-
-
4.将item类型的对象提交给管道进行持久化存储的操作
在sprid文件的parse方法中 最后录入 yield item 是将item对象提交给管道 -
5.在管道文件(pipelines.py)中, 接收爬虫文件提交过来的Item类型对象,且对其进行任意形式的持久化存储操作
工程里只能有一个管道文件, 但是可以有多个管道类简单代码 点击查看
# 文件中有管道类 管道类的的方法是用来接受item对象的 # 一次只能接收一个item 说明该方法会被调用多次 # 参数item就是接受到的tiem对象 # 如果有多个爬虫文件 不能执行一个就打开一次文件 所以要重写父类的2个方法 让文件只打开一次 写入多次 def open_spider(self, spider): print('我是open_spider(), 我只会在爬虫开始的时候执行一次') self.fp = open('xx.txt', 'w', encoding='utf-8') # 文件需要关闭 所以需要重写父类的另一个方法 def close_spider(self, spider): print("我是close_spider(), 我只会在爬虫结束的时候执行一次!") self.fp.close() def process_item(self, item, spider): print(item) # item其实就是一个字典 self.fp.write(item['title']+' ') # 将item存储到文件 return item
-
6.在配置文件中开启管道机制
在配置文件中有 ITEM_PIPELINES = {'XXX.pipelines.xxxPipeline': 300,}
300表示优先级,数字越小 优先级越高
-
-
基于管道实现数据的备份
- 将爬取到的数据分别存储到不同的载体
- 实现:将数据一份存储到mysql 一份存储到redis
- 问题:管道文件中的一个管道类表示怎样一组操作?
- 一个管道类对应一种形式的持久化存储操作 如果将数据存储到不同的载体中就需要使用多个管道类。
- 定义好了三个管道类 将数据写入到三个载体中进行存储
-
item不会依次提交给三个管道类
-
爬虫文件中的item只会被提交给优先级最高的那一个管道类
-
优先级高的管道类需要在process_item中实现return item就传递给下一个即将执行的管道
-
如果redis报错 需要将redis模块指定为2.10.6即可 pip install -U redis==2.10.6
简单实例 写入mysql 点击查看
import mysql # 将数据存储到mysql中 在pipelines管道文件中写一个类 class MysqlPileLine(object): conn = None # 链接对象和文件句柄一样 只能创建一次 def open_spider(self, spider): self.conn = pymysql.Connect(host='127.0.0.1', port=3306, user='root', password='567913', db='lj') print(conn) def process_item(self, item, spider): self.cursor = self.conn.cursor() sql = 'insert into duanziwang values (%s, %s)' try: self.cur.execute(sql, [item['title'], item['content']]) self.conn.commit() except Exception as e: print(e) self.conn.rollback() def close_spider(self, spider): self.cursor.close() self.conn.close()
简单实例 写入redis 点击查看
from redis import Redis class RedisPileLine(object): conn = None def open_spider(self, spider): self.conn = Redis(host='127.0.0.1', port=6379) print(self.conn) def process_item(self, item, spider): sql.conn.lpush('duanziData', item)
-
-
-
-
scrapy手动请求发送实现的全站数据爬取
- yield srapy.Request(url, callback) # 这个是GET请求
- callback指定解析函数 用于解析数据
- yield scrapy.FormRequest(url, callback, formdata) # 这个是POST请求
- formdata字典 请求参数
- yield srapy.Request(url, callback) # 这个是GET请求
-
为什么start_urls列表中的url会被自动进行get请求的发送?
-
因为列表中的url其实是被start_requests这个父类方法实现的get请求发送
点击查看代码
``` #父类方法:这个是该方法的原始实现 def start_requests(self): for u in self.start_urls: yield scrapy.Request(url=u, callback=self.parse) ``` </details>
-
-
如何将start_urls中的url默认改成post请求发送?
-
重写start_requests方法即可
点击查看代码
``` def start_requests(self): for u in self.start_urls: yield scrapy.FormRequst(url=u, callback=self.parse) ``` </details>
-