swipper项目

  • python可以做三种推导式:列表,字典,集合,还可以做生成器
a = {i:i*3 for i in range(10)}

print(a)
b = {i:j*3 for i,j in zip(range(10), range(10,20)) if i>5}
  • zip返回值是一迭代器,有别于可迭代对象,并以最短作为迭代的次数
  • 集合是无序的,用for进行遍历取出来也不是固定顺序的
for i in {3,4,6,7,8,43,24,242,3453}:
	print(i)
  • 可迭代对象可以做成迭代器等着被迭代
  • 驼峰是两边小写,python的类要首字母大写,推荐用_
  • *d 和**d的用法
  • 字符串可以和数字相乘
  • import 时带下划线的私有属性不会被直接导入进来,需要单独导入,__all__也是跟导入时有关
  • 类属性需要类名+属性进行调用
  • *_的用法
  • 在ipython中可以用? ??进行函数的查看
  • 列表可以相乘,可以扩充列表
  • python timeit的用法
  • \用来转义 还有windows下的路径

赋值和引用

迭代器和生成器

def foo():
	for i in range(10):
		yield i

res = foo()

print(res)

print(next(res))
  • 这里的生成器函数不会马上执行,会在调用next的时候将yield里面的值传递给接受的变量x
def foo():
	print(111)
	yield 222
	print(333)
	yield 444
	print(555)

res = foo()

x = next(res)
print(x)
x = next(res)
print(x)
next(res)
  • 生成器为什么可以被迭代,被调用?
  • 生成器
  • 可迭代对象:str list tuple dict set bytes 内部都实现了__iter__
class My:
	def __iter__(self):
		return self

	def __next__(self):
		return 1



for i in My():
	print(i)

写了一个return1的死循环,因为没有退出条件

class My:
	def __init__(self):
		self.count = 1
	def __iter__(self):
		return self

	def __next__(self):
		if self.count < 6:
			self.count += 1
			return 1
		else:
			raise StopIteration()

for i in My():
	print(i)

My()的对象是一个迭代器,实现了next iter方法
生成器本身就是迭代器,是一种特殊的迭代器

自定义xrange

  • 优点:节省内存,不是一次性创建,惰性求值 思想来源于lisp语言

lambda表达式,迭代器,生成器,装饰器,各种生成器

  • 自定义时要注意没有默认参数的要放在前面
  • https://blog.csdn.net/weixin_40320794/article/details/79367243 否则会报错
class Range:
	def __init__(self, end,start=0, step=1):
		self.start = start
		self.end = end
		self.step = step
	def __iter__(self):
		return self

	def __next__(self):
		if self.start < self.end:
			self.start += self.step
			return self.start
		else:
			raise StopIteration

for i in Range(10):
	print(i)

  • 查看内存占用 sizeof()函数,单位字节
class Range:
	def __init__(self, end,start=0, step=1):
		self.start = start
		self.end = end
		self.step = step
	def __iter__(self):
		return self

	def __next__(self):
		if self.start < self.end:
			self.start += self.step
			return self.start
		else:
			raise StopIteration

a = Range(10)
print(a.__sizeof__())
  • 生成器调用__iter__返回一个生成器
  • 自定义的迭代器调用返回的就是自己的这个对象
  • 可迭代对象调用__iter__返回的是一个迭代器
  • itertools
  • 指针指向内存地址
  • 如果有一个字段想存储任意类型的数据,就可以将这个字段的类型设置为空接口
  • abs返回数字的绝对值
a = 1
b = 2

print(id(a))
print(id(1))
print(id(b))
print(id(2))
b = a
print(id(a))
print(id(1))
print(id(b))
print(id(2))
a = 2
print(id(a))
print(id(1))
print(id(b))
print(id(2))
a = a+1

b = a

print(id(a))
print(id(1))
print(id(b))
print(id(2))
# def foo():
# 	print(3425)

# foo()


