12.1.爬虫 副知识

浏览器用户跟踪三种方式

  • cookie
  • 隐藏域(每个表单加一个hidden标签,存储用户信息)
  • url重写(url后面跟上用户信息)

cookie与session关系

cookie存储方式

  • 基于浏览器窗口(浏览器关闭,cookie失效)
  • 持久化的cookie(cookie中设置expires)

mysql事物隔离级别分为四种

  • READ-UNCOMMITTED:该事物隔离级别可读取其它事物未提交的结果
  • READ-COMMITTED:该事物隔离级别只会读取已提交的数据,在事务中已更改但未提交的数据不会读取
  • REPEATABLE-READ:该事务隔离级别只会读取已提交的结果,与READ-COMMITTED不同的是,repeatable-read在开启事务的情况下,同一条件的查询返回的结果永远是一致的,无论其它事物是否提交了新的数据
  • SERIALIZABLE:这种隔离级别和repeatable-read类似,只会读取其它事物已提交的内容,有一点不同的地方在于,如果autocommit为false,那么每一条select语句会自动被转化为select … lock in share mode.这样出现一些阻塞情况

查看mysql事物隔离级别方法:

mysql> select @@tx_isolation;

更改mysql事物级别方法

set global transaction isolation leve read committed; 
-- 或者
set tx_isolation = 'repeatable-read';

sql

关系型数据库遵循ACID规则

事务在英文中是transaction,和现实世界中的交易很类似,它有如下四个特性:

1、A (Atomicity) 原子性

原子性很容易理解,也就是说事务里的所有操作要么全部做完,要么都不做,事务成功的条件是事务里的所有操作都成功,只要有一个操作失败,整个事务就失败,需要回滚。

比如银行转账,从A账户转100元至B账户,分为两个步骤:1)从A账户取100元;2)存入100元至B账户。这两步要么一起完成,要么一起不完成,如果只完成第一步,第二步失败,钱会莫名其妙少了100元。

2、C (Consistency) 一致性

一致性也比较容易理解,也就是说数据库要一直处于一致的状态,事务的运行不会改变数据库原本的一致性约束。

例如现有完整性约束a+b=10,如果一个事务改变了a,那么必须得改变b,使得事务结束后依然满足a+b=10,否则事务失败。

3、I (Isolation) 独立性

所谓的独立性是指并发的事务之间不会互相影响,如果一个事务要访问的数据正在被另外一个事务修改,只要另外一个事务未提交,它所访问的数据就不受未提交事务的影响。

比如现在有个交易是从A账户转100元至B账户,在这个交易还未完成的情况下,如果此时B查询自己的账户,是看不到新增加的100元的。

4、D (Durability) 持久性

持久性是指一旦事务提交后,它所做的修改将会永久的保存在数据库上,即使出现宕机也不会丢失。

NoSql

CAP定理(CAP theorem)

在计算机科学中, CAP定理(CAP theorem), 又被称作 布鲁尔定理(Brewer’s theorem), 它指出对于一个分布式计算系统来说,不可能同时满足以下三点:

  • 一致性(Consistency) (所有节点在同一时间具有相同的数据)
  • 可用性(Availability) (保证每个请求不管成功或者失败都有响应)
  • 分隔容忍(Partition tolerance) (系统中任意信息的丢失或失败不会影响系统的继续运作)

CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个。

因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类:

  • CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
  • CP - 满足一致性,分区容忍性的系统,通常性能不是特别高。
  • AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。

数据压缩

  • 先要序列化数据再才能压缩数据

数据压缩(zlib)

zlib.compress压缩
zlib.decompress解压

序列化/反序列化

