什么是框架
集成了很多功能,并且具有很强通用性的一个项目模板。(或理解成一个项目的半成品)
scrapy框架
爬虫中封装好的一个明星框架。
功能:
- 高性能的持久化存储操作
- 异步的数据下载
- 高性能的数据解析
- 分布式
环境安装
Mac & Linux
pip isntall scrapy
Windows
1、 wheel
pip install wheel
2、下载Twisted
https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted 下载自己对应得版本(我的是py3.9)
输入pip install 将下载的文件拖入安装
pip install d:\Users\YQ17454\Downloads\Twisted-20.3.0-cp39-cp39-win_amd64.whl
pywin32
pip install pywin32
scrapy
pip install scrapy
测试安装成功
终端中输入 scrapy,无报错及成功,不成功的注意版本
scrapy基本使用
基本使用
创建一个工程
终端输入:
scrapy startproject demo
UA伪装
在配置文件中
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'
切换到项目文件中
cd .\first\
在spiders文件下,创建一个爬虫文件(必须有)
spider是爬虫类(spiders下的爬虫文件)的父类
scrapy genspider first_demo www.baidu.com
自动生成的first_demo.py:
import scrapy
class FirstDemoSpider(scrapy.Spider):
# 爬虫文件的名称 唯一标识
name = 'first_demo'
# 允许的域名: 用来限制start_urls 中可以发送请求的url,基本不使用
# allowed_domains = ['www.baidu.com']
# 起始的url列表(可有多个):自动的被scrapy进行请求
start_urls = ['http://www.baidu.com/', 'http://www.qq.com/']
# 用作于数据解析,response为请求成功后响应的响应对象。
# parse 会被调用多次,取决于请求的url个数(start_urls )
def parse(self, response):
print(response)
执行工程
scrapy crawl first_demo
输出的很多是 log日志
不输出log日志
scrapy crawl first_demo --nolog
执行后,并没有打印响应数据,原因是配置文件:
ROBOTSTXT_OBEY = True,遵从robots协议
学习过程中,修改为 ROBOTSTXT_OBEY = False
再次运行工程
完全不显示日志信息,出错了也不会提示,所以在配置文件中添加 LOG_LEVEl = ‘ERROR’
只输出错误类型的log
scrapy数据解析
爬取糗事百科的作者和内容
https://www.qiushibaike.com/text/
创建一个工程,配置文件
爬虫文件源码:
import scrapy
class QsbkSpider(scrapy.Spider):
name = 'qsbk'
# allowed_domains = ['https://www.qiushibaike.com/']
start_urls = ['https://www.qiushibaike.com/text/']
def parse(self, response):
# 解析段子 作者的名称和内容
author = response.xpath(
'//*[@id="qiushi_tag_123876908"]/div[1]/a[2]/h2/text()')[0].extract()
content = response.xpath(
'//*[@id="qiushi_tag_123876908"]/a[1]/div/span//text()').extract()
content = ''.join(content)
print(author, content)
scrapy持久化存储
基于终端指令
好处:简洁高效便捷
缺点:局限性比较强(数据存储指定类型)
要求:只可以将parse方法的返回值存储到本地的文本文件中
只可以存储这几种类型的数据:
‘json’, ‘jsonlines’, ‘jl’, ‘csv’, ‘xml’, ‘marshal’, ‘pickle’
import scrapy
class QsbkSpider(scrapy.Spider):
name = 'qsbk'
# allowed_domains = ['https://www.qiushibaike.com/']
start_urls = ['https://www.qiushibaike.com/text/']
def parse(self, response):
# 解析段子 作者的名称和内容
author = response.xpath(
'//div[@id="content"]/div/div[2]/div/div[1]//h2/text()').extract()
content = response.xpath(
'//div[@id="content"]/div/div[2]/div/a[1]/div/span[1]//text()').extract()
print(author, content)
dic = {
'author': author,
'content': content
}
return dic
终端执行命令:
scrapy crawl qsbk -o ./qiubai.csv
基于管道
好处:通用性强(数据库、本地)
确定:些许繁琐
编码流程
- 数据解析
- 在item类(文件 items.py)中定义相关属性
- 将解析到的数据封装存储到item类型的对象
- 将item类型的对象提交给管道进行持久化存储操作
- 在管道类(文件 pipelines.py)的process_item中将接收到的item对象中的数据进行持久化存储
- 配置文件中开启管道
items.py
import scrapy
class QiushiItem(scrapy.Item):
# define the fields for your item here like:
author = scrapy.Field()
content = scrapy.Field()
# pass
pipelines.py
from itemadapter import ItemAdapter
class QiushiPipeline:
fp = None
def open_spider(self, spider): # 重写父类的一个方法:该方法只在开始爬虫的时候被调用一次
print('start')
self.fp = open('./qiubai.txt', 'w', encoding='utf-8')
def process_item(self, item, spider): # 每调用一次执行一次
author = item['author']
content = item['content']
self.fp.write('作者们:' + author + '\n' + '内容:' + content)
return item
def close_spider(self, spider): # 父类结束中调用一次
print('end')
self.fp.close()
修改 settings.py
ITEM_PIPELINES = {
'qiushi.pipelines.QiushiPipeline': 300,
}
爬虫文件:
import scrapy
from qiushi.items import QiushiItem
class QsbkSpider(scrapy.Spider):
name = 'qsbk'
# allowed_domains = ['https://www.qiushibaike.com/']
start_urls = ['https://www.qiushibaike.com/text/']
def parse(self, response):
# 解析段子 作者的名称和内容
author = response.xpath(
'//div[@id="content"]/div/div[2]/div/div[1]//h2/text()').extract()
content = response.xpath(
'//div[@id="content"]/div/div[2]/div/a[1]/div/span[1]//text()').extract()
# 将解析到的数据封装存储到item类型的对象
item = QiushiItem()
item['author'] = ''.join(author)
item['content'] = ''.join(content)
# 将item提交给管道
yield item