# def foo():
# 	x = []
# 	def add(k):
# 		x.append(k)
# 		return x
# 	return add

# res = foo()
# a = res(3)
# a = res(5)

# print(a)
import sys

a = 1
s = 2
a = s
del s

g = sys.getrefcount(a)
print(g)
# class A:
# 	def __call__(self):
# 		print("callable")

# a = A()
# a()
import random

def check(func):
	def wrap():
		result = func()
		if result < 0:
			return 0
		else:
			return result
	return wrap

@check
def foo():
	return random.randint(-10,10)

a = foo()
print(a)

# wrap = check(foo)
# wrap()


# obj = A()![在这里插入图片描述](https://img-blog.csdnimg.cn/20191010164121396.png)
# obj()
# 要实现__call__()
  • 深入理解python

魔法方法

  • name
  • main
  • doc
  • init
  • del:del先执行__del__里面的东西
  • call
  • next
  • iter:初始化
  • new:分配内存,产生对象
  • str:格式化打印对象,在类中定义__str__方法,return init 里面的东西
  • python3中默认继承object
  • python的单例模式__new__
  • add
  • sub
  • and
  • or
  • 可以在类中定义__add__ 魔法方法可以实现不可运算的东西可以进行运算
  • 也可以重载比较运算符(场景,游戏公司一键整理背包需要进行比较)q
  • 容器方法__len__ iter
  • 上下文:enter :with的代码准备 exit:处理后事
  • len() 进行比较只是因为那个对象里面支持__len__ 方法
  • 多继承的问题
  • python的垃圾清除机制
  • len(l) 相当于l.len()
  • 在这里插入图片描述
  • 多继承菱形继承
  • 要用super方法严格按照继承的顺序调用

在这里插入图片描述
在这里插入图片描述

  • python都是引用,go中都是赋值

装饰器:

# 装饰器工厂方法
def deco(n):
	def wrap1(func):
		def wrap2(*args, **kwargs):
			return func(*args, **kwargs)
		return wrap2
	return wrap1
# import itertools
# '''螺旋矩阵
# [description]
# '''
# res = itertools.chain([1,2,3], [4,5,6])  # 可以进行链式迭代
# print(next(res))


'''装饰器

[description]
'''
def deco(func):
	'''a'''
	def wrap(*args, **kwargs):
		'''b'''
		func(*args, **kwargs)
	return wrap
@deco
def foo(a, b):
	'''c'''
	return a + b
print(foo.__doc__)
# def foo():
# 	'''this is a doc
	
# 	[description]
# 	'''
# 	print("hello vue")

# print(foo.__name__)  # 知道自己的名字
# print(foo.__doc__)  # 会打印出注释的内容
import time

'''装饰器

[description]:计时功能
'''
def run_time(run):
	def timer_now(x):
		start = time.time()

		run(x)
		end = time.time()
		print(end-start)
		print("计时完毕")

	return timer_now

class Run():
	def __init__(self):
		print("计时开始")

	@run_time
	def run(self):
		print("I can run")
		# time.sleep(1)
		# print(5)
		# time.sleep(1)
		# print(4)
		# time.sleep(1)
		# print(3)
		# time.sleep(1)
		# print(2)
		# time.sleep(1)
		# print(1)
		res = [i for i in range(100000)]

		print(res)
		print(res.__sizeof__())


a = Run()
a.run()

  • ipython可以执行linux的命令

  • 对象保存在 dict 的里面

  • 动态语言可以在运行时增加或删除一些属性

  • 可以进行动态添加属性,定义完的对象是什么就是什么样子

  • 类本身也是一个对象,可以动态的添加方法

  • 正常在类中创建的对象只是将这个对象添加到字典里

  • 类可以动态添加的方法

  • 在外部对对象进行加减操作,内部的类的属性不会被修改

  • 在这里插入图片描述

  • 当a.z删除时,A.z 不会被删除,有个优先级的概念,当再次去a.z时,会取到790 是类属性中定义的东西

  • python中还提供了三个内建函数 setattr getattr hasattr

  • setattr可以动态的修改,增加属性

  • getattr 获取一个属性

