Python技巧备忘录



Python技巧备忘录

作者: cj13888

全网最全的网络资源分享网站

手机扫码查看

标签:

Python

特别声明:本站资源分别为免费资源、查看密码或解压密码资源、三个级别VIP会员资源。本站所有发布的内容都是安全,请放心下载!本站不可能所有资源都可以商业用途,原创或部分除外!如:商业用途请联系原作者购买正版。与本站无关!若侵犯到您的权益,请联系本站删除,我们将及时处理!

分享

格式化字符串 f-string(最低 Python 版本为 3.6)
路径管理库 Pathlib(最低 Python 版本为 3.4)
类型提示 Type hinting(最低 Python 版本为 3.5)
枚举 enum (最低 Python 版本为 3.4)
原生 LRU 缓存(最低 Python 版本为 3.2)
Data class 装饰器(最低 Python 版本为 3.7)
隐式命名空间包(最低 Python 版本为 3.3)


py功能模块

hashlib加密模块

MD5模块

在python3由于加密前需要先进行encode转码,所以许多字符的md5值在py2与py3下都是不同的,当前环境下py2较符合测试

python2 = hashlib.md5('abc').hexdigest()
python3 = hashlib.md5('abc'.encode('utf-8').hexdigest()

生成器

使用生成器,会减少内存使用。这里说一下generator和函数的执行流程,函数是顺序执行的,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次被next()调用时候从上次的返回yield语句处急需执行,也就是用多少,取多少,不占内存,给调用者返回一个值,同时保留了当前的足够多的状态,可以使函数继续执行。为了避免NEXT()生成无限循环序列,可以改为循环。

# 函数有了yield之后,函数名+()就变成了生成器
# return在生成器中代表生成器的中止,直接报错
# next的作用是唤醒并继续执行
# send的作用是唤醒并继续执行,发送一个信息到生成器内部
'''生成器'''

def create_counter(n):
    print("create_counter")
    while True:
        yield n
        print("increment n")
        n +=1

gen = create_counter(2)
print(gen)
print(next(gen))
print(next(gen))

结果:
<generator object create_counter at 0x0000023A1694A938>
create_counter
2
increment n
3
Process finished with exit code 0

生成器表达式:

>>> # 列表解析生成列表
>>> [ x ** 3 for x in range(5)]
[0, 1, 8, 27, 64]
>>>
>>> # 生成器表达式
>>> (x ** 3 for x in range(5))
<generator object <genexpr> at 0x000000000315F678>
>>> # 两者之间转换
>>> list(x ** 3 for x in range(5))
[0, 1, 8, 27, 64]

迭代器

可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。可以使用isinstance()判断一个对象是否是Iterator对象:

>>> from collections import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)
False

生成器都是Iterator对象,但list、dict、str虽然是Iterable(可迭代对象),却不是Iterator(迭代器)。
因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

traceback使用

跟踪执行信息
def test_traceback():
    import traceback
    #返回调用堆栈(一个list),最多两层, 其中最后一个元素为当前行的信息,包括(文件名,行号,函数名,这一行的代码)
    info = traceback.extract_stack(limit=2)
    print(info)
    # 打印函数调用堆栈
    # traceback.print_stack(limit=2)
    # 无异常时为None
    # traceback.print_exc()

2to3.exe

将py2的代码转换为3,一般使用-w参数保留备份

按照代码转换
2to3.exe -w split.py
按照目录转换
2to3.exe -w d:\object

时间函数库time,datetime

将错误异常写为log文件

import datetime
except Exception as identifier:
    error_log = open('log.txt','w+')
    now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    error_log.write(username+' '+now_time+" "+str(identifier)+'\n')
Python 引入了 with 语句来自动帮我们调用 close() 方法

python之字符串格式化(format)

用法:它通过{}和:来代替传统%方式

