scrapy框架
scrapy库“5+2”框架图
上面的图着实看不懂,总结一句话:scrapy框架是一个半成品,它已经把大多数功能实现了使用者只要对少数几个模块进行操作,如spider模块、Downloader模块、Item piplines模块
注:scrapy是使用命令行格式
>scrapy< <command> [options] [args]
scrapy常用命令
命令 | 说明 | 格式 |
startproject | 创建一个新工程 | scrapy startproject <name> [dir] |
genspider | 创建一个爬虫 | scrapy genspider [options] <name> [domain] |
settings | 获得爬虫配置信息 | scrapy settings [options] |
crawl | 运行一个爬虫 | scrapy crawl <spider> |
list | 列出工程中所有的爬虫 | scrapy list |
shell | 启动URL调试命令行 | scrapy shell [URL] |
基于常用命令的实例:
爬取:https://python123.io/ws/demo.html的HTML网页并存储
步骤1.建立一个scrapy爬虫工程
执行 scrapy startproject python123demo
生成的工程目录
python3deom/-------------->外层目录
scrapy.cfg------------>部署scrapy爬虫的配置文件,即放在服务器上并配置相应的操作接口
python23deom/--------->scrapy框架的用户字定义python代码
__int__.py------------>初始化脚本(继承类)
items.pyItems--------->Items代码模板(基础类)
middlewares.py-------->Middlewares代码模板(继承类)
piplines.py----------->Piplines代码模板(继承类)
settings.py----------->scrapy爬虫的配置文件
spiders/-------------->spiders代码模板目录(继承类)
__int__.py----------->初始文件,无需修改
__pycache__/--------->缓存目录,无需修改
步骤2.在工程中产生一个scrapy爬虫
执行 cd python123deom
执行 scrapy genspider deom python123.io 生成一个名为demo的爬虫(在spiders/目录下生成一个deom.py文件)
如下:
# -*- coding: utf-8 -*-
import scrapy
#以面向对象编写的一个类,该类叫demospider,这个类必须是继承scrapy.spider这个类的子类
class DemoSpider(scrapy.Spider):
name = 'demo'#变量name赋值为demo,即当前爬虫的名字叫demo
allowed_domains = ['python123.io']#指最开始用户提交给命令行的域名,即这个爬虫只能爬取这个域名以下的相关链接
start_urls = ['http://python123demo.io/']#以列表形式包含的一个或多个URL,就是scrapy框架所要爬取的初始页面
def parse(self, response):#解析页面的方法(此处初始为空),parse()用于处理响应,解析内容形成字典,发现新的URL爬取请求
pass
步骤3.配置产生的spider爬虫
# -*- coding: utf-8 -*-
import scrapy
#以面向对象编写的一个类,该类叫demospider,这个类必须是继承scrapy.spider这个类的子类
class DemoSpider(scrapy.Spider):
name = 'demo'#变量name赋值为demo,即当前爬虫的名字叫demo
#allowed_domains = ['python123demo.io']#指最开始用户提交给命令行的域名,即这个爬虫只能爬取这个域名以下的相关链接
start_urls = ['http://python123demo.io/ws/demo.html']#以列表形式包含的一个或多个URL,就是scrapy框架所要爬取的初始页面
def parse(self, response):#解析页面的方法(此处初始为空),parse()用于处理响应,解析内容形成字典,发现新的URL爬取请求
fname = response.url.split("/")[-1]#定义一个名字将response的内容保存到一个html文件中,从响应的url链接中提取名字,作为保存为本地的文件名
with open(fname,"wb")as f :#将返回的内容保存为文件
f.write(response.body)
self.log("Saved file %s."%name)
步骤4.运行爬虫,获取网页
执行 scrapy crawl demo
如下;
#以面向对象编写的一个类,该类叫demospider,这个类必须是继承scrapy.spider这个类的子类
class DemoSpider(scrapy.Spider):
name = 'demo'#变量name赋值为demo,即当前爬虫的名字叫demo
#allowed_domains = ['python123demo.io']#指最开始用户提交给命令行的域名,即这个爬虫只能爬取这个域名以下的相关链接
start_urls = ['http://python123demo.io/ws/demo.html']#以列表形式包含的一个或多个URL,就是scrapy框架所要爬取的初始页面
def parse(self, response):#解析页面的方法(此处初始为空),parse()用于处理响应,解析内容形成字典,发现新的URL爬取请求
fname = response.url.split("/")[-1]#定义一个名字将response的内容保存到一个html文件中,从响应的url链接中提取名字,作为保存为本地的文件名
with open(fname,"wb") as f :#将返回的内容保存为文件
f.write(response.body)
self.log("Saved file %s."% fname)
——————————————————————————————————-
yield关键字的使用:
yield 等价于生成器
生成器是一个不断产生值的函数
生成器每次产生一个值(yield语句)函数被唤醒后再产生一个值
#输出小于5的平方值(生成器写法)
def gen(n):
for i in range(n):
yield i**2#生成器每次只返回一个值
for i in gen(5):
print(i," ",end="")
#输出小于5的平方值(普通写法)
def square(n):
ls = [i**2 for i in range(n)]#将所有遍历的所有值返回到列表中,存储空间占用相对较多
return ls
for i in square(5):
print(i," ",end="")
生成器相比一次列出所有内容的优势:
1.更节省存储空间
2.响应更迅速
3.使用更加灵活
——————————————————————————————————
scrapy爬虫的使用步骤:
步骤1.创建一个工程和spider模板
步骤2.编写一个spider
步骤3.编写Item Pipeline
步骤4.优化配置策略
scrapy爬虫的数据类型: Request类
Response类
Item类
Requests类:
定义:Requests对象表示一个HTTP请求,由spider生成,由Downloader执行
使用:class scrapy.http.Request()
.url———->Request对应的请求url的地址
.method——->对应的请求方法,“GET”、“POST”
.headers——>字典型风格的请求头
.body———>请求内容主体,字符串类型
.meta———>用户添加的扩展信息,在scrapy内部模块间传递使用
.copy()——->复制该请求
Response类:
定义:Response对象表示一个HTML响应,由Downloader生成,由spider处理
使用:clss scrapy.http.Response()
.url——->Response对应的url地址
.start—–>HTML状态码,默认是200
.headers——->Respons对应的头部信息
.body——->Respons对应的内容信息,字符串类型
.flags——->一组标记
.request——->产生Reponse类型对应的reequest对象
.copy()——->复制该响应
Item类;
定义:Item对象表示一个从HTML页面中提取页面信息,由spider生成,由Pipeline处理。Item类似字典类型,可以照字典类型操作
===========================================================
实例:爬取股票数据
功能描述
技术路线:scrapy
目标:获取上交所和深交所所有股票的名称和交易信息
输出:保存在文件中
数据网站的确定:
获取股票列表:东方财富网:http://quote.eastmoney.com/stocklist.html
获取个股信息:百度股票:https://gupiao.baidu.com/stock/
单个股票:https://gupiao.baidu.com/stock/sz002439.thml
步骤1.创建一个工程和spider模板
步骤2.编写一个spider
#编写spider模板 # -*- coding: utf-8 -*- import scrapy import re class StockSpider(scrapy.Spider): name = 'stock' start_urls = ['http://quote.eastmoney.com/stocklist.html'] def parse(self, response):#解析页面的函数方法 for href in response.css("a::attr(href)").extract(): try: stock = re.findall(r"[s][hz]\d{6}",href)[0]#通过正则表达式获取东方财富网的股票代码 url ="http://stockdata.stock.hexun.com/" + stock + ".shtml"#生成一个百度股票页面的对应链接 yield scrapy.Request(url,callback=self.parse_stock)#将链接作为新的请求提交给scrapy框架,yield关键词将parse变成一个生成器 except: continue def parse_stock(self,response):#从百度股票的单个页面中提取信息 infoDict = {} stockInfo = response.css(".stock-bets") name = stockInfo.css(".bets-name").extract()[0]#获取股票名字 keyList = stockInfo.cs("dt").extract(0)#获取dt标签 valueList = stockInfo.css("dd").extract()#获取dd标签 for i in range(len(keyList)):#将提取的信息保存在字典中 key = re.findall(r">.*</dt>",keyList[i])[0][1:5] try: val = re.findall(r"\d+\.?.*</dd>",valueList[i])[0][0:-5] except: val = "--" infoDict[key]=val infoDict.update( {"股票名称":re.findall("\s.*\(",name)[0].split()[0] + \ re.findall("\>.*\<",name)[0][1:-1]}) #提取的整个股票页面的相关信息 yield infoDict
步骤3.编写Item Pipeline
#编写Item Pipeline # -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html class BaidustocksPipeline(object): def process_item(self, item, spider): return item class BaidustocksPipeline(object): def open_spider(self,spider):#指当爬虫被调用时对应的Pipeline启动的方法 self.f = open("BaidustockInfo.txt","w") def close_spider(self,spider):#指一个函数关闭时对应的Pipeline方法 self.f.close() def process_item(self,item,spider):#指对每一个item项进行处理时对应的方法 try: line = str(dict(item)) + "\n"#将所有信息写到item中 self.f.write(line) except: pass return item
设置settings.py文件
最后:scrapy crawl <文件名称>运行程序即可