在这里插入图片描述

  • 字典的get方法取不到可以设置一个默认值
  • getattr(a,“oo”, 7777) 也是设置一个默认值7777
  • hasattr:用来检查属性的是否存在某属性
    在这里插入图片描述
  • 用来检查类是否含有什么属性
  • setattr:用来添加属性的操作 getattr:动态获取的本质操作

在这里插入图片描述

  • a.调用变量参数的时候本质就是__getattribute__
  • object 大多数都是由这个对象支撑
  • 在运行的是否先获取到变量
  • __getattr__处理属性或方法的默认行为
  • 钩子函数
  • setattr getattr 钩子函数 可以监听一些东西 ,比如一些金融服务

异常处理

  • 将try except放在 __main__里面永远不会抛异常了
  • 程序必须有刹车,用来保护程序
  • 比如一些金融业务,必须要再三处理
  • 有错误一定要抛出来
  • 带着错误进行运行会有更大的损失
  • Exception时所有类型的父类,要匹配到什么错误就处理什么错误
  • 没有报错的错误最难受,单元测试,断点调式,打日志
  • 在线上的时候用log模块进行处理
  • 某公司进行项目开发,规定,一句try except都不让写
  • 等着报错再进行修改
  • try except里面包的语句越少越好

利用dict做简单的模式匹配

  • 类似于switch语句
  • 用字典进行case
  • 字典的匹配比较快
  • hashtable结构
  • fun = mapping.get(cond,do4)
  • python的缓存 ,会额外的战局一些内存
  • join会节约内存, 一次性申请内存,因为传的是一个列表
  • 可变对象和不可变对象的区别

python性能

  • unicode-》二进制:encode
  • 二进制-》unicode:decode
  • 用列表推导来取代map和filter
  • 用生成器表达式来改写数据量较大的列表推导
  • 尽量用enumerate取代range
  • 了解如何在闭包里使用外围作用域中的变量
  • 考虑用生成起来改成直接返回列表的函数
  • 用数量可变的位置参数减少视觉杂讯 *args
  • 以@classmethod形式的多态去通用地构建对象
  • 用super初始化父类
  • 只在使用Mix-in组件制作工具类时进行多重继承
  • 继承collections.abc以实现自定义的容器类型
  • 考虑用@property来代替属性重构
  • 用__getattr__、__getattribute__和__setatr__实现按需生成的属性
  • 用subprocess模块来管理子进程
  • 考虑用concurrent.futures来实现真正的平行计算
  • 用Queue来协调个线程之间的工作
  • 考虑以contextlib和with语句来改写可复用的try/finally代码
  • 用copyreg实现可靠的pickle操作
  • 应该用datetime模块来处理本地时间,而不是time模块
  • 在重视精确度的场合,应该使用decimal
  • 用tracemalloc来掌握内存的使用及泄露情况
  • Python中的异步程序依赖于 Coroutines(协程) ,它与event loop(事件循环)一同工作

git

  • git checkout file 暂存区回滚到工作区
  • git reset --hard ‘版本号’ 回滚到指定版本的工作区
  • git reset --soft ‘版本号’ 将指定版本回滚到暂存区
  • git reset --mix ‘版本号’ 将指定版本回滚到修改过的内容
  • git log 查看日志信息: 命令(版本号) 作者 时间 版本描述
    • git log --pretty=oneline 日志信息:版本号 版本描述
    • git reflog 日志信息:版本号缩写(7位) HEAD(x) 命令 操作记录
rm file
    git checkout --file     回滚至修改前的状态
 
    rm file
    git add file
    git reset HEAD file
    git checkout --file     回滚至提交到暂存区前的状态
     
    rm file
    git reset --hrad '版本号'  回滚至指定版本号