使用位置参数
>>> li = ['hoho',18]
>>> 'my name is {} ,age {}'.format(*li)
'my name is hoho ,age 18'
>>> 'my name is {1} ,age {0} {1}'.format(10,'hoho')
'my name is hoho ,age 10 hoho'
使用关键字参数
>>> hash = {'name':'hoho','age':18}
>>> 'my name is {name},age is {age}'.format(name='hoho',age=19)
'my name is hoho,age is 19'
>>> 'my name is {name},age is {age}'.format(**hash)
'my name is hoho,age is 18'
填充与格式化
>>> '{0:*>10}'.format(10)  ## 右对齐
'********10'
>>> '{0:*<10}'.format(10)  ## 左对齐
'10********'
>>> '{0:*^10}'.format(10)  ## 居中对齐
'****10****'
精度与进制
>>> '{0:.2f}'.format(1/3)
'0.33'
>>> '{0:b}'.format(10)    #二进制
'1010'
>>> '{0:o}'.format(10)     #八进制
'12'
>>> '{0:x}'.format(10)     #16进制
'a'
>>> '{:,}'.format(12369132698)  #千分位格式化
'12,369,132,698'

os模块

python中对文件、文件夹操作时经常用到的os模块和shutil模块常用方法

在Python的string前面加上‘r’, 是为了告诉编译器这个string是个raw string,不要转意backslash '\' 。
例如,\n 在raw string中,是两个字符,\和n, 而不会转意为换行符。
由于正则表达式和 \ 会有冲突,因此,当一个字符串使用了正则表达式后,最好在前面加上'r'。

google_path = r'Google\Chrome\User Data\Default\Login Data'

在操作系统中定义的环境变量,全部保存在os.environ这个变量中,可以直接查看:

>>> os.environ
environ({'VERSIONER_PYTHON_PREFER_32_BIT': 'no', 'TERM_PROGRAM_VERSION': '326', 'LOGNAME': 'michael', 'USER': 'michael', 'PATH': '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/usr/local/mysql/bin', ...})
要获取某个环境变量的值,可以调用os.environ.get('key'):
>>> os.environ.get('PATH')
'/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/usr/local/mysql/bin'
>>> os.environ.get('x', 'default')
'default'
或者 os.environ['LOCALAPPDATA']

join方法:连接字符串数组。将字符串、元组、列表中的元素以指定的字符(分隔符)连接生成一个新的字符串