要实现的功能 可以使用的api
将Python数据类型转换为(json)字符串 json.dumps()
将json字符串转换为Python数据类型 json.loads()
将Python数据类型以json形式保存到本地磁盘 json.dump()
将本地磁盘文件中的json数据转换为Python数据类型 json.load()
将Python数据类型转换为Python特定的二进制格式 pickle.dumps()
将Python特定的的二进制格式数据转换为Python数据类型 pickle.loads()
将Python数据类型以Python特定的二进制格式保存到本地磁盘 pickle.dump()
将本地磁盘文件中的Python特定的二进制格式数据转换为Python数据类型 pickle.load()
以类型dict的形式将Python数据类型保存到本地磁盘或读取本地磁盘数据并转换为数据类型 shelve.open(

redis

# redis有两种数据持久化方案:
# 1.RDB 数据记录到文件
# 2.AOF记录操作记录

dbsize          # 查看数据库大小
get key         # 取数据
flushall        # 删除所有数据
info            # 查看redis配置信息
info replication # 查看redis主从分离的信息
set username admin ex 30    # 设置30秒存活时间
ttl username                # 查看存活时间

主从复制/实现读写分离:redis.conf配置:

​ 奴隶身份的redis只能读数据

bind 10.7.189.103                   # 绑定IP
port 6379                           # 绑定端口
databases 16                        # 配置底层数据库个数
requirepass 111111                  # 配置redis验证口令
rdbcompression yes                  # 配置redis持久化机制-RDB(默认开启)
appendonly yes                      # 配置redis持久化机制-AOF
slaveof <masterip> <masterport>     # 配置主从复制;绑定主redis的IP及端口
masterauth <master-password>        # 配置主从复制;绑定主redis的验证口令
slowlog-max-len 128                 # 配置慢查询日志
slaveof no one                      # 退出奴隶身份(进入redis-cli后)

哨兵:sentinel.conf

# 配置master主机的ip及端口,后面的2表示如果2台奴隶机发现主机死亡,则断定主机死亡
sentinel monitor mymaster 127.0.0.1 6379 2
# 配置master主机的的名字和验证口令
sentinel auth-pass <master-name> <password>
# 默认在此时段内(30s)master从新连接将继续作为master
sentinel down-after-milliseconds mymaster 30000 
# master在此时段内没恢复就从配置文件中剔除
sentinel failover-timeout <master-name> <milliseconds>

启动哨兵:redis-server sentinel.conf --sentinel
  • 原理:

服务器搭建

MD5/SHA摘要

from hashlib import md5, sha1

hasher = md5()
hasher.update('需要摘要的数据'.encode('utf-8'))
a = hasher.hexdigest()   # 128bit

hasher = sha1()
hasher.update('需要摘要的数据'.encode('utf-8'))
a = hasher.hexdigest()   # 192bit
print(a)
print(len(a))

推送服务

pc端

  • websocket

    var ws = new WebSocket("wss://echo.websocket.org");
    
    ws.onopen = function(evt) { 
    console.log("Connection open ..."); 
    ws.send("Hello WebSockets!");
    };
    
    ws.onmessage = function(evt) {
    console.log( "Received Message: " + evt.data);
    ws.close();
    };
    
    ws.onclose = function(evt) {
    console.log("Connection closed.");
    };      
    
  • SockJs

    registry.addEndpoint("/coordination").withSockJS();
    
    <script src="//cdn.jsdelivr.net/sockjs/1.0.0/sockjs.min.js"></script>
    
    var sock = new SockJS('/coordination');  
    sock.onopen = function() {
      console.log('open');
    };
    sock.onmessage = function(e) {
      console.log('message', e.data);
    };
    sock.onclose = function() {
      console.log('close');
    };
    sock.send('test');
    sock.close();
  • STOMP

移动端

1.第三方平台 2.极光 3.百度 4.小米 5.友盟

mongodb

mongodb数据存储类型为 BSON - Binary JSON

linux指令复习

pwd 记录当前路径
netstat -nap|grep mongo 查看进程的ip端口及协议等
top 查看进程
jobs 查看后台服务
fg %1 把后台编号为1的服务拿到前台,启动服务时加上&,表示后台运行
ifconfig 查询ip

安装及添加环境变量

1. https://www.mongodb.com/download-center#atlas
2. wget <url>
3. gunzip <filename>
4. tar -xvf <filename>
5. mv <source> /usr/local/<source>
6. vim .bash_profile             # 配置环境变量
    export PATH=<source>/bin:$PATH  # 末尾添加
7. source .bash_profile
8. mkdir -p /data/db              # -p表示如果没有data文件夹就创建,再创建db
9. mongod                       # 启动
    27017
10. 配置防火墙

连接mongodb

查看指令:

mongod --help |more

启动:

mongod --bind_ip 10.7.189.103 --quiet & #绑定IP,静默处理, 后台运行

连接:

mongo --host 10.7.189.103

mongodb指令

  • python连接mongodb两种方法

    client = pymongo.MongoClient('mongodb://10.7.189.103:27017')
    client = pymongo.MongoClient(host='10.7.189.103', port=27017)
  • 基本指令

    
    # 创建数据库
    
    db = client.zhihu
    
    # 创建集合
    
    pages_cache = db.webpages
    
    # 插入一条数据
    
    page_id = pages_cache.insert_one({'url':'http://www.baidu.com', 'content':'jkdjgkajk'})
    
    # 打印mongodb创建的id
    
    print(page_id.inserted_id)
    
    # 删除数据
    
    print(pages_cache.remove({'url':'http://www.baidu.com'}))
    
    # 创建多条数据
    
    pages_cache.insert_many([
    {'_id':1, 'url':'www.baidu.com'},
    {'_id':2, 'url':'www.sina.com'},
    {'_id':3, 'url':'www.qq.com'}
    ])
    
    # upsert属性自动判断是插入(没有相应数据)还是更新(存在相应数据)
    
    print(pages_cache.update({'_id':4},{'$set':{'url':'www.csdn.com'}}, upsert=True))
    
    # 统计查询数据条数
    
    print(pages_cache.find().count())
    
    # 对查询的数据进行排序
    
    for doc in pages_cache.find().sort('url'):
      print(doc)
    
    # 数据的值--也可以是一个bson
    
    pages_cache.insert_one({'url':'www.haoya.com',
                          'type':'zipapp',
                          '好压':{'name':'好压',
                                'size':'32152kb',
                                'star':5}})

    更多查询指令可以查看相关在线资料

base64

协程

  • 协程是生成器的消费者(协程是一个消费型的生成器)—-(Python对协程的支持是通过generator实现的。)
  • 协程在一个线程中执行
  • 两个函数在互不调用的情况下协调工作

fork()

import os


def main():
    # linux和unix下创建多进程的另一种方法,这个方法if/else都会执行:
    pid = os.fork()
    print(pid)
    if pid == 0:
        print(os.getpid())
        print('good')
    else:
        print('bye')
        print(os.getpid())


if __name__ == '__main__':
    main()

genarator

from time import sleep


def fib(n):
    a, b = 0, 1
    while a <= n:
        a, b = a + b, a
        yield(a)


def count(n):
    while n>=0:
        yield n
        n -= 1


def even(gen):
    for val in gen:
        if val % 2 == 0:
            yield val


def main():
    gen = even(fib(9999))
    for _ in even(fib(9999)):
        print(next(gen))


if __name__ == '__main__':
    main()

优化

from time import sleep


def countdown(n, consumer):
    # 预激(激活消费者协程)
    # 所谓的激活就是让代码执行到yield
    # consumer.send(None)
    next(consumer)
    while n > 0:
        consumer.send(n)
        n -= 1
    print('生产完成') # 此时消费者协程将自动终止


def countdown_con():
    while True:
        n = yield
        if n:
            print('countdowm', n)
            sleep(1)


def main():
    consumer = countdown_con()
    countdown(10, consumer)


if __name__ == '__main__':
    main()
from time import sleep
from inspect import getgeneratorstate
from functools import wraps


def coroutine(fn):

    @wraps(fn)
    def wrapper(*args, **kwargs):
        gen = fn(*args, **kwargs)
        next(gen)
        return gen
    return wrapper


@coroutine
def create_delivery_man(capacity=1):
    capacitylist = []
    while True:
        while len(capacitylist) < capacity:
            pack = yield
            if pack:
                print('正在接收包裹', pack)
                capacitylist.append(pack)

            else:
                break
        print('========================')
        for i in capacitylist:
            print('正在派送包裹',i)
            sleep(2)
        capacitylist.clear()


def deliver_center(n, cou):
    for i in range(n):
        if i % 5 == 0:
            sleep(3)
        print('++准备派送包裹', i+1)
        cou.send(i+1)
    cou.send(None)


def main():
    cou = create_delivery_man(capacity=7)
    deliver_center(23, cou)

if __name__ == '__main__':
    main()
import asyncio
from time import sleep
from inspect import getgeneratorstate
from functools import wraps

import requests

"""
@asyncio.coroutine
def download(url): # 要想用异步io,此函数必须必须返回的是生成器,用aiohttp,下面只是一个假象
    print('Fetch', url)
    yield from asyncio.sleep(0.00001)
    resp = requests.get(url)
    print(url,'--->', resp.status_code)
    print(url,'--->', resp.headers)

"""

async def download(url): # 这个语法在3.5引入,async/await将在3.7里面正式变成关键字
    print('Fetch', url)
    await asyncio.sleep(0.00001)
    resp = requests.get(url)
    print(url,'--->', resp.status_code)
    print(url,'--->', resp.headers)


def main():
    loop = asyncio.get_event_loop()
    urls = [
        'https://www.baidu.com',
        'http://www.sina.com.cn',
        'http://www.sohu.com',
        'http://www.qq.com',
        'https://www.taobao.com'
    ]
    tasks = [download(url) for url in urls]
    loop.run_until_complete(asyncio.wait(tasks))
    loop.close()


if __name__ == '__main__':
    main()

猜你喜欢

转载自blog.csdn.net/gold_time_/article/details/80959908
今日推荐