day38 爬虫之Scrapy + Flask框架
s1617day3
内容回顾:
Scrapy
- 创建project
- 创建爬虫
- 编写
- 类
- start_urls = ['http://www.xxx.com']
- def parse(self,response):
yield Item对象
yield Request对象
- pipeline
- process_item
@classmethod
- from_clawer
- open_spider
- close_spider
配置
- request对象("地址",回调函数)
- 执行
高性能相关:
- 多线程【IO】和多进程【计算】
- 尽可能利用线程:
一个线程(Gevent),基于协程:
- 协程,greenlet
- 遇到IO就切换
一个线程(Twisted,Tornado),基于事件循环:
- IO多路复用
- Socket,setBlocking(Flase)
今日内容:
- Scrapy
- Cookie操作
- Pipeline
- 中间件
- 扩展
- 自定义命令
- 其他
- scrapy-redis
- Tornado和Flask
- 基本流程
内容详细:
1. Scrapy
- start_requests
- 可迭代对象
- 生成器
内部iter()
from scrapy.crawler import Crawler
Crawler.crawl
def start_requests(self):
for url in self.start_urls:
yield Request(url=url,callback=self.parse)
# return [Request(url=url,callback=self.parse),]
- cookie
cookie_jar = CookieJar()
cookie_jar.extract_cookies(response, response.request)
- pipeline
- 5个方法
- process_item
- return item
- raise DropItem()
- 去重规则
DUPEFILTER_CLASS = 'sp2.my_filter.MyDupeFilter'
from scrapy.utils.request import request_fingerprint
class MyDupeFilter(object):
def __init__(self):
self.visited = set()
@classmethod
def from_settings(cls, settings):
return cls()
def request_seen(self, request):
fp = request_fingerprint(request)
if fp in self.visited:
return True
self.visited.add(fp)
def open(self): # can return deferred
pass
def close(self, reason): # can return a deferred
pass
def log(self, request, spider): # log that a request has been filtered
pass
from scrapy.utils.request import request_fingerprint
from scrapy.http import Request
obj1 = Request(url='http://www.baidu.com?a=1&b=2',headers={'Content-Type':'application/text'},callback=lambda x:x)
obj2 = Request(url='http://www.baidu.com?b=2&a=1',headers={'Content-Type':'application/json'},callback=lambda x:x)
v1 = request_fingerprint(obj1,include_headers=['Content-Type'])
print(v1)
v2 = request_fingerprint(obj2,include_headers=['Content-Type'])
print(v2)
- 自定义命令
- 目录
xx.py
Class Foo(ScrapyCommand)
run方法
- settings
COMMANDS_MODULE = "sp2.目录"
- scrapy xx
- 下载中间件
- __init__
- from_crawler
- process_request
- None
- response
- request
- process_response
- process_exception
应用:
- 定制请求头(代理)
- HTTPS
注意:
默认代理规则:from scrapy.downloadermiddlewares.httpproxy import HttpProxyMiddleware
设置代理两种方式
- 环境变量
os.environ['xxxxxxxxxxx_proxy']
os.environ['xxxxxxxxxxx_proxy']
os.environ['xxxxxxxxxxx_proxy']
os.environ['xxxxxxxxxxx_proxy']
程序启动之前,先设置
import os
os.environ['xxxxxxxxxxx_proxy'] = "sdfsdfsdfsdfsdf"
- 中间件
...
- 爬虫中间件
class SpiderMiddleware(object):
def __init__(self):
pass
@classmethod
def from_cralwer(cls,cralwer):
return cls()
def process_spider_input(self,response, spider):
"""
下载完成,执行,然后交给parse处理
:param response:
:param spider:
:return:
"""
pass
def process_spider_output(self,response, result, spider):
"""
spider处理完成,返回时调用
:param response:
:param result:
:param spider:
:return: 必须返回包含 Request 或 Item 对象的可迭代对象(iterable)
"""
return result
def process_spider_exception(self,response, exception, spider):
"""
异常调用
:param response:
:param exception:
:param spider:
:return: None,继续交给后续中间件处理异常;含 Response 或 Item 的可迭代对象(iterable),交给调度器或pipeline
"""
return None
def process_start_requests(self,start_requests, spider):
"""
爬虫启动时调用
:param start_requests:
:param spider:
:return: 包含 Request 对象的可迭代对象
"""
return start_requests
# return [Request(url='http://www.baidu.com'),]
- 自定义扩展
from scrapy import signals
class MyExtension(object):
def __init__(self):
pass
@classmethod
def from_crawler(cls, crawler):
obj = cls()
crawler.signals.connect(obj.xxxxxx, signal=signals.engine_started)
crawler.signals.connect(obj.rrrrr, signal=signals.spider_closed)
return obj
def xxxxxx(self, spider):
print('open')
def rrrrr(self, spider):
print('open')
EXTENSIONS = {
'sp2.extend.MyExtension': 500,
}
- Https证书,自定义证书
默认:
DOWNLOADER_HTTPCLIENTFACTORY = "scrapy.core.downloader.webclient.ScrapyHTTPClientFactory"
DOWNLOADER_CLIENTCONTEXTFACTORY = "scrapy.core.downloader.contextfactory.ScrapyClientContextFactory"
自定义:
DOWNLOADER_HTTPCLIENTFACTORY = "scrapy.core.downloader.webclient.ScrapyHTTPClientFactory"
DOWNLOADER_CLIENTCONTEXTFACTORY = "sp2.https.MySSLFactory"
from scrapy.core.downloader.contextfactory import ScrapyClientContextFactory
from twisted.internet.ssl import (optionsForClientTLS, CertificateOptions, PrivateCertificate)
class MySSLFactory(ScrapyClientContextFactory):
def getCertificateOptions(self):
from OpenSSL import crypto
v1 = crypto.load_privatekey(crypto.FILETYPE_PEM, open('/Users/wupeiqi/client.key.unsecure', mode='r').read())
v2 = crypto.load_certificate(crypto.FILETYPE_PEM, open('/Users/wupeiqi/client.pem', mode='r').read())
return CertificateOptions(
privateKey=v1, # pKey对象
certificate=v2, # X509对象
verify=False,
method=getattr(self, 'method', getattr(self, '_ssl_method', None))
)
- 其他:配置
参考地址:http://www.cnblogs.com/wupeiqi/articles/6229292.html
2. pip3 install scrapy-redis
需求:10个爬虫
组件: scrapy-redis,将去重规则和调度器放置到redis中。
流程:连接redis,指定调度器时,调用去重规则.request_seen方法
# 连接redis
# REDIS_HOST = 'localhost' # 主机名
# REDIS_PORT = 6379 # 端口
REDIS_URL = 'redis://user:pass@hostname:9001' # 连接URL(优先于以上配置)
# REDIS_PARAMS = {} # Redis连接参数 默认:REDIS_PARAMS = {'socket_timeout': 30,'socket_connect_timeout': 30,'retry_on_timeout': True,'encoding': REDIS_ENCODING,})
# REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient' # 指定连接Redis的Python模块 默认:redis.StrictRedis
# REDIS_ENCODING = "utf-8" # redis编码类型 默认:'utf-8'
# 去重规则(redis中的set集合)
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue' # 默认使用优先级队列(默认),其他:PriorityQueue(有序集合),FifoQueue(列表)、LifoQueue(列表)
SCHEDULER_QUEUE_KEY = '%(spider)s:requests' # 调度器中请求存放在redis中的key
SCHEDULER_SERIALIZER = "scrapy_redis.picklecompat" # 对保存到redis中的数据进行序列化,默认使用pickle
SCHEDULER_PERSIST = True # 是否在关闭时候保留原来的调度器和去重记录,True=保留,False=清空
SCHEDULER_FLUSH_ON_START = True # 是否在开始之前清空 调度器和去重记录,True=清空,False=不清空
SCHEDULER_IDLE_BEFORE_CLOSE = 10 # 去调度器中获取数据时,如果为空,最多等待时间(最后没数据,未获取到)。
SCHEDULER_DUPEFILTER_KEY = '%(spider)s:dupefilter' # 去重规则,在redis中保存时对应的key
REDIS_START_URLS_AS_SET = False
REDIS_START_URLS_KEY = '%(name)s:start_urls'
方式一:
REDIS_URL = 'redis://user:pass@hostname:9001' # 连接URL(优先于以上配置)
# REDIS_PARAMS = {} # Redis连接参数 默认:REDIS_PARAMS = {'socket_timeout': 30,'socket_connect_timeout': 30,'retry_on_timeout': True,'encoding': REDIS_ENCODING,})
# REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient' # 指定连接Redis的Python模块 默认:redis.StrictRedis
# REDIS_ENCODING = "utf-8" # redis编码类型 默认:'utf-8'
# 去重规则(redis中的set集合)
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue' # 默认使用优先级队列(默认),其他:PriorityQueue(有序集合),FifoQueue(列表)、LifoQueue(列表)
SCHEDULER_QUEUE_KEY = '%(spider)s:requests' # 调度器中请求存放在redis中的key
SCHEDULER_SERIALIZER = "scrapy_redis.picklecompat" # 对保存到redis中的数据进行序列化,默认使用pickle
SCHEDULER_PERSIST = True # 是否在关闭时候保留原来的调度器和去重记录,True=保留,False=清空
SCHEDULER_FLUSH_ON_START = True # 是否在开始之前清空 调度器和去重记录,True=清空,False=不清空
SCHEDULER_IDLE_BEFORE_CLOSE = 10 # 去调度器中获取数据时,如果为空,最多等待时间(最后没数据,未获取到)。
SCHEDULER_DUPEFILTER_KEY = '%(spider)s:dupefilter' # 去重规则,在redis中保存时对应的key
class ChoutiSpider(scrapy.Spider):
name = 'chouti'
allowed_domains = ['chouti.com']
cookies = None
cookie_dict = {}
start_urls = ['http://dig.chouti.com/',]
def index(self, response):
print('爬虫返回结果',response,response.url)
方式二:
REDIS_START_URLS_AS_SET = False
REDIS_START_URLS_KEY = '%(name)s:start_urls'
from scrapy_redis.spiders import RedisSpider
class ChoutiSpider(RedisSpider):
name = 'chouti'
allowed_domains = ['chouti.com']
def index(self, response):
print('爬虫返回结果',response,response.url)
********************* 基本使用 *********************
类,继承scrapy_redis
参考博客:http://www.cnblogs.com/wupeiqi/articles/6912807.html
3. Flask Web框架
- pip3 install flask
- Web框架:
- 路由
- 视图
- 模板渲染
- flask中无socket,依赖 实现wsgi协议的模块: werkzeug
- URL两种添加方式:
方式一:
@app.route('/xxxxxxx')
def hello_world():
return 'Hello World!'
方式二:
def index():
return "Index"
app.add_url_rule('/index',view_func=index)
- 路由系统:
- 固定
@app.route('/x1/')
def hello_world():
return 'Hello World!'
- 不固定
@app.route('/user/<username>')
@app.route('/post/<int:post_id>')
@app.route('/post/<float:post_id>')
@app.route('/post/<path:path>')
@app.route('/login', methods=['GET', 'POST'])
@app.route('/xx/<int:nid>')
def hello_world(nid):
return 'Hello World!'+ str(nid)
- 自定制正则
@app.route('/index/<regex("\d+"):nid>')
def index(nid):
return 'Index'
- 视图
- 模板
- message
- 中间件
- Session
- 默认:加密cookie实现
- 第三方:Flask-Session
redis: RedisSessionInterface
memcached: MemcachedSessionInterface
filesystem: FileSystemSessionInterface
mongodb: MongoDBSessionInterface
sqlalchemy: SqlAlchemySessionInterface
- 蓝图(文件夹的堆放)
- 安装第三方组件:
- Session: Flask-Session
- 表单验证:WTForms
- ORM: SQLAchemy
参考博客:http://www.cnblogs.com/wupeiqi/articles/7552008.html
4. Tornado
- pip3 install tornado
参考博客:http://www.cnblogs.com/wupeiqi/articles/5702910.html
课堂代码:https://github.com/liyongsan/git_class/tree/master/day38
day38 爬虫之Scrapy + Flask框架的更多相关文章
- 爬虫之scrapy框架
解析 Scrapy解释 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中.其最初是为了页面抓取 (更确切来说, 网络抓 ...
- 5、爬虫之scrapy框架
一 scrapy框架简介 1 介绍 Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速.简单.可扩展的方式从网站中提取所需的数据.但目前Sc ...
- golang学习笔记17 爬虫技术路线图,python,java,nodejs,go语言,scrapy主流框架介绍
golang学习笔记17 爬虫技术路线图,python,java,nodejs,go语言,scrapy主流框架介绍 go语言爬虫框架:gocolly/colly,goquery,colly,chrom ...
- Python学习---爬虫学习[scrapy框架初识]
Scrapy Scrapy是一个框架,可以帮助我们进行创建项目,运行项目,可以帮我们下载,解析网页,同时支持cookies和自定义其他功能. Scrapy是一个为了爬取网站数据,提取结构性数据而编写的 ...
- 网络爬虫值scrapy框架基础
简介 Scrapy是一个高级的Python爬虫框架,它不仅包含了爬虫的特性,还可以方便的将爬虫数据保存到csv.json等文件中. 首先我们安装Scrapy. 其可以应用在数据挖掘,信息处理或存储历史 ...
- 爬虫 之 scrapy框架
浏览目录 介绍 安装 项目结构及爬虫应用简介 常用命令行工具 Spiders爬虫 Selectors选择器 Item Pipeline 项目管道 Downloader Middleware下载中间件 ...
- python爬虫之scrapy框架
Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中.其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的, 也可以 ...
- Python网络爬虫之Scrapy框架(CrawlSpider)
目录 Python网络爬虫之Scrapy框架(CrawlSpider) CrawlSpider使用 爬取糗事百科糗图板块的所有页码数据 Python网络爬虫之Scrapy框架(CrawlSpider) ...
- Python3 爬虫之 Scrapy 框架安装配置(一)
博客地址:http://www.moonxy.com 基于 Python 3.6.2 的 Scrapy 爬虫框架使用,Scrapy 的爬虫实现过程请参照本人的另一篇博客:Python3 爬虫之 Scr ...
随机推荐
- k8s-离线安装k8s
1.开始 目标 coreos的igniton.json有很强的可配置性,通过安装时指定集群配置的ignition.json, 安装完成后打开https://{{Master_IP}}:6443/ui直 ...
- 微信小程序组件action-sheet
操作反馈action-sheet:官方文档 Demo Code: Page({ data: { actionSheetHidden: true, actionSheetItems: ['item1', ...
- Spring入门学习推荐
该作者的 spring 博客很好,作为学习用 简介 https://blog.csdn.net/column/details/15088.html?&page=1 https://blog.c ...
- java 并发——内置锁
坚持学习,总会有一些不一样的东西. 一.由单例模式引入 引用一下百度百科的定义-- 线程安全是多线程编程时的计算机程序代码中的一个概念.在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同 ...
- 『NiFi 学习之路』简介
『NiFi 学习之路』简介 『NiFi 学习之路』入门 -- 下载.安装与简单使用 『NiFi 学习之路』资源 -- 资料汇总 『NiFi 学习之路』把握 -- 架构及主要组件 『NiFi 学习之路』 ...
- XVII Open Cup named after E.V. Pankratiev Grand Prix of Moscow Workshops, Sunday, April 23, 2017 Problem D. Great Again
题目: Problem D. Great AgainInput file: standard inputOutput file: standard outputTime limit: 2 second ...
- HTML5文件上传前本地预览
HTML5之FileReader的使用 HTML5定义了FileReader作为文件API的重要成员用于读取文件,根据W3C的定义,FileReader接口提供了读取文件的方法和包含读取结果的事件模型 ...
- Hexo博客配置笔记
安装Hexo npm install hexo-cli -g cd /blog hexo init 安装next主题 git clone https://github.com/iissnan/hexo ...
- OpenStack之Glance模块
一.Glance服务 1.Glance架构 Glance架构是一个典型的CS架构,提供的也是标准的Rest接口,各个layer分层也是很清楚的. 2.Glance服务 Glance是OpenStack ...
- 20145329《Java程序设计》第四周学习总结
教材学习内容总结 封装.继承.多态 封装:封装类私有数据,让用户无法直接存取. 继承: 定义:避免多个类间重复定义共同行为,就是相同的代码提升为父类,java中只能继承一个父类.用继承的方式编写代码可 ...