os.path.join():  将多个路径组合后返回
>>> seq3 = ('hello','good','boy','doiido')
>>> print ':'.join(seq3)
hello:good:boy:doiido
seq4 = {'hello':1,'good':2,'boy':3,'doiido':4}
>>> print ':'.join(seq4)
boy:good:doiido:hello
1.得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd()
2.返回指定目录下的所有文件和目录名:os.listdir()
3.函数用来删除一个文件:os.remove()
4.删除多个目录:os.removedirs(r"c:\python")
5.检验给出的路径是否是一个文件:os.path.isfile()
6.检验给出的路径是否是一个目录:os.path.isdir()
7.判断是否是绝对路径:os.path.isabs()
8.检验给出的路径是否真地存:os.path.exists()
9.返回一个路径的目录名和文件名:os.path.split() eg os.path.split(‘/home/swaroop/byte/code/poem.txt’) 结果:(‘/home/swaroop/byte/code’, ‘poem.txt’)
10.分离扩展名:os.path.splitext()
11.获取路径名:os.path.dirname()
12.获取文件名:os.path.basename()
13.运行shell命令
在子终端运行系统命令,不能获取命令执行后的返回信息以及执行返回的状态
import os
os.system('date')
# 2016年 06月 30日 星期四 19:26:21 CST
不仅执行命令而且返回执行后的信息对象(常用于需要获取执行命令后的返回信息)
import os
nowtime = os.popen('date')
print nowtime.read()
# 2016年 06月 30日 星期四 19:26:21 CST
commands模块
|方法 |说明|
|getoutput    |获取执行命令后的返回信息|
|getstatus    |获取执行命令的状态值(执行命令成功返回数值0,否则返回非0)|
|getstatusoutput    |获取执行命令的状态值以及返回信息|
import commonds
status, output = commands.getstatusoutput('date')
print status # 0
print output # 2016年 06月 30日 星期四 19:26:21 CST
subprocess模块
运用对线程的控制和监控,将返回的结果赋于一变量,便于程序的处理。
官方文档:http://python.usyiyi.cn/python_278/library/subprocess.html
import subprocess
nowtime = subprocess.Popen('date', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
print nowtime.stdout.read()
# 2016年 06月 30日 星期四 19:26:21 CST
14.读取和设置环境变量:os.getenv() 与os.putenv()
15.给出当前平台使用的行终止符:os.linesep Windows使用’\r\n’,Linux使用’\n’而Mac使用’\r’
16.指示你正在使用的平台:os.name 对于Windows,它是’nt’,而对于Linux/Unix用户,它是’posix’
17.重命名:os.rename(old, new)
18.创建多级目录:os.makedirs(r"c:\python\test")
19.创建单个目录:os.mkdir("test")
20.获取文件属性:os.stat(file)
21.修改文件权限与时间戳:os.chmod(file)
22.终止当前进程:os.exit()
23.获取文件大小:os.path.getsize(filename)

文本文件操作:

1.os.mknod("test.txt") #创建空文件
2.fp = open("test.txt",w) #直接打开一个文件,如果文件不存在则创建文件
3.关于open 模式:
w:以写方式打开,
a:以追加模式打开 (从 EOF 开始, 必要时创建新文件)
r+:以读写模式打开
w+:以读写模式打开 (参见 w )
a+:以读写模式打开 (参见 a )
rb:以二进制读模式打开
wb:以二进制写模式打开 (参见 w )
ab:以二进制追加模式打开 (参见 a )
rb+:以二进制读写模式打开 (参见 r+ )
wb+:以二进制读写模式打开 (参见 w+ )
ab+:以二进制读写模式打开 (参见 a+ )
fp.read([size]) #size为读取的长度,以byte为单位
fp.readline([size]) #读一行,如果定义了size,有可能返回的只是一行的一部分
fp.readlines([size]) #把文件每一行作为一个list的一个成员,并返回这个list。其实它的内部是通过循环调用readline()来实现的。如果提供size参数,size是表示读取内容的总长,也就是说可能只读到文件的一部分。
fp.write(str) #把str写到文件中,write()并不会在str后加上一个换行符
fp.writelines(seq) #把seq的内容全部写到文件中(多行一次性写入)。这个函数也只是忠实地写入,不会在每行后面加上任何东西。
fp.close() #关闭文件。python会在一个文件不用后自动关闭文件,不过这一功能没有保证,最好还是养成自己关闭的习惯。 如果一个文件在关闭后还对其进行操作会产生ValueError
fp.flush() #把缓冲区的内容写入硬盘
fp.fileno() #返回一个长整型的"文件标签"
fp.isatty() #文件是否是一个终端设备文件(unix系统中的)
fp.tell() #返回文件操作标记的当前位置,以文件的开头为原点
fp.next() #返回下一行,并将文件操作标记位移到下一行。把一个file用于for … in file这样的语句时,就是调用next()函数来实现遍历的。
fp.seek(offset[,whence]) #将文件打操作标记移到offset的位置。这个offset一般是相对于文件的开头来计算的,一般为正数。但如果提供了whence参数就不一定了,whence可以为0表示从头开始计算,1表示以当前位置为原点计算。2表示以文件末尾为原点进行计算。需要注意,如果文件以a或a+的模式打开,每次进行写操作时,文件操作标记会自动返回到文件末尾。

目录操作方法大全

1.创建目录
os.mkdir("file")
2.复制文件:
shutil.copyfile("oldfile","newfile") #oldfile和newfile都只能是文件
3.复制文件夹:
shutil.copy("oldfile","newfile") #oldfile只能是文件夹,newfile可以是文件,也可以是目标目录
4.shutil.copytree("olddir","newdir") #olddir和newdir都只能是目录,且newdir必须不存在
5.重命名文件(目录)
os.rename("oldname","newname") #文件或目录都是使用这条命令
6.移动文件(目录)
shutil.move("oldpos","newpos")
7.删除文件
os.remove("file")
8.删除目录
os.rmdir("dir") #只能删除空目录
shutil.rmtree("dir") #空目录、有内容的目录都可以删
9.转换目录
os.chdir("path") #换路径

codecs进行文件的读取

python给我们提供了一个包codecs进行文件的读取,这个包中的open()函数可以指定编码的类型:
import codecs
f = codecs.open('text.text','r+',encoding='utf-8')#必须事先知道文件的编码格式,这里文件编码是使用的utf-8
content = f.read()#如果open时使用的encoding和文件本身的encoding不一致的话,那么这里将将会产生错误
f.write('你想要写入的信息')
f.close()
以上的报错信息的意思是:在将Unicode编码成gbk的时候,不能将Unicode u'\xa0'编码成gbk。
这里,我们需要弄清楚gb2312、gbk和gb18030三者之间的关系
GB2312:6763个汉字
GBK:21003个汉字
GB18030-200027533个汉字
GB18030-200570244个汉字
所以,GBK是GB2312的超集,GB18030是GBK的超集。
在GB18030字符集中,可以找到u'\xa0'对应的字符。
codecs.open(file,'w',out_enc,errors="ignore").write(new_content)    将Unicode编码(encode)成gbk格式,但是注意encode函数的第二个参数,我们赋值"ignore",表示在编码的时候,忽略掉那些无法编码的字符

Excel操作

  1. Xlwings、pandas、xlsxwriter

csv操作

读取csv文件,返回的是迭代类型
打开文件,用with打开可以不用去特意关闭file了,python3不支持file()打开文件,只能用open()
with open("XXX.csv","r",encoding="utf-8") as csvfile:
read = csv.reader(csvfile)
for i in read:
    print(i)
写入csv文件
import csv
with open(csvfilename,"w") as file:
    writer= csv.writer(file, dialect='unix') # windows下用unix就不会有空行了
    #dialect为打开csv文件的方式,默认是excel,delimiter="\t"参数指写入的时候的分隔符
    csvwriter = csv.writer(datacsv,dialect = ("excel"))
    #csv文件插入一行数据,把下面列表中的每一项放入一个单元格(可以用循环插入多行)
    csvwriter.writerow(["A","B","C","D"])

使用DictReader可以像操作字典那样获取数据,把表的第一行(一般是标头)作为key。可访问每一行中那个某个key对应的数据。
import csv
filename = 'F:/Jupyter Notebook/matplotlib_pygal_csv_json/sitka_weather_2014.csv'
with open(filename) as f:
    reader = csv.DictReader(f)
    for row in reader:
        # Max TemperatureF是表第一行的某个数据,作为key
        max_temp = row['Max TemperatureF']
        print(max_temp)
    #每一行为key,value的记录,针对每一行均为键值对的特殊情形,这里默认认为第一列为所构建的字典的key,而第二列对应为value,可根据需要进行修改
def row_csv2dict(csv_file):
    dict_club={}
    with open(csv_file)as f:
        reader=csv.reader(f,delimiter=',')
        for row in reader:
            dict_club[row[0]]=row[1]
    return dict_club
使用DictWriter类,可以写入字典形式的数据,同样键也是标头(表格第一行)。
import csv
headers = ['name', 'age']
datas = [{'name':'Bob', 'age':23},
        {'name':'Jerry', 'age':44},
        {'name':'Tom', 'age':15}
        ]
with open('example.csv', 'w', newline='') as f:
    # 标头在这里传入,作为第一行数据
    writer = csv.DictWriter(f, headers)
    writer.writeheader()
    for row in datas:
        writer.writerow(row)
    # 还可以写入多行
    writer.writerows(datas)

字符串操作

strip()用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。

声明:s为字符串,rm为要删除的字符序列
s.strip(rm)        删除s字符串中开头、结尾处,位于 rm删除序列的字符
s.lstrip(rm)       删除s字符串中开头处,位于 rm删除序列的字符
s.rstrip(rm)      删除s字符串中结尾处,位于 rm删除序列的字符
注意:
当rm为空时,默认删除空白符(包括'\n', '\r',  '\t',  ' ')
该方法只能删除开头或是结尾的字符,不能删除中间部分的字符。也可用replace("\n", ""),后边的串替换掉前边的

split() 函数拆分字符串将字符串转化为列

str.split(str="", num=string.count(str))

字典排序collections中Counter类

collections模块自Python 2.4版本开始被引入,包含了dict、set、list、tuple以外的一些特殊的容器类型
分别是:
OrderedDict类:排序字典,是字典的子类。
namedtuple()函数:命名元组,是一个工厂函数。
Counter类:为hashable对象计数,是字典的子类。
deque:双向队列。
defaultdict:使用工厂函数创建字典,使不用考虑缺失的字典键。
Counter类则一般用于跟踪值出现的次数。它是一个无序的容器类型,
以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)。
计数器的更新(update和subtract)
当计数值为0时,并不意味着元素被删除,删除元素应当使用del
elements():返回一个迭代器。元素被重复了多少次,在该迭代器中就包含多少个该元素。元素排列无确定顺序,个数小于1的元素不被包含。
most_common([n]):返回一个TopN列表。如果n没有被指定,则返回所有元素。当多个元素计数值相同时,排列是无确定顺序的。
.copy()拷贝
算术和集合操作:+、-、&、|操作也可以用于Counter。其中&和|操作分别返回两个Counter对象各元素的最小值和最大值。需要注意的是,得到的Counter对象将删除小于1的元素。
常用操作:
sum(c.values())  # 所有计数的总数
c.clear()  # 重置Counter对象,注意不是删除
list(c)  # 将c中的键转为列表
set(c)  # 将c中的键转为set
dict(c)  # 将c中的键值对转为字典
c.items()  # 转为(elem, cnt)格式的列表
Counter(dict(list_of_pairs))  # 从(elem, cnt)格式的列表转换为Counter类对象
c.most_common()[:-n:-1]  # 取出计数最少的n-1个元素
c += Counter()  # 移除0和负值

