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 ...
随机推荐
- vertical-align和line-height的深入应用
vertical-align和line-height的深入应用 本文的重点是了解vertical-align和line-height的使用 涉及到的名词:基线,底端,行内框,行框,行间距,替换元素及非 ...
- Creating an AVI in memory with C++
Creating an AVI in memory with C++ The following example demonstrates how an avi file is comp ...
- Linux系统——进程和计划任务管理
进程和计划任务管理 一.进程和程序的关系 进程:在CPU及内存中运行的程序代码:动态执行的代码:每个进程可以创建一个或多个进程 程序:保存在硬盘.光盘等介质中的可执行代码和数据:静态保存的代码 二.基 ...
- The 15th UESTC Programming Contest Preliminary B - B0n0 Path cdoj1559
地址:http://acm.uestc.edu.cn/#/problem/show/1559 题目: B0n0 Path Time Limit: 1500/500MS (Java/Others) ...
- NetBeans 启动时出现 Invalid jdkhome specified提示
执行 NetBeans 出现如下文字内容: Invalid jdkhome specifiedCannot locate java installation in specifired jdkhome ...
- 【Linux学习】2.Linux常见命令行
记录学习Linux 系统的相关知识点,欢迎大家拍砖交流,一起成长:QQ:2712192471 作者背景:前端开发工程师 | Python | web安全爱好者 Linux命令行: 系统关机重启 s ...
- git删除本地分支和删除远程分支
引言: 切换分支的时候命令打错了,git checkout 后面没有跟分支名,结果git status,很多delete的文件,直接冒冷汗,git add ,commit 之后发现本地与远程确实是删除 ...
- CF1157D N Problems During K Days(简单构造)
题目 题目 原数据是水成啥样了,\(<\longrightarrow <=,>=\longrightarrow <=,\)这也能过 被\(hack\)后身败名裂 做法 简单的贪 ...
- Eclipse FindBugs插件
在线安装: Update Site:http://findbugs.cs.umd.edu/eclipse 本地安装: 1.首先从findbugs网站下载插件:http://findbugs.sourc ...
- [BZOJ3669]魔法森林
Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节 ...