上药三品,神与气精

曾因酒醉鞭名马 生怕情多累美人


  • 首页

  • 关于

  • 分类

  • 标签

  • 归档

  • 搜索

python装饰器总结

发表于 2019-05-02 | 分类于 web | 阅读次数:
字数统计: 357 | 阅读时长 ≈ 1

写一个记录函数运行时间的装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

from functools import wraps
import time


# 使用直接装饰器 @listener(Monitor)
class Monitor(object):
@staticmethod
def start_monitor():
return time.clock()

@staticmethod
def end_monitor():
return time.clock()


def listener(listen):
def log(func):
@wraps(func)
def wrapper(*args, **kw):
startime = listen.start_monitor()
f = func(*args, **kw)
endtime = listen.end_monitor()
print("total time is {0}".format(startime-endtime))
return f
return wrapper
return log

一个函数 挂多个装饰器的执行顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# -*- coding: utf-8 -*-

import functools


# 采用functools.wraps的目的是为了使装饰器返回的类型始终是func的类型,否则将返回嵌套高阶函数的中的类型,例如返回的是wraper
# 采用参数*args ,**kw是解决函数多参数的问题
def log(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper


# 修饰器参数的情况
def logger(pram):
def log(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('call %s(): and parsms is %s' %(func.__name__,pram))
return func(*args, **kw)
return wrapper
return log


@log
def showMesage(name,age):
print("my name is {0} and my age is {1}".format(name,age))


@logger("hello")
def getMessage(name,age):
print("my name is {0} and my age is {1}".format(name,age))

# 添加多个修饰器来拓展所需的功能
@log
@logger("hello15466")
def recieveMessage(name,age):
print("my name is {0} and my age is {1}".format(name,age))


if __name__=='__main__':
# showMesage("ddd",21)
# getMessage("aaa",43)
recieveMessage("ccc",34)

类装饰器

带参数的装饰器

python-web的未来

发表于 2019-05-01 | 分类于 web | 阅读次数:
字数统计: 546 | 阅读时长 ≈ 1

没有人愿意从事即将过时的技术 学习过气的技术


Django 主要是为web开发服务的

基于MVC的MTV模型

非常适合开发基于PC的传统网站,因为它同时包括了后端的开发(逻辑层,数据库层) 和前端的开发(如模板语言,样式)。基于PC的网站和自适应(responsive)的手机网站不会消失,不过其重要性会随着手机APP和小程序等的普及而逐渐降低。即使对于开发传统网站,Django也只有在后台开发上有些优势,在前端仍需要借助流行的JS框架如Vue.js才能开发出互动性强且符合未来审美趋势的优秀网站来。

最近几年及未来几年更流行的开发模式肯定是前后端分离。现代网络应用Web APP或大型网站一般是一个后台,然后对应各种客户端(iOS, android, 浏览器)。由于客户端的开发语言与后台的开发语言经常不一样,这时需要后台能够提供可以跨平台跨语言的一种标准的资源或数据(如Json格式)供前后端沟通,这就是Web API(网络应用程序结口)的作用了。Django本身开发不了符合REST规范的Web API, 不过借助django-rest-framework (DRF)可以快速开发出优秀规范的Web API来。所以我们这里要感谢DRF,因为它,Django的应用前景更广了,减少了被淘汰的风险。

  • web开发

一定会有

  • 网络爬虫
  • 计算与数据分析
  • 人工智能
  • 自动化运维
  • 云计算

Python的最强大之处在于模块化和灵活性,而构建云计算的平台的IasS服务的OpenStack就是采用Python的,云计算的其他服务也都是在IasS服务之上的。

  • 网络编程

Python提供了丰富的模块支持sockets编程,能方便快速地开发分布式应用程序。很多大规模软件开发计划例如Zope,Mnet, BitTorrent和Google都在广泛地使用它。

  • 游戏开发

对比flask

python爬虫要点

发表于 2019-05-01 | 分类于 web | 阅读次数:
字数统计: 1.9k | 阅读时长 ≈ 6

分块

  • 抓取
  • 解析
  • 存储
  • 反爬
  • 加速

抓取

爬虫的目标绝大多数是网页 少部分是app

网页分为两种 服务端渲染和客户端渲染

app 分为四种 普通接口 加密参数接口 加密内容接口 非常规协议接口

服务端

有效的信息在HTML页面里

真实的数据 一般通过ajax接口形式进行获取的

服务端渲染 一般基本的http库 就可以爬取

客户端

寻找 Ajax 接口,此种情形可以直接使用 Chrome/Firefox 的开发者工具直接查看 Ajax 具体的请求方式、参数等内容,然后用 HTTP 请求库模拟即可,另外还可以通过设置代理抓包来查看接口,如 Fiddler/Charles。

模拟浏览器执行,此种情形适用于网页接口和逻辑较为复杂的情况,可以直接以可见即可爬的方式进行爬取,如可以使用 Selenium、Splinter、Spynner、pyppeteer、PhantomJS、Splash、requests-html 等来实现。

直接提取 JavaScript 数据,此种情形适用于真实数据没有经过 Ajax 接口获取,而是直接包含在 HTML 结果的某个变量中,直接使用正则表达式将其提取即可。

模拟执行 JavaScript,某些情况下直接模拟浏览器执行效率会偏低,如果我们把 JavaScript 的某些执行和加密逻辑摸清楚了,可以直接执行相关的 JavaScript 来完成逻辑处理和接口请求,比如使用 Selenium、PyExecJS、PyV8、js2py 等库来完成即可。


对于普通无加密接口,这种直接抓包拿到接口的具体请求形式就好了,可用的抓包工具有 Charles、Fiddler、mitmproxy。

对于加密参数的接口,一种方法可以实时处理,例如 Fiddler、mitmdump、Xposed 等,另一种方法是将加密逻辑破解,直接模拟构造即可,可能需要一些反编译的技巧。

对于加密内容的接口,即接口返回结果完全看不懂是什么东西,可以使用可见即可爬的工具 Appium,也可以使用 Xposed 来 hook 获取渲染结果,也可以通过反编译和改写手机底层来实现破解。

对于非常规协议,可以使用 Wireshark 来抓取所有协议的包,或者使用 Tcpdump 来进行 TCP 数据包截获。

解析

基本上两种

css

xpath

一些其他接口 json xml 使用对应的库即可处理

智能解析意思就是说,如果能提供一个页面,算法可以自动来提取页面的标题、正文、日期等内容,同时把无用的信息给刨除。对于智能解析,分为四个方法进行了划分:

readability 算法,这个算法定义了不同区块的不同标注集合,通过权重计算来得到最可能的区块位置。

疏密度判断,计算单位个数区块内的平均文本内容长度,根据疏密程度来大致区分。

Scrapyly 自学习,是 Scrapy 开发的组件,指定⻚页⾯面和提取结果样例例,其可⾃自学习提取规则,提取其他同类⻚页⾯面。

深度学习,使⽤用深度学习来对解析位置进⾏行行有监督学习,需要⼤大量量标注数据。如果能够容忍一定的错误率,可以使用智能解析来大大节省时间。


存储

即选用合适的存储媒介来存储爬取到的结果,这里还是分为四种存储方式来进行介绍。

文件,如 JSON、CSV、TXT、图⽚、视频、⾳频等,常用的一些库有 csv、xlwt、json、pandas、pickle、python-docx 等。

数据库,分为关系型数据库、非关系型数据库,如 MySQL、MongoDB、HBase 等,常用的库有 pymysql、pymssql、redis-py、pymongo、py2neo、thrift。

搜索引擎,如 Solr、ElasticSearch 等,便于检索和实现⽂本匹配,常用的库有 elasticsearch、pysolr 等。

云存储,某些媒体文件可以存到如七⽜牛云、又拍云、阿里云、腾讯云、Amazon S3 等,常用的库有 qiniu、upyun、boto、azure-storage、google-cloud-storage 等。

反爬

现在爬虫已经越来越难了

非浏览器检测

封IP

验证码

封账户

字体反爬等

对于封 IP 的情况,可以分为几种情况来处理:首先寻找手机站点、App 站点,如果存在此类站点,反爬会相对较弱。使用代理,如抓取免费代理、购买付费代理、使用 Tor 代理、Socks 代理等。在代理的基础上维护自己的代理池,防止代理浪费,保证实时可用。搭建 ADSL 拨号代理,稳定高效。

验证码分为非常多种,如普通图形验证码、算术题验证码、滑动验证码、点触验证码、手机验证码、扫二维码等。对于普通图形验证码,如果非常规整且没有变形或干扰,可以使用 OCR 识别,也可以使用机器学习、深度学习来进行模型训练,当然打码平台是最方便的方式。对于算术题验证码,推荐直接使用打码平台。对于滑动验证码,可以使用破解算法,也可以模拟滑动。后者的关键在于缺口的找寻,可以使用图片比对,也可以写基本的图形识别算法,也可以对接打码平台,也可以使用深度学习训练识别接口。对于点触验证码,推荐使用打码平台。对于手机验证码,可以使用验证码分发平台,也可以购买专门的收码设备,也可以人工验证。对于扫二维码,可以人工扫码,也可以对接打码平台。

某些网站需要登录才能爬取,但是一个账号登录之后请求过于频繁会被封号,为了避免封号,可以采取如下措施:寻找手机站点或 App 站点,此种类别通常是接口形式,校验较弱。寻找无登录接口,尽可能寻找⽆无需登录即可爬取的接口。维护 Cookies 池,使⽤用批量账号模拟登录,使⽤时随机挑选可用 Cookies 使⽤即可,实现:https://github.com/Python3WebSpider/CookiesPool。


加速

常见的措施

多线程

多进程

异步

分布式

细节优化

爬虫是网络请求密集型任务,所以使用多进程和多线程可以大大提高抓取效率,如使用 threading、multiprocessing 等。

将爬取过程改成非阻塞形式,当有响应式再进行处理,否则在等待时间内可以运行其他任务,如使用 asyncio、aiohttp、Tornado、Twisted、gevent、grequests、pyppeteer、pyspider、Scrapy 等。

分布式的关键在于共享爬取队列,可以使用 celery、huey、rq、rabbitmq、kafka 等来实现任务队列的对接,也可以使用现成的框架 pyspider、Scrapy-Redis、Scrapy-Cluster 等。

可以采取某些优化措施来实现爬取的加速,如:

  • DNS 缓存
  • 使用更快的解析方法
  • 使用更高效的去重方法
  • 模块分离化管控

如果搭建了分布式,要实现高效的爬取和管理调度、监控等操作,我们可以使用两种架构来维护我们的爬虫项目。

将 Scrapy 项目打包为 Docker 镜像,使用 K8S 控制调度过程。

将 Scrapy 项目部署到 Scrapyd,使用专用的管理工具如 SpiderKeeper、Gerapy 等管理。

python2-3迁移问题

发表于 2019-04-30 | 分类于 web | 阅读次数:
字数统计: 229 | 阅读时长 ≈ 1
  • 使用pathlib 处理更好的路径
  • 类型现在是语言的一部分
  • 运行时类型提示类型检查
  • 使用@表示矩阵的乘法
  • **通配符的使用
  • print函数
  • 数字文字的下划线(千位分隔符)
  • 简单可看的字符串格式化f-string
  • / 和 // 在数学运算当中有着明显的区别
  • 严格的顺序
  • 检查对象为None的合理方案
  • NLP unicode问题
  • 保留了字典和**kwargs的顺序
  • 可迭代对象拆包
  • 提供了更高性能的pickle
  • 更安全的列表推导
  • 更简单的super()
  • IDE能够给出更好的提示
  • 合并多个字典
1
z = {**x, **y}
  • 3.7加入data class类 存储数据对象
  • 自定义对模块属性的访问
  • 内置的断点
1
2

breakout() # 3.7 加入
  • math 当中的常数
  • 整数类型只有 int

代码变得更短 更易读 更安全

提升工作效率的方法论006

发表于 2019-04-29 | 阅读次数:
字数统计: 0 | 阅读时长 ≈ 1
1…8910…109
John Cheung

John Cheung

improve your python skills

543 日志
33 分类
45 标签
RSS
GitHub Email
© 2020 John Cheung
本站访客数:
|
主题 — NexT.Pisces v5.1.4
博客全站共226.3k字