pathlib

处理windows、linux、mac跨平台程序的路径不统一问题

pathlib能够很快很容易的做出大多数标准的文件操作:
from pathlib import Path
filename = Path("source_data/text_files/raw_data.txt")
print(filename.name)
# prints "raw_data.txt"
print(filename.suffix)
# prints "txt"
print(filename.stem)
# prints "raw_data"
if not filename.exists():
    print("Oops, file doesn't exist!")
else:
    print("Yay, the file exists!")
可以用pathlib准确地将Unix路径转换成Windows格式的路径:
from pathlib import Path, PureWindowsPath
filename = Path("source_data/text_files/raw_data.txt") # 将路径转换为 Windows 格式
path_on_windows = PureWindowsPath(filename)
print(path_on_windows)
# prints "source_data\text_files\raw_data.txt"
想在代码中安全地使用反斜杠符号,可以将路径声明为Windows格式,pathlib会将它转换为适用当前操作系统的格式:
from pathlib import Path, PureWindowsPath
# 由于已明确声明路径在Windows格式中,因此可以用斜杠符号
filename = PureWindowsPath("source_data\\text_files\\raw_data.txt")
# 将路径转换为适用当前操作系统的正确格式
correct_path = Path(filename) print(correct_path)
# 在Mac和Linux上打印 "source_data/text_files/raw_data.txt"
# 在Windows上打印"source_data\text_files\raw_data.txt"
用pathlib解决相对文件路径,解析网络分享路径和生成file://urls等这些问题。这里举个例子,只需两行代码就能让你在浏览器上打开一个本地文件:
from pathlib import Path
import webbrowser
filename = Path("source_data/text_files/raw_data.txt")
webbrowser.open(filename.absolute().as_uri())