https://www.cnblogs.com/zhangyafei/p/10307907.html

异步爬虫

import asyncio
import functools
import time
from collections.abc import Iterable

import async_timeout
from pyquery import PyQuery as pq

import aiohttp

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'}


class Request(object):
    """
    用于封装用户请求信息所用
    """

    def __init__(self, url, callback):
        self.url = url
        self.callback = callback


class RequestManager(object):
    def __init__(self):
        self.new_requests = set()
        self.old_requests = set()

    def has_new_request(self):
        """ 判断是否有未爬取的url """
        return self.new_request_size() != 0

    async def get_new_request(self):
        """ 获取一个未爬取的请求 """
        new_request = self.new_requests.pop()
        # 提取之后,将其添加到已爬取的链接中
        self.old_requests.add(new_request)
        return new_request

    async def add_new_request(self, request):
        """ 将新请求添加到未爬取的集合中(单个请求) """
        if request is None:
            return
        if request not in self.new_requests and request not in self.old_requests:
            self.new_requests.add(request)

    async def add_new_requests(self, requests):
        """ 将新请求添加到未爬取的集合中(集合) """
        if requests is None or len(requests) == 0:
            return
        for request in requests:
            self.add_new_request(request)

    def new_request_size(self):
        """ 获取未爬取的url大小 """
        return len(self.new_requests)

    def old_request_size(self):
        """ 获取已爬取的url大小 """
        return len(self.old_requests)


class HTMLParser(object):
    def __init__(self):
        pass

    async def parse(self, response):
        # items = {'name': 'parse'}
        # doc = pq(await response.text())
        # print(doc)
        print('parse---', response.url)
        return [Request(url='http://www.sxmu.edu.cn/', callback=self.next_parse)]
        # yield items

    async def next_parse(self, response):
        doc = pq(await response.text())
        print('next parse', response.url)
        items = {'next_parse': response.url}
        return [items]


class DataMemory(object):
    def __init__(self):
        pass

    async def store_data(self, data):
        print('store data: ', data)

    def to_csv(self):
        pass

    def to_excel(self):
        pass

    def save_mongo(self):
        pass

    def save_redis(self):
        pass

    def save_mysql(self):
        pass


class Crawler(object):
    def __init__(self, urls, loop=None, pool=100):
        self.manager = RequestManager()
        self.parser = HTMLParser()
        self.data_memory = DataMemory()
        self.urls = urls
        self.pool = pool
        self.loop = loop

    def filter_downloaded_urls(self):
        return self.urls

    async def start(self, session, request):
        await self.manager.add_new_request(request)
        while self.manager.has_new_request():
            # 1. 取出新请求
            new_request = await self.manager.get_new_request()
            # 2. 将请求的url进行下载
            url = new_request.url
            sem = asyncio.Semaphore(self.pool, loop=self.loop)
            async with sem:
                print(f'make request to {url}')
                with async_timeout.timeout(60):
                    async with session.get(url=url, headers=headers, verify_ssl=False) as response:
                        if response.status == 200:
                            # 3. 将下载的Html文本进行解析
                            result = await new_request.callback(response)
                            # 4. 判断解析之后返回的数据对象为新请求还是解析的数据
                            if not isinstance(result, Iterable):
                                raise Exception('返回的数据类型不可迭代')
                            for ret in result:
                                if isinstance(ret, Request):
                                    # 5. 如果是新请求,则加入到请求管理器
                                    await self.manager.add_new_request(ret)
                                elif isinstance(ret, dict) and ret:
                                    # 6. 如果是解析的数据,则将数据进行存储
                                    await self.data_memory.store_data(ret)
                                else:
                                    raise Exception(
                                        '返回数据类型或格式不正确,只能返回Request的实例对象或字典的实例对象,且不能为空')
                        else:
                            print(f'{new_request.url}\t请求失败\t{response.status}')

    async def run(self, loop):
        """ 异步执行爬虫项目 """
        print('*******************开始下载***********************')
        self.loop = loop
        conn = aiohttp.TCPConnector(ssl=False,
                                    limit=100,  # 连接池在windows下不能太大, <500
                                    use_dns_cache=True)
        url_list = self.filter_downloaded_urls()
        # astnc with上下文管理器。接收的是的是协程,内部自动关闭到服务器的连接释放资源
        async with aiohttp.ClientSession(connector=conn, loop=loop) as session:
            # await声明程序挂起 await + 异步程序/__await__属性的对象
            datas = await asyncio.gather(*[self.start(session, Request(url=url, callback=self.parser.parse)) for url in url_list])
            for index, url in enumerate(url_list):
                if isinstance(datas[index], Exception):
                    print(f"{index}, {url}: 下载失败 请重新下载:", datas[index])


