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 ...
随机推荐
- Django框架_URLconf、Views、template、ORM
目录: 一.Django-MTV MTV模型 Django基本命令 视图层之路由配置系统(views) 视图层之视图函数(views) 模板层(template) 二.Django-model基础 O ...
- 001-搭建spring boot项目
1.第一步.file--new--project. 2.spring initializr--project sdk--default--next 3. 4.spring boot--选择依赖项--n ...
- vue生命周期探究(二)
vue生命周期探究(二) 转载自:https://segmentfault.com/a/1190000008923105 上一章我们介绍了vue的组件生命周期和路由勾子,这一章,让我们来看看在vue- ...
- SHUOJ - 算法题1 矩阵连乘问题(区间dp)
链接:http://acmoj.shu.edu.cn/problem/24/ 分析:设\(dp[i][j]\)为矩阵\(A[i:j]\)所需的最少乘法次数,则有dp方程:\(dp[i][j]=min\ ...
- scala和正则表达式常用基础知识示例
http://www.cnblogs.com/deerchao/archive/2006/08/24/zhengzhe30fengzhongjiaocheng.html . 匹配除换行符以外的 ...
- Hbase Region Server整体架构
Region Server的整体架构 本文主要介绍Region的整体架构,后续再慢慢介绍region的各部分具体实现和源码 RegionServer逻辑架构图 RegionServer职责 1. ...
- Ubuntu&Linux系统出现文件系统只读Read-only file system 的快速解决方法
问题描述: 周末运行盘平台服务程序,周一来操作系统卡顿,主进程已退出,重启进程时提示Read-only file system:新建目录和其他chmod -R等等操作都提示Read-only file ...
- 20145324 《Java程序设计》第9周学习总结
20145324 <Java程序设计>第9周学习总结 教材学习内容总结 第十六章 1.JDBC是java联机数据库的标准规范.它定义了一组标准类与接口,标准API中的接口会有数据库厂商操作 ...
- Nginx配置X-Forwarded-Proto
需求 最近公司在做全站https,架构上面有Nginx+tomcat Nginx+php,且nginx配置了ssl,tomcat和php项目使用https协议 但是,发送的是https url请求,p ...
- ubuntu环境下nginx的编译安装以及相关设置
一.基本的编译与安装 1.安装依赖项 sudo apt-get update sudo apt-get install build-essential zlib1g-dev libpcre3 libp ...