python中的三个读read(),readline()和readlines()

文件对象提供了三个"读"方法: .read()、.readline() 和 .readlines()。每种方法可以接受一个变量以限制每次读取的数据量,但它们通常不使用变量。 .read() 每次读取整个文件,它通常用于将文件内容放到一个字符串变量中。然而 .read() 生成文件内容最直接的字符串表示,但对于连续的面向行的处理,它却是不必要的,并且如果文件大于可用内存,则不可能实现这种处理。
.readline() 和 .readlines() 非常相似。它们都在类似于以下的结构中使用:
Python .readlines() 示例

fh = open('c:\\autoexec.bat')
for line in fh.readlines():
    print line

.readline() 和 .readlines() 之间的差异是后者一次读取整个文件,象 .read() 一样。.readlines() 自动将文件内容分析成一个行的列表,该列表可以由 Python 的 for ... in ... 结构进行处理。另一方面,.readline() 每次只读取一行,通常比 .readlines() 慢得多。仅当没有足够内存可以一次读取整个文件时,才应该使用 .readline()。

爬虫相关

selenium模块

  • 这个模块一般用来模拟浏览器操作
  • 使用Xpath定位模拟登录
    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    options = Options()
    options.set_headless()
    options.binary_location = "./chrome/chrome.exe"
    driver = webdriver.Chrome(chrome_options=options, executable_path="chromedriver.exe", )
    login_url = 'http://192.168.254.1/doc/page/login.asp'
    driver.get(login_url)
    print(driver.title)
    driver.find_element_by_xpath('//*[@id="username"]').clear()
    driver.find_element_by_xpath('//*[@id="username"]').send_keys('admin')
    driver.find_element_by_xpath('//*[@id="username"]').clear()
    driver.find_element_by_xpath('//*[@id="password"]').send_keys('1qaz2wsx')
    driver.find_element_by_xpath('//*[@id="login"]/table/tbody/tr/td[2]/div/div[5]/button').click()
    current_page = driver.current_url
    print(current_page)
    if current_page == login_url :
        print('GG')
  • selenium指定浏览器程序位置与浏览器驱动位置
    1.Using Options Class:
    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    options = Options()
    options.binary_location = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"
    driver = webdriver.Chrome(chrome_options=options, executable_path="C:/Utility/BrowserDrivers/chromedriver.exe", )
    driver.get('http://google.com/')

    2.Using DesiredCapabilities Class:

    from selenium import webdriver
    from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
    cap = DesiredCapabilities.CHROME
    cap = {'binary_location': "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"}
    driver = webdriver.Chrome(desired_capabilities=cap, executable_path="C:\\Utility\\BrowserDrivers\\chromedriver.exe")
    driver.get('http://google.com/')

    3.Using Chrome as a Service:

    from selenium import webdriver
    import selenium.webdriver.chrome.service as service
    service = service.Service('C:\\Utility\\BrowserDrivers\\chromedriver.exe')
    service.start()
    capabilities = {'chrome.binary': "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"}
    driver = webdriver.Remote(service.service_url, capabilities)
    driver.get('http://www.google.com')

    json模块

  • 将程序生成字符串以字典格式写入文件中时,使用json.dumps()将将 Python 对象编码成 JSON 字符串。可以避免字典的 value 中有引号、格式不标准等问题。
  • json转码格式参数解释
    obj要存入json文件的python对象
    fp文件句柄
    ensure_ascii设置为False的话才可以把中文以中文的形式存到文件里,否则会是’\xXX\xXX’这种
    indent缩进的空格数,设置为非零值时,就起到了格式化的效果,比较美观
    #将json文本转换为dict字典输出
    json_str = json.loads(json_content)
    #将dict字典转换为json文本保存
    json.dumps(json_str, ensure_ascii=False, indent=4)
    # 使用eval函数将字符串转换为字典
    test = eval(Bookmarks_)

    mechanize

    模拟浏览器发送请求,可以根据html构造提交请求

