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 ...
随机推荐
- TOSCA自动化测试工具视频资料
https://www.udemy.com/ search 'TOCSA' 找到两个免费资料学习
- 通过Java编码获取String分行字符串的内容
代码案列: import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException ...
- Oracle中验证非空的函数NVL(),NVL2()总结
1.NVL()函数 NVL函数的格式如下: NVL(expr1,expr2) 含义是:如果oracle第一个参数为空那么显示第二个参数的值,如果第一个参数的值不为空,则显示第一个参数本来的值. 2 N ...
- 【读书笔记】《深入浅出nodejs》第五章 内存控制
海量请求+长时间运行 -> 内存控制 -> 一切资源高效循环利用 1. V8的垃圾回收机制与内存限制 在Node中通过JavaScript使用内存时,只能使用部分内存(64位系统下约1.4 ...
- Remote System Explorer Operation总是运行后台服务,卡死eclipse
阿里云 > 教程中心 > android教程 > Remote System Explorer Operation总是运行后台服务,卡死eclipse Remote System E ...
- An Example for Javascript Function Scoping and Closure
1. An Real World Example In the patron detail page of the CRM system I'm working with, there’re larg ...
- Juniper SRX防火墙简明配置手册(转)
在执行mit命令前可通过配置模式下show命令查看当前候选配置(Candidate Config),在执行mit后配置模式下可通过run show config命令查看当前有效配置(Active co ...
- Windows下才有blat进行命令行邮件发送
1.先下载blat.exe文件,下载地址: https://sourceforge.net/projects/blat/files/ 2.解压后只需要blat.exe即可,进入此文件夹,运行如下脚本进 ...
- 05_zookeeper_原生API使用1(更新)
1. java方式操作远端zookeeper集群概述 步骤:下载zookeeper压缩包并解压, 创建java工程,导入zookeeper相关jar包 (1)下载zookeeper压缩包 http:/ ...
- harbor 管理Helm Chart包
官方网站:https://github.com/goharbor/harbor官方用户手册:https://github.com/goharbor/harbor/blob/master/docs/us ...