def timeit(func):
    """
    装饰器: 判断函数执行时间
    :param func:
    :return:
    """
    @functools.wraps(func)
    def inner(*args, **kwargs):
        start = time.time()
        ret = func(*args, **kwargs)
        end = time.time() - start
        if end < 60:
            print(f'花费时间:\t{round(end, 2)}秒')
        else:
            min, sec = divmod(end, 60)
            print(f'花费时间\t{round(min)}分\t{round(sec, 2)}秒')
        return ret
    return inner


@timeit
def main():
    """ 主函数 """
    urls = ['https://www.researchgate.net' for _ in range(100)]
    crawl = Crawler(urls)
    # 创建循环,检测task运行的情况并返回结果
    event_loop = asyncio.get_event_loop()
    event_loop.run_until_complete(crawl.run(event_loop))


if __name__ == '__main__':
    main() 

https://github.com/HuberTRoy/aiohttp-chinese-documentation aiohttp中文文档
三次握手:(打电话,信号不好时)
client —SYN — server:想跟你建立连接
server — ACK+SYN ---- client:同意,再给你一个(减少通信次数)
client -----server

在这里插入图片描述

  • TCP是双向全双工的,我给你发送数据的时候,你也可以给我发数据,收发互不影响
  • 创建----绑定—监听端口,阻塞的等着接受数据—read—write—close
  • 创建—连接—write—read—close
  • 绑定对应连接
  • 多任务:多进程-多线程-多协程
  • 进程属于操作系统 线程属于进程 协程属于线程
  • 内存消耗进程最大 线程消耗:2k左右
  • 进程之间的通信:socket 消息队列 共享内存 UDS 管道 文件
  • 共享内存
  • 进程通信不灵活
  • 多个线程共享一个进程的资源
  • 多个进程对于一个单核CPU不是并行的
  • 进程之间的上下文切换
  • A B 线程(进程)来回执行一些操作 context
  • 进程以时间片来切换,时间片轮转
  • 进程由os来调度 线程由python解释器来调度
  • 时间片轮转是低效的切换方式
  • 改进:算法
  • 服务器最好是利用60-70%
  • 中断有优先级(信号,事件) 本身就是异步的,网络事件发生一种通知机制
  • 中断可以进行回调程序
  • 专门有一个程序监听事件,就是事件驱动
  • 协程+事件驱动
  • 多路复用:事件先由硬件接收到,先通知到操作系统,提供了一套接口,供应用程序调用
  • select poll epoll
  • 10个水壶10个炉子放在10个屋子,水开了通知,不通知就会轮询的查看
  • 系统调用:epoll
  • 协程:协作 多协程共存一个内核级线程
  • python yield:让出cpu,交出控制权,执行后线程会挂起
  • gevent python2里最成熟的实现 用c语言实现
  • tornado 原生的yield语句
  • asyncio
  • 关键字:不允许定义成变量
  • 包可以,但是内容会被覆盖
  • python引入了两个关键字:async await
  • rps:每秒请求量,多进程+多协程
  • https://blog.csdn.net/weixin_30577801/article/details/95280996 asyncio
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值