hackhttp相关

https://github.com/BugScanTeam/hackhttp
一款 Python2.7 语言的 HTTP 第三方库,除众多基础功能外,hackhttp 支持直接发送 HTTP 原始报文,开发者可以直接将浏览器或者 Burp Suite 等抓包工具中截获的 HTTP 报文复制后,无需修改报文,可直接使用 hackhttp 进行重放。
hackhttp 使用连接池技术,在应对大量请求时自动对连接进行复用,节省建立连接时间与服务器资源,这种天生的特性,在编写爬虫时尤为显著

python3 requests模块的学习

1.模拟登陆
获取登录成功后的cookies,并格式化。

把它转换成一个包含元组的列表,然后用合适的分隔符连接起来就好了
resp = requests.get(url)
cookies = resp.cookies
login_cookies = '; '.join(['='.join(item) for item in rep.cookies.items()])
可以利用postman直接生成代码
s = requests.Session()  # 可以在多次访问中保留cookie
s.post(login_url, {'username':username, 'password': password,}, headers=headers)  # POST帐号和密码,设置headers
r = s.get(url)  # 已经是登录状态了

2.网站编码问题

import requests
r = requests.get('http://blog.sina.com.cn')
r.encoding = 'utf-8' #这里添加一行
res.content.decode("utf8")
也就是说,如果你想取文本,可以通过r.text。返回的是Unicode型的数据。
如果想取图片,文件,则可以通过r.content。返回的是bytes型也就是二进制的字节集数据。
resp.json()返回的是json格式数据

直接将文件以字节写入

r = requests.get(url_file, stream=True)    #将文件以流的方式传输
f = open("file_path", "wb")
for chunk in r.iter_content(chunk_size=512):    #size大小可以自定义,防止文件过大吃内存
    if chunk:
        f.write(chunk)
    解决获取网页内容乱码问题(获取编码格式显示为iso-8859)。
req = requests.get(url, headers=headers, timeout=20)
html = req.text.encode(req.encoding).decode('utf-8')
print(html)
当requests无法识别当前网站的编码,可以自己指定编码。requests在保存字符的时候都是先转换为unicode编码,再用相应字符集转换,所以有时候会存在生僻字无法正常保存的现象,因为字符集中不包含这个字符。
f1 = codecs.open('1.html', 'w', encoding='utf-8')
content = html.text.encode()
f1.write(content.decode('utf-8'))
f1.close

3.网站headers问题
将网站headers格式化,或者可以利用postman直接生成

s = '''Host: web.kompaskarier.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Cookie: ci_session=我就是cookies
Connection: close
Upgrade-Insecure-Requests: 1'''
s = s.strip().split('\n')
s = {x.split(':')[0] : x.split(':')[1] for x in s}
print(s)
    随机生成header头
import random
def get():
    user_agent = [
    "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)",
    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
    "Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
    "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
    "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
    "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
    "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
    "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
    "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
    "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
    "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
    "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
    "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
    ]
    #return random.choice(user_agent)
    header = {
    'User-Agent': random.choice(user_agent),
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'en-US,en;q=0.5',
    'Connection': 'keep-alive',
    'Accept-Encoding': 'gzip, deflate',
    }
    return header

4.网站html问题
美化html文件,方便正则匹配

htmltext = content.replace('\n','').replace('\r','').replace(' ','').replace('\t','')
def main():
    name1 = input('来吧输入选择的文件名:')
    soup = BeautifulSoup(open(name1, 'rb'), 'lxml').prettify()
    content = str(soup)
    content = content.replace('\n','')
    content = content.replace('\r','')
    content = content.replace(' ','')
    content = content.replace('\t','')
    write_test(content)

用chardet判断字符编码的方法

实例
使用中,chardet.detect()返回字典,其中confidence是检测精确度,encoding是编码形式

1)网页编码判断:
<span data-wiz-span="data-wiz-span" style="font-size: 1rem;">>>> import urllib
>>> rawdata = urllib.urlopen('http://www.google.cn/').read()
>>> import chardet
>>> chardet.detect(rawdata)
{'confidence': 0.98999999999999999, 'encoding': 'GB2312'}
(2)文件编码判断
<span data-wiz-span="data-wiz-span" style="font-size: 1rem;">import chardet
tt=open('c:\\111.txt','rb')
ff=tt.readline()
#这里试着换成read(5)也可以,但是换成readlines()后报错
enc=chardet.detect(ff)
print enc['encoding']
tt.close()

BeautifulSoup

from bs4 import BeautifulSoup
import codecs
import re
import csv
def main():
    soup = BeautifulSoup(codecs.open('1.html', 'r', encoding='utf-8'), 'lxml')
    content = str(soup.prettify)
    content = content.replace("\n", "")
    parse_time = '訂單時間:(.*?)</td></tr></table>'
    parse_shop = '訂單時間:(.*?)</td></tr></table>'
    parse_text(parse_time, content)
def parse_text(parse_re, content):
    parse_text = re.compile(parse_re, re.S)
    parse_content = re.findall(parse_text, content)
    print(parse_content)
if __name__ == '__main__':
    main()
    # f= codecs.open("1.txt", "w", encoding='utf-8')
    # f.write(content)

协程相关

asyncio与aiohttp

可以配合queue构建生产者消费者模型使用
http://aiohttp.readthedocs.io/en/stable/    官网

client例子

import aiohttp
import asyncio
import async_timeout

async def fetch(session, url):
    async with async_timeout.timeout(10):
        async with session.get(url) as response:
            return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        html = await fetch(session, 'http://python.org')
        print(html)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

server例子

from aiohttp import web

async def handle(request):
    name = request.match_info.get('name', "Anonymous")
    text = "Hello, " + name
    return web.Response(text=text)

app = web.Application()
app.add_routes([web.get('/', handle),
                web.get('/{name}', handle)])

web.run_app(app)

正则相关

import codecs
import re
with codecs.open('./eg.html',encoding='big5') as f1:
    content = f1.read()
pattern_page = re.compile('/ 共 (.*?) 頁')
pages = re.findall(pattern_page,content)
print(pages[0])
pattern_content = re.compile('<a href="(.*?)" target="_blank"\>列印\</a>')
items = re.findall(pattern_content,content)
for item in items:
    print(item)

二进制文件打包

cs_freeze
py2exe
https://github.com/cdrx/docker-pyinstaller    linux下使用wine来使用pyinstaller生成exe
pyinstaller -F -w run.py
https://github.com/takluyver/pynsist
wine下使用pyinstaller
wine msiexec /i /home/watson/dload/chrome/python-2.7.3.msi
wine /home/watson/dload/chrome/pywin32-218.win32-py2.7.exe
wine ~/.wine/drive_c/Python27/python.exe ~/bin/pyinstaller-2.0/pyinstaller.py -Fw demo.py

验证码识别

https://github.com/madmaze/pytesseract
https://github.com/ZYSzys/awesome-captcha

数据库相关

sqlite数据库,附带win32api加密数据

import sqlite3
# 调用win32api加解密
import win32crypt
# sql的插入语句,这里在sql语句中可以在关键位置以英文下的 ? 号作为提前预置值
SQLword = "INSERT INTO logins(username,password) VALUES ('admin', ?)"
# 加密前需要先将字符串转为byte
pwd = str.encode("test123")
# 调用win32api加密
encPwd = win32crypt.CryptProtectData(pwd)
# 连接数据库
SqliConn = sqlite3.connect(SqlPath)
# 设置游标
cursor = SqliConn.cursor()
# 执行sql语句,同时在预置值的地方填充值
cursor.execute(SQLword, [sqlite3.Binary(encPwd)])
# 提交执行
SqliConn.commit()
# 调用win32api解密
pwd2 = win32crypt.CryptUnprotectData(blob,None,None,None,0)

版本环境管理

anaconda

将anaconda的bin目录加入PATH,根据版本不同,也可能是~/anaconda3/bin
echo 'export PATH="/root/anaconda3/bin:$PATH"' >> ~/.bashrc
alias pyana="/root/anaconda3/bin/python"    #生成快捷命令
source ~/.bashrc    #更新bashrc以立即生效
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --set show_channel_urls yes    #配置清华镜像
conda create -n py27 python=2.7    #添加2.7版本的Python环境
activate py27(linux:  source activate py27)    #开启环境
source deactivate py27    #退出环境
conda info -e    #命令查看已有的环境
conda remove -n env_name --all    #来删除指定的环境
conda install -n py27 lxml        #安装依赖 remove 移除依赖
conda install -n py27 anaconda    #安装所有包
conda env export > environment.yml    #分享环境文件
conda env create -f environment.yml   #从文件创建环境
conda update conda    #升级conda
conda update python    #升级python版本

pip与easy_install

生成requirements.txt

python -m pip freeze >requirements.txt
python -m pip install -r requirements.txt
pip uninstall [options]

安装方法-Windows: pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
安装方法-Linux:
root用户(避免多python环境产生问题): python2 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
非root用户(避免安装和运行时使用了不同环境): sudo python2 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt

python出错总结

app开发

分享到:
打赏
未经允许不得转载:

作者: cj13888, 转载或复制请以 超链接形式 并注明出处 易启发资源网
原文地址: 《Python技巧备忘录》 发布于2020-7-12

评论


切换注册

登录

忘记密码?

您也可以使用第三方帐号快捷登录

切换登录

注册

Python技巧备忘录

长按图片转发给朋友

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