Python常用内建模块
文章目录
- datetime
- 获取当前日期和时间
- 获取指定日期和时间
- datetime转化为timestamp
- timestamp转化为datetime
- str转化为datetime
- datetime转化为str
- datetime加减
- collections
- namedtuple
- deque
- defaultdict
- ChainMap
- Counter
- base64
- hashlib
- 摘要算法简介
- MD5摘要算法使用
- 摘要算法的应用
- hmac
- itertools
- count
- cycle
- repeat
- accumulate
- chain
- dropwhile
- takewhile
- groupby
- 计算圆周率的小例子
- contextlib
- closing
- urllib
- Get
- 模拟浏览器去访问
- Post
- 单独的用户登录
- 添加和查看用户信息
- XML
- dom
- sax
- ElementTree
- 三种方式的代码运行截图
- HTMLParser
- 实战例子
- 参考网址
datetime
datetime
是Python处理日期和时间的标准库。
获取当前日期和时间
注意下面第一个datetime
是包名,第二个datetime
是类名
# 获取当前日期和时间
from datetime import datetime
now = datetime.now()
print(now)
print(type(now))
获取指定日期和时间
#获取指定日期和时间
from datetime import datetime
# 注意datetime的初始化方法里 年月日时分秒 都是int类型
dt = datetime(2020, 2, 10, 22, 15, 30)
print(dt)
datetime转化为timestamp
在计算机中,时间实际上是用数字表示的。我们把
1970年1月1日 00:00:00 UTC+00:00
时区的时刻称为epoch time
,记为0(1970年以前的时间timestamp为负数),当前时间就是相对于epoch time的秒数,称为timestamp。
仔细理解上面那段话。可以这样认为
timestamp = 0 = 1970-1-1 00:00:00 UTC+0:00
对应北京时间就是
timestamp = 0 = 1970-1-1 08:00:00 UTC+8:00
可以看出timestamp的值与时区是无关的。因为一旦timestamp确定,其UTC时间就确定了,转换到任意时区也是可以完全确定的。这也是为什么这计算机存储的当前时间是以timestamp表示的。
from datetime import datetime
dt = datetime(2020, 2, 10, 22, 15, 30)
print(dt)
# 获取datetime对应的timestamp
print(dt.timestamp())
注意Python的timestamp是一个浮点数。如果有小数位,小数位表示毫秒数。
某些编程语言(如Java和JavaScript)的timestamp使用整数表示毫秒数,这种情况下只需要把timestamp除以1000就得到Python的浮点表示方法。
timestamp转化为datetime
我们知道timestamp是和时区没有关系的,但是datetime是和时区有关的。
# timestamp转化为datetime
ts = 1581344130.0
# 转化成本地时间,即北京时间,UTC+8
local_dt = datetime.fromtimestamp(ts)
# 转化成utc时间,即UTC+0
utc_dt = datetime.utcfromtimestamp(ts)
print(local_dt)
print(utc_dt)
我们可以从打印结果也能看出datetime是和时区有关的,北京时间就比UTC时间+8。
str转化为datetime
用datetime.strptime(cls, date_string, format)
,注意是datetime
类的类方法。
我们常用的日期格式就是下面的格式,更加的详细可以参考Python官网日期格式
# str转化为datetime
dt = datetime.strptime("2020-05-20 20:05:10", "%Y-%m-%d %H:%M:%S")
print(dt)
print(type(dt))
datetime转化为str
采用datetime.strftime(self, fmt)
格式化datetime
# datetime转化为str
s = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(s)
datetime加减
对于日期和时间的加减需要用到datetime
包里的timedelta
类。
其中timedelta
类支持days
、weeks
、hours
、minutes
、seconds
等等
def __init__(self, days: float = ..., seconds: float = ..., microseconds: float = ...,milliseconds: float = ..., minutes: float = ..., hours: float = ...,weeks: float = ...)
# datetime加减
from datetime import datetime,timedelta
now = datetime.now()
print("当前时间是: ",now)
print("后退5天的时间是: ",now + timedelta(days=5))
print("前进5天的时间是: ",now - timedelta(days=5))
但是时间加减上并没有前几年或者前几个月,这就需要另一个arrow
模块去实现,不过这不是内建模块,是第三方模块,具体使用可查看Arrow官网。
# 从timestamp获取arrow
a = arrow.get(1581344130.0)
# 注意这里的format方法和strftime方法的参数格式是不同的
print(a.format("YYYY-MM-DD HH:mm:ss"))
# 从str获取arrow
a = arrow.get("2020-02-10 22:15:30", "YYYY-MM-DD HH:mm:ss")
print(a.format("YYYY-MM-DD HH:mm:ss"))
# 获取前2年 后3月 的时间
print("前2年 后3月 的时间: ",a.shift(years=-2, months=3).format("YYYY-MM-DD HH:mm:ss"))
collections
collections
是Python内建的一个集合模块,提供了许多有用的集合类。
namedtuple
我们知道tuple
里的元素是不可变的,但是访问其中元素时是和list
一样通过索引下标
访问。
例如,我们定义一个平面系坐标的点(x,y),就可以用namedtuple
来定义,然后通过名字来访问。如下所示
# namedtuple 通过名字访问tuple元素
from collections import namedtuple
import math
Point = namedtuple("Point",["x", "y"])
p = Point(3,4)
print("点p的横坐标为{}, 纵坐标为{}, 其到原点长度是{}".format(p.x, p.y, math.sqrt(math.pow(p.x,2)+math.pow(p.y,2))))
# 此处Point已经是一个类型
print("p是Point? ", isinstance(p, Point))
print("p是tuple? ",isinstance(p, tuple))
deque
使用list
存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低
deque是为了高效实现插入和删除操作的双向列表
,适合用于队列和栈
。
from collections import deque
q = deque(['a', 'b', 'c'])
q.append('d')
q.appendleft('1')
print(q)
print("弹出右边的元素: ", q.pop())
print("弹出左边的元素: ", q.popleft())
print(q)
defaultdict
使用dict
时,如果引用的Key
不存在,就会抛出KeyError
。如果希望key不存在时,返回一个默认值
,就可以用defaultdict
注意defaultdict
里面的参数是一个函数,该函数无参,但是有返回值即默认值。
# defaultdict 当key不存在时返回默认值
from collections import defaultdict
d = defaultdict(lambda : 0)
d['patrick']=100
print('patrick的分数是: ', d['patrick'])
print('marry的分数是(默认值): ', d['marry'])
ChainMap
ChainMap
可以把一组dict
串起来并组成一个逻辑上的dict
。ChainMap本身也是一个dict,但是查找的时候,会按照顺序在内部的dict依次查找
。
这个在向应用程序传入参数时非常适用。向应用程序传入既可以通过命令行传入,也可以通过环境变量,程序也有默认参数。但是我们可以使用ChainMap
来按序查找参数的值,即可以先从命令行查找,然后从环境变量查找,最后查默认值。
这个可以结合Hadoop的配置来理解,Hadoop优先支持命令行,然后支持配置文件,再支持默认值。
# ChainMap
from collections import ChainMap
import os
import argparse# 构造缺省参数
defaults = {"dfs_replication": 3, "mapreduce_job_reduces": 0}# 构造命令行参数
parser = argparse.ArgumentParser()
parser.add_argument("-dr", "--dfs_replication")
parser.add_argument("-mrn", "--mapreduce_job_reduces")
namespace = parser.parse_args()
# 获取v不为空的键值对
command_line = {k:v for k,v in vars(namespace).items() if v}combined_maps = ChainMap(command_line, os.environ, defaults)print("dfs_replication=",combined_maps["dfs_replication"])
print("mapreduce_job_reduces=",combined_maps["mapreduce_job_reduces"])
下面分别展示了三种情况下的参数的值。
注意:这里之所以把.
换成了_
是因为环境变量不支持.
而且需要使用export
将变量使得后面的子进程可见,否则os.environ
会获取不到设置的环境变量值。
这里由于使用了 argparse
模块,故可以直接输入-h
来查看其帮助信息。当然这个帮助信息是自动生成的。关于 argparse
模块后面会有专门的章节去讲,这也是Python内建模块,详细可以直接参考官网argparse模块。
Counter
Counter
是一个简单的计数器。
能非常方便的计数和统计前N的字符及其出现次数。
from collections import Counter
d = Counter()
for c in "programming":d[c] = d[c]+1
print(d)
print("统计前2的字符是", d.most_common(2))# 可以传入iterable
print(Counter("programming"))
# 可以通过k=v传入
print(Counter(a=3, b=2))
# 可以通过dict传入
print(Counter({"a":3, "b":2}))
base64
Base64
是一种用64个字符来表示任意二进制数据的方法。
由于二进制文件如图片、exe文件等包含很多无法显示和打印的字符,所以,如果要让记事本这样的文本处理软件能处理二进制数据,就需要一个二进制到字符串的转换方法。Base64是一种最常见的二进制编码方法。
Base64的原理很简单,首先,准备一个包含64个字符的数组:
['A', 'B', 'C', ... 'a', 'b', 'c', ... '0', '1', ... '+', '/']
然后,对二进制数据进行处理,每3个字节一组,一共是3x8=24bit,划为4组,每组正好6个bit:
这样我们得到4个数字作为索引,然后查表,获得相应的4个字符,就是编码后的字符串。
所以,Base64编码会把3字节的二进制数据编码为4字节的文本数据,长度增加33%,好处是编码后的文本数据可以在邮件正文、网页等直接显示。
如果要编码的二进制数据不是3的倍数,最后会剩下1个或2个字节怎么办?Base64用\x00字节在末尾补足后,再在编码的末尾加上1个或2个=号,表示补了多少字节,解码的时候,会自动去掉。
所以Base64编码后的字符串一定是4的倍数,如果不是4的倍数就需要再后面补相应个数的=号。
这里需要说明下=
号只会出现在最后面作为补足位数,前提是表里本身就不包含=
。
如下所示,需要注意的是 b64encode 和 b64decode 方法的输入参数和返回参数都是bytes类型的字符串
# -*- coding:UTF-8 -*-import base64
# b64encode 和 b64decode 方法的输入参数和返回参数都是bytes类型的字符串# 编码后的是bytes类型字符串
e_str = base64.b64encode("大数据平台yarn".encode())
print(e_str)
# <class 'bytes'>
print(type(e_str))
s = base64.b64decode(e_str)
print(s.decode())# 该方法是用于处理那些尾部已经去掉等号的bytes类型字符串
def safe_base64_decode(s):s = s.decode()left = len(s) % 4list_str = []list_str.append(s)for i in range(left):list_str.append("=")return base64.b64decode("".join(list_str).encode()).decode()assert '大数据平台yarn' == safe_base64_decode(b'5aSn5pWw5o2u5bmz5Y+weWFybg=='), "带等号解码失效"
assert '大数据平台yarn' == safe_base64_decode(b'5aSn5pWw5o2u5bmz5Y+weWFybg'), "不带等号解码失效"
assert '大数据平台' == safe_base64_decode(b'5aSn5pWw5o2u5bmz5Y+w'), "带等号解码失效"
print('ok')
Base64是一种通过查表的编码方法,不能用于加密,即使使用自定义的编码表也不行(一般也不需要自定义表)。
Base64适用于小段内容的编码,比如数字证书签名、Cookie的内容等
hashlib
摘要算法简介
摘要算法
又称为哈希算法
、散列算法
。它通过一个函数把任意长度的数据转换为一个固定的数据串(如16位固定长度)。
摘要算法的目的是为了发现原始数据是否被人篡改过,如Apache下的包有的也会附带着摘要,来判断下载的包是否是完整的未经篡改的包,只是平时我们不去校验摘要而已。
摘要算法之所以能够指出原数据是否被人篡改过,主要在于摘要函数是一个单向函数,计算摘要很容易,但是通过摘要反推出原数据就很困难,任意一个bit的修改都会导致计算出摘要完全不同。
Python的hashlib
提供了常见的摘要算法,如MD5,SHA1等等。
MD5摘要算法使用
下面是常用的MD5
摘要算法的使用方法。
update()
:传入原始数据(注意必须是bytes
类型),可以多次调用
digest()
:计算原始数据的摘要,返回的类型是bytes
hexdigest()
:计算原始数据的摘要,返回的类型是32位固定长度的字符串
import hashlib# 获取md5算法
md5 = hashlib.md5()
# 将Bytes类型的字符串传入update方法里, 可以多次传入
md5.update('how to use md5 in python hashlib?'.encode('utf-8'))
md5.update('just use update & hexdigest'.encode('utf-8'))
# 计算到目前位置通过update传入到该md5里所有数据的摘要, 返回bytes类型的字符串
print(md5.digest())
# 返回32位固定长度的16进制字符串, 其类型是str
print(md5.hexdigest())
python的hashlib
模块还支持如下算法,但是使用方法都是和md5
类似。
越安全的摘要算法长度越长,耗时越高。
摘要算法的应用
最常见的就是在数据库中对用户的密码取md5摘要并代替明文密码存到数据库中,这样可以防止用户密码随意暴露给运维人员。
但是这样也不一定安全。如果用户设置如123456
、password
等简单的密码,黑客完全可以事先算出常用密码的摘要并构造出一个反推表即通过摘要推出简单的密码。
我们可以在程序设计上对简单密码进行加强保护,俗称加盐
即Salt
。即对原始密码添加一个复杂的字符串然后再进行摘要计算。只要Salt
没有暴露,那么很难通过摘要计算出明文密码。
如果有两个用户使用同样的密码,那么保存在数据库中的摘要是一样的,如何让相同口令的用户存储不同的摘要呢?可以把用户名作为Salt
的一部分,从而实现相同口令的用户存储不同的摘要。
hmac
为了防止黑客通过彩虹表根据哈希值反推出明文口令,根据上面内容可以采用加盐
的方式使得相同的输入得到不同的哈希值,大大增加黑客的破解难度。
其实加盐
这种方式就是Hmac
算法:Keyed-Hashing for Message Authentication
。它通过一个标准算法,在计算哈希的过程中,把key混入计算过程中。采用Hmac替代我们自己的salt算法,可以使程序算法更标准化,也更安全。
Python自带的hmac
模块实现了标准的Hmac算法。
下面是Hmac算法的例子,和上面的MD5使用方法一样。
import hmackey = b'secret key'
message = "how to use md5 in python hashlib?".encode()
h = hmac.new(key, message, 'md5')
# 可以通过upadte方法传入数据
h.update('just use update & hexdigest'.encode())
print(h.hexdigest())
itertools
itertools
模块提供了很多用来创建和使用迭代对象的函数。
下面图展示了itertools
模块的源码简介
count
count(start=0, step=1) --> start, start+step, start+2*step, ...
会创建一个无限迭代器。
如下所示,打印100以内的自然数,由于是无限迭代器,所以测试代码里设置了退出条件。
import itertools# 打印100以内的自然数
num = itertools.count(1)
for n in num:if n <= 100:print(n)else:break
cycle
cycle(p) --> p0, p1, ... plast, p0, p1, ...
会创建一个无限迭代器。
下面代码展示了cycle
的使用方法,字符串是可迭代的。为了使测试代码能退出故使用了enumerate
计算迭代次数。
iter_c = itertools.cycle("hadoop")
for i,c in enumerate(iter_c):if i< 10:# 此处为了让打印看的更清除,就将sep和end设置成空字符串print(c, sep="", end="")else:break
repeat
repeat(elem [,n]) --> elem, elem, elem, ... endlessly or up to n times
负责将一个元素无限重复下去,也可以指定参数来指定重复次数。
如下所示,将字符串hadoop
重复3次。
iter_s = itertools.repeat("hadoop", 3)
for s in iter_s:print(s)
accumulate
accumulate(p[, func]) --> p0, p0+p1, p0+p1+p2
会创建一个不断累积的无限迭代器,其中累积函数默认是求和。
如下面代码就展示了求自然数前N项和的函数。
def sum_n(n):iter_num = itertools.count(1)iter_sum = itertools.accumulate(iter_num)for i, s in enumerate(iter_sum):if i == 10:breakprint("自然数前{}项和为{}".format((i+1), s))if __name__ == "__main__":sum_n(10)pass
chain
chain(p, q, ...) --> p0, p1, ... plast, q0, q1, ...
可以将已有的迭代器串起来形成更大的迭代器。
如下面所示,将两个字符串迭代器串起来形成一个大的迭代器。
iter_chain = itertools.chain("hadoop", "spark")
for c in iter_chain:# 此处为了让打印看的更清除,就将sep和end设置成空字符串print(c, sep="", end="")
dropwhile
dropwhile(pred, seq) --> seq[n], seq[n+1], starting when pred fails
也会创建一个子迭代器。
如下面例子展示了从自然数中的11开始前十个自然数。
def print_ten(iter_element):for i, element in enumerate(iter_element):if i == 10:breakprint(element)iter_n = itertools.dropwhile(lambda x:x<11, itertools.count(1))
print_ten(iter_n)
takewhile
takewhile(pred, seq) --> seq[0], seq[1], until pred fails
会创建一个迭代器。
如下面代码展示了使用takewhile
取奇数项前十个元素
n=10
odd = itertools.count(1, step=2)
ten_odd = itertools.takewhile(lambda v: (v+1)/2 <= n, odd)
print(list(ten_odd))
groupby
groupby()
把迭代器中相邻的重复元素挑出来放在一起。可以类比MapReduce任务的Reduce阶段,不过又不同于Reduce,因为这个迭代器中相同的元素并不是全部都是相邻的。
所以请特别注意是相邻的重复元素。
下面展示了groupby()
使用的例子及其结果
iter_groups = itertools.groupby('AAAABBCCCCDDD')
for k,sub_iter in iter_groups:print("*******************************")print("k={}".format(k))print(list(sub_iter))
实际上挑选规则是通过函数完成的,只要作用于函数的两个元素返回的值相等,这两个元素就被认为是在一组的,而函数返回值作为组的key。如果我们要忽略大小写分组,就可以让元素’A’和’a’都返回相同的key。
下面的例子就是让相邻的大小写字母归为同一组。
iter_groups = itertools.groupby('AAaaABBCccCDdd', lambda v: v.upper())
for k,sub_iter in iter_groups:print("*******************************")print("k={}".format(k))print(list(sub_iter))
计算圆周率的小例子
根据提供的四个步骤去计算圆周率,如果打印出ok则证明算法是正确的。
def pi(n):""" 计算pi的值step 1: 创建一个奇数序列: 1, 3, 5, 7, 9, ...step 2: 取该序列的前N项: 1, 3, 5, 7, 9, ..., 2*N-1.step 3: 添加正负符号并用4除: 4/1, -4/3, 4/5, -4/7, 4/9, ...step 4: 求和:"""# step 1odd = itertools.count(1, step=2)# step 2n_odd = itertools.takewhile(lambda v: (v + 1) / 2 <= n, odd)# step 3 注意这里采用生成式的方式生成迭代对象iter_n = ( -4/i if (i+1)/2%2 == 0 else 4/i for i in n_odd)# step 4from functools import reducereturn reduce(lambda x,y:x+y, iter_n)def check_pi():print(pi(10))print(pi(100))print(pi(1000))print(pi(10000))assert 3.04 < pi(10) < 3.05assert 3.13 < pi(100) < 3.14assert 3.140 < pi(1000) < 3.141assert 3.1414 < pi(10000) < 3.1415print('ok')if __name__ == "__main__":check_pi()pass
contextlib
在Python里我们是通过with
语句来自动关闭文件资源的,不需要写try ... finally ...
这种繁琐的语句。
并不是只有open()
函数返回的文件描述符对象才能使用with
语句。实际上,任何对象,只要正确实现了上下文管理,就可以使用with
语句关闭相应资源。
实现上下文管理是通过__enter__
和__exit__
这两个方法实现的。
下面的代码就展示了如何让自定义类可以使用with
语句自动关闭资源。
class Query(object):def __init__(self, name):self.name=namedef __enter__(self):print("Begin")# 注意必须返回当前对象实例 否则使用with语句会报错return selfdef __exit__(self, exc_type, exc_val, exc_tb):if exc_type:print("Error")else:print("End")def query(self):print("Query info about {}".format(self.name))with Query("patrick") as q:q.query()
实际上每个类都要这么去实现两个方法也挺繁琐的。
我们可以使用contextlib
模块提供的contextmanager
去简化代码。
如下面代码所示。@contextmanager
这个装饰器接受一个generator
,用yield
语句把with ... as var
把变量输出出去,然后,with
语句就可以正常地工作了。
class Query(object):def __init__(self, name):self.name=namedef query(self):print("Query info about {}".format(self.name))from contextlib import contextmanager@contextmanager
def create_query(name):print("Begin")q = Query(name)yield qprint("End")with create_query("patrick") as q:q.query()
很多时候我们希望在某些代码块前后自动执行特定代码,可以使用@contextmanager
来实现。
如当向数据库执行一条查询语句时,可以按照下面的方式去计算查询时间并打印出来。
from contextlib import contextmanager
import time@contextmanager
def count_time(action):print("Begin")start = time.perf_counter()yieldend = time.perf_counter()print("{}共耗时{:.0f}s".format(action, (end-start)))print("End")with count_time("select"):import random# 向数据库执行一条查询语句time.sleep(random.randint(3,7))
closing
contextlib
中还包含一个closing
对象,这个对象就是一个上下文管理器,它的__exit__
函数仅仅调用传入参数的close
。其源码如下。
所以closeing
上下文管理器仅使用于具有close()
方法的资源对象。如我们通过urllib.urlopen
打开一个网页,urlopen
返回的对象有close
方法,所以我们就可以使用closing
上下文管理器。
from contextlib import closing
from urllib.request import urlopenwith closing(urlopen("https://www.baidu.com/")) as resp:print(type(resp))for line in resp:print(line)
urllib
urllib
模块提供了一系列操作url的功能。
Get
urllib
的request
模块可以非常方便地抓取URL内容,也就是发送一个GET请求到指定的页面,然后返回HTTP的响应。
urlopen()
函数返回的对象类型是http.client.HTTPResponse
。假设下面的resp
就表示HTTPResponse
对象。
resp.info()
和 resp.getheaders()
返回HTTPResponse
的header
信息,只不过后者返回的是列表(如下面源码所示)。可以通过resp.info().get('Content-Type')
来获取具体的header
值,后者的话只能遍历获取了效率没有前者高。
resp.geturl()
获取页面真实的url, 通过和原有的url进行比对可发现是否产生了重定向。
resp.getcode()
获取响应的返回码, 其实就是返回resp.status
。
resp.read()
获取响应的返回内容。
下面代码展示了通过urlopen()
函数来抓取三个网页内容。
其中在抓取https://www.qq.com/
时发现该网页的响应header
里有Content-Encoding: gzip
,表示该网页是通过gzip压缩然后返回给客户端的,客户端需要进行解压缩,所以下面的代码就用了zlib
模块去解压缩。
由于resp.read()
返回的类型是bytes
,所以转换成中文需要解码。一方面可以参考响应header
里的Content-Type
看其具体是什么编码,一方面可以参考第三方库chardet
来检查返回的内容具体是什么编码。
在发现网页编码类型是gb2312
时,直接用gbk
去解码即可,如果用gb2312
反而会报错,具体可看下面代码。
from urllib.request import urlopen
from contextlib import closing# url = "https://lol.qq.com/" # gb2312编码
url = "https://www.qq.com/" # gb2312编码 并采用了Content-Encoding: gzip 通过压缩网页内容来减少网络传输数据量, 当然客户端就需要解压缩
# url = "https://www.csdn.net/" # utf-8编码with closing(urlopen(url)) as resp:# 属于http.client.HTTPResponseprint(type(resp))# 获取返回的header信息, 可以通过resp.info() 也可以通过resp.getheaders()print(resp.info())print(resp.getheaders())# 获取页面真实的url, 通过和原有的url进行比对可发现是否产生了重定向# 其实就是返回resp.urlprint(resp.geturl())# 获取响应的返回码 其实就是返回resp.statusprint(resp.getcode())# 获取响应返回的内容data = resp.read()# 获取其'Content-Type'print(resp.info().get('Content-Type'))gzip_val = resp.info().get("Content-Encoding")if gzip_val:print("Content-Encoding: ", gzip_val)# 解压缩import zlibdata = zlib.decompress(data, 16+zlib.MAX_WBITS)# 引用第三方包检查其类型 只作为参考, 也可以使用上面提到的'Content-Type'import chardetdetect_res = chardet.detect(data)print(detect_res)if detect_res.get("encoding").lower().find("utf") != -1:print(data.decode())else:# 例如 https://lol.qq.com/ 网页的编码就是gb2312 但是解码的时候直接用gbk解码就好print(data.decode("gbk"))
模拟浏览器去访问
如果我们要想模拟浏览器发送GET请求,就需要使用Request
对象,通过往Request
对象添加相应的header
信息,我们就可以把请求伪装成浏览器。例如,模拟iPhone 6去请求豆瓣首页
首先通过request.Request(url)
获取Request
对象,然后通过req.add_header()
添加相应的header
信息,再使用urlopen(req)
请求网页,注意此时urlopen()
函数的参数是Request
对象。
下面只展示了部分代码,其余内容和上面的代码保持一致。
其中user-agent
的值可以通过在浏览器上按F12
查看(如下图所示)。
from urllib.request import urlopen
from urllib import request
from contextlib import closing# url = "https://lol.qq.com/" # gb2312编码
# url = "https://www.qq.com/" # gb2312编码 并采用了Content-Encoding: gzip 通过压缩网页内容来减少网络传输数据量, 当然客户端就需要解压缩
# url = "https://www.csdn.net/" # utf-8编码
url = "https://www.douban.com/"req = request.Request(url)
# req.add_header("user-agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36")
# 模拟手机发送请求
req.add_header("user-agent", "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Mobile Safari/537.36")
with closing(urlopen(req)) as resp:# 获取返回的header信息, 可以通过resp.info() 也可以通过resp.getheaders()print(resp.info())print(resp.getheaders())
Post
可以采用post的方式去提交请求。譬如登录。
下面的请求中查看所有用户信息和添加用户信息之前都需要先登录。那么这就涉及到一个保存cookie的问题。
下面的请求是用SpringBoot
写的一个简单的web应用。传递参数都是用的json
,所以在发出请求时都需要在请求的header
信息里添加content-type: application/json
url | 说明 |
---|---|
/login | 登录 |
/user/list | 查看所有用户信息 |
/user/add | 添加用户信息 |
单独的用户登录
由于传递的是json信息,需要使用json.dumps(login_d).encode("utf8")
将json信息转化成字符串并编码成bytes
类型,这样才能传递给urlopen()
函数的data参数。
from urllib.request import urlopen
from urllib import request
from contextlib import closing
import jsonurl = "http://localhost:8080/"req = request.Request(url+"login")
# 登录信息
login_d = {"username": 'admin', "password": 'admin'}
# 将个人信息转化成字符串后并编码转化成bytes类型
post_data = json.dumps(login_d).encode("utf8")
# 由于后台服务支持的是 application/json 而不是application/x-www-form-urlencoded 所以请求对象这里必须显示设置
req.add_header("content-type", "application/json")with closing(urlopen(req, data=post_data)) as resp:# 获取响应返回的内容data = resp.read()# 后台返回的是json字符串 通过json.loads转化成json对象res = json.loads(data)print(res)print(res.get("msg"))print(res.get("code"))
添加和查看用户信息
添加用户前,需要登录,如上面所示需要考虑cookie的保存问题。
需要使用下面的代码保存cookie
信息,并且不能需要使用opener
对象去请求,而不是像以前一样用urlopen()
函数。
from urllib import request
from http import cookiejar
from contextlib import closing# 利用cookie保存登录信息
cookie = cookiejar.CookieJar()
handler = request.HTTPCookieProcessor(cookie)
# 后面用opener去请求而不是用urlopen() 这样就能访问cookie里的登录信息
opener = request.build_opener(handler)
下面是完整的代码
# -*- coding:UTF-8 -*-from urllib import request
from http import cookiejar
from contextlib import closing
import jsonserver_url = "http://localhost:8080/"# 利用cookie保存登录信息
cookie = cookiejar.CookieJar()
handler = request.HTTPCookieProcessor(cookie)
# 后面用opener去请求而不是用urlopen() 这样就能访问cookie里的登录信息
opener = request.build_opener(handler)def login():req = request.Request(server_url + "login")# 登录信息login_d = {"username": 'admin', "password": 'admin'}# 将个人信息转化成字符串后并编码转化成bytes类型post_data = json.dumps(login_d).encode("utf8")# 由于后台服务支持的是 application/json 而不是application/x-www-form-urlencoded 所以请求对象这里必须显示设置req.add_header("content-type", "application/json")# with closing(urlopen(req, data=post_data)) as resp:with closing(opener.open(req, data=post_data)) as resp:# 获取响应返回的内容data = resp.read()# 后台返回的是json字符串 通过json.loads转化成json对象res = json.loads(data)print(res)def user_list():req = request.Request(server_url + "user/list")with closing(opener.open(req)) as resp:# 获取响应返回的内容data = resp.read()# 后台返回的是json字符串 通过json.loads转化成json对象res = json.loads(data)# 采用pprint模块打印的更加美化import pprintpprint.pprint(res)def user_add(user):req = request.Request(server_url + "user/add")req.add_header("content-type", "application/json")post_data = json.dumps(user).encode()with closing(opener.open(req, data=post_data)) as resp:# 获取响应返回的内容data = resp.read()# 后台返回的是json字符串 通过json.loads转化成json对象res = json.loads(data)print(res)if __name__ == "__main__":login()user_data = {"username": "鹿丸", "password": "admin", "age": 20, "sex": "男", "money": 500.25, "school": "北京大学"}user_add(user_data)user_data = {"username": "丁次", "password": "admin", "age": 20, "sex": "男", "money": 200.25, "school": "火影大学"}user_add(user_data)user_data = {"username": "井野", "password": "admin", "age": 20, "sex": "女", "money": 100.25, "school": "中忍大学"}user_add(user_data)user_list()pass
XML
python有三种方式去解析xml文件。个人倾向于第三种方式。
- 使用
dom
去解析。缺点是需要将整个xml文件都读入内存,内存占用高,比较慢。 - 使用
sax
去解析。sax
是采用事件驱动模型,边读入内存边解析,优点是占用内存小,解析快,缺点是需要自己写对应事件的回调函数。 - 使用
ElementTree
去解析。ElementTree 相对于 DOM 来说拥有更好的性能,与 SAX 性能差不多,API 使用也很方便。
准备xml文件如下。
<?xml version="1.0" encoding="utf-8"?>
<list>
<student id="stu1" name="stu1_name"><id>1001</id><name>张三</name><age>22</age><gender>男</gender>
</student>
<student id="stu2" name="stu2_name"><id>1002</id><name>李四</name><age>21</age><gender>女</gender>
</student>
</list>
dom
from xml.dom.minidom import parsexml_path = "d:/test.xml"def func_dom():"""使用dom解析xml文件, 由于dom会将整个xml文件读入内存,占用内存高,解析会比较慢"""# 将文件读取成一个dom对象dom = parse(xml_path)# 获取文档元素对象 这里获取的是<list>root = dom.documentElement# 类型是 xml.dom.minidom.Elementprint(type(root))# 根据tag=student获取所有的studentstus = root.getElementsByTagName("student")for stu in stus:# 获取属性值attr_id = stu.getAttribute("id")attr_name = stu.getAttribute("name")# 获取节点值id = stu.getElementsByTagName("id")[0].childNodes[0].dataname = stu.getElementsByTagName("name")[0].childNodes[0].dataage = stu.getElementsByTagName("age")[0].childNodes[0].datagender = stu.getElementsByTagName("gender")[0].childNodes[0].dataprint("attr_id={}\tattr_name={}\tid={}\tname={}\tage={}\tgender={}".format(attr_id, attr_name, id, name, age, gender))
sax
使用sax
最麻烦的就是需要自己写回调函数。需要了解xml.sax.handler.ContentHandler
类中几个事件的调用时机。
-
characters(content)
方法
从行开始,遇到标签之前,存在字符,content 的值为这些字符串。
从一个标签,遇到下一个标签之前, 存在字符,content 的值为这些字符串。
从一个标签,遇到行结束符之前,存在字符,content 的值为这些字符串。
标签可以是开始标签,也可以是结束标签。 -
startDocument() 方法
文档启动的时候调用。 -
endDocument() 方法
解析器到达文档结尾时调用。 -
startElement(name, attrs)
方法
遇到XML开始标签时调用,name是标签的名字,attrs是标签的属性值字典。 -
endElement(name)
方法
遇到XML结束标签时调用。
from xml.sax import ContentHandler
import xml.sax as saxxml_path = "d:/test.xml"class StudentHandler(ContentHandler):def __init__(self):# 存放所有的学生self.stus = []def startElement(self, name, attrs):# 记录当前的elementself.CurrentData = nameif name == "student":stu = {"attr_id": attrs["id"], "attr_name": attrs["name"]}self.stus.append(stu)# 记录当前学生self.CurrentStu = studef endElement(self, name):if name in ("id", "name", "age", "gender"):# 清空CurrentData 这是由于characters的调用时机会有三次# 所以当遇到介绍元素时就可以清空CurrentData保证属性值不会被覆盖self.CurrentData = ""passdef characters(self, content):if self.CurrentData in ("id", "name", "age", "gender"):self.CurrentStu[self.CurrentData]=contentpassdef func_sax():"""SAX 用事件驱动模型,通过在解析XML的过程中触发一个个的事件并调用用户定义的回调函数来处理XML文件。边读边解析,优点是占用内存小,缺点是需要自己写回调函数"""# 创建一个SAX parsersax_parser = sax.make_parser()# 关闭命名空间sax_parser.setFeature(sax.handler.feature_namespaces, 0)# 重写Handlerstu_handler = StudentHandler()sax_parser.setContentHandler(stu_handler)# 解析xml文件sax_parser.parse(xml_path)import pprintpprint.pprint(stu_handler.stus)
ElementTree
个人比较推荐这种方式去解析xml,主要是api比较友好。
def func_element_tree():"""使用ElementTree解析xml"""# 解析xml文件为ElementTree对象tree = ET.parse(xml_path)# 获取根元素root = tree.getroot()# xml.etree.ElementTree.Element# print(type(root))for stu in root:attrs = stu.attribstu_d = {"attr_id": attrs["id"], "attr_name": attrs["name"]}stu_d["id"]=stu.findtext("id")stu_d["name"]=stu.findtext("name")stu_d["age"]=stu.findtext("age")stu_d["gender"]=stu.findtext("gender")print(stu_d)
三种方式的代码运行截图
将上面三种方式的代码合并在一起后,运行结果截图如下。
HTMLParser
python提供了html.parser.HTMLParser
类去解析HTML。需要注意的是该类也是事件驱动型,和用SAX
去解析xml文件类似。
下面是该类常用的方法:
- HTMLParser.
feed
(data):接收一个字符串类型的HTML内容,并进行解析。 - HTMLParser.
handle_starttag
(tag, attrs):对开始标签的处理方法。例如<div id="main">
,参数tag指的是div,attrs指的是一个(name,Value)的列表,即列表里面装的数据是元组。 - HTMLParser.
handle_endtag
(tag):对结束标签的处理方法。例如</div>
,参数tag指的是div。 - HTMLParser.
handle_startendtag
(tag, attrs):识别没有结束标签的HTML标签,例如<img />
等。 - HTMLParser.
handle_data
(data):对标签之间的数据的处理方法。<tag>test</tag>
,data指的是“test”。
实战例子
我们获取csdn博客首页右下角的企业博客信息, 包括企业博客的 名字、原创数、粉丝数、获赞数。如下图。
思路:首先通过上面的urlopen()
函数去抓取该网页内容,然后通过html.parser.HTMLParser
类去解析HTML获取网页上列出的企业博客信息。个人觉得最重要的是需要仔细观看网页内容,然后根据需求定位到所需要的元素,即需要一定的HTML知识。因为html.parser.HTMLParser
类就是在扫描一个个标签的时候触发的事件(也就是你写的回调函数)。
下面贴出信息所在的html部分内容。
下面的代码我在上面的思路基础上又写了一个稍微没那么复杂的代码,即通过re
模块去匹配到所需要的html内容,这样就会大大地较少解析的内容,同时代码上看起来就会简洁一些。
此处就不细讲代码具体的实现逻辑了。代码关键处有注释。
# -*- coding:UTF-8 -*-from contextlib import closing
from urllib.request import urlopen
from html.parser import HTMLParser"""
获取csdn博客首页右下角的企业博客信息, 包括企业博客的 名字、原创数、粉丝数、获赞数。
"""def get_page(url):data = ""with closing(urlopen(url)) as resp:# 获取响应返回的内容data = resp.read()return data.decode()class CsdnHtmlParser(HTMLParser):def __init__(self):# 必须对父类进行初始化 要不然运行会报错HTMLParser.__init__(self)# 记录一些信息以便后面事件驱动时使用self.enterprises = []self.is_tick = Falseself.is_tick_data = Falseself.CurrentEnterprise = Noneself.name_ok = Falsedef handle_starttag(self, tag, attrs):if tag == "div" and (("class", "enterprise_r") in attrs):enterprise = {"msg": "ok"}self.CurrentEnterprise = enterpriseself.enterprises.append(enterprise)elif tag == "a" and (("target", "_blank") in attrs):if self.CurrentEnterprise:href = list(filter(lambda x: x[0] == "href", attrs))[0][1]self.CurrentEnterprise["地址"] = hrefself.name_ok = Trueelif tag == "span" and (("class", "name") in attrs):if self.CurrentEnterprise:self.is_tick = Trueself.attr_name = Noneelif tag == "span" and (("class", "number") in attrs):if self.CurrentEnterprise and self.attr_name:self.is_tick_data = Truepassdef handle_startendtag(self, tag, attrs):# print("tag: ", tag)passdef handle_endtag(self, tag):if tag == "div" and self.CurrentEnterprise:self.CurrentEnterprise = Nonepassdef handle_data(self, data):if self.CurrentEnterprise and self.name_ok:self.CurrentEnterprise["名字"] = dataself.name_ok = Falseif self.is_tick:old_attr_name = self.attr_nameself.attr_name = dataif self.is_tick_data:self.CurrentEnterprise[old_attr_name] = dataself.is_tick = Falseself.is_tick_data = Falsepasspassdef parse_page(htmldata):"""获取企业博客的 名字、原创数、粉丝数、获赞数"""csdn_parser = CsdnHtmlParser()csdn_parser.feed(htmldata)import pprintpprint.pprint(csdn_parser.enterprises)def cut_html(htmldata):import re# 记住.*?这样就不是贪婪匹配了pattern = r'.*?<div class="enterprise_r">(.*?)</p>\n\s+</div>.*?'# 这里使用re.DOTALL让.可以表示任意字符(包括回车换行符) 不加的话.不能表示回车换行符的# 使用findall找出所有匹配到的内容matchs = re.findall(pattern, htmldata, re.DOTALL)for text in matchs:# print(text)cut_parser = CutCsdnHtmlParser()cut_parser.feed(text)cut_parser.blog_info()class CutCsdnHtmlParser(HTMLParser):def __init__(self):HTMLParser.__init__(self)# 记录一些信息以便后面事件驱动时使用self.href=""self.name=""self.blog = {}self.name_ok = Falseself.is_tick = Falseself.attr_name = Noneself.is_tick_data = Nonedef handle_starttag(self, tag, attrs):if tag == "a" and (("target", "_blank") in attrs):self.href=list(filter(lambda x: x[0] == "href", attrs))[0][1]self.name_ok=Trueelif tag == "span" and (("class", "name") in attrs):self.is_tick = Trueelif tag == "span" and (("class", "number") in attrs):self.is_tick_data = Truepassdef handle_startendtag(self, tag, attrs):passdef handle_endtag(self, tag):passdef handle_data(self, data):if self.name_ok:self.name=data# 避免下次进来替换掉正确的值self.name_ok=Falseelif self.is_tick:self.attr_name=dataself.is_tick=Falseelif self.is_tick_data:self.blog[self.attr_name]=dataself.is_tick_data=Falsepassdef blog_info(self):self.blog["href"]=self.hrefself.blog["name"]=self.nameimport pprintpprint.pprint(self.blog)passif __name__ == "__main__":url = "https://www.csdn.net/"# 第一种方式是直接整个HTML文件 由于HTMLParser是事件驱动类型 代码写的会比较凌乱htmldata = get_page(url)parse_page(htmldata)# 第二种方式是首先用re模块去匹配出所需要的html内容,然后再通过HTMLParser去解析# 由于已经通过re模块找出我们所需要的内容,所以代码上相较于第一种方式会简单一点htmldata = get_page(url)cut_html(htmldata)
参考网址
廖雪峰老师Python教程之常用内建模块
argparse简述
python菜鸟教程之xml解析
python解析xml
python正则中换行符的匹配
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- 设置Android Studio开发无线调试
设置Android Studio开发无线调试1、从插件市场安装插件WIFI ADB ULTIMATE并重启Android Studio生效。这是右边框会增加一个选项,就是刚才安装的插件:2、保证手机/pad设备和电脑连接同一wifi,否则无法进行无线调试,切记。3、通过数据线连接设备,打开设备的5555端口,每次设…...
2024/4/16 10:36:04 - 计算机网络安全教程(第三版)第十章简答题答案
第 10 章 防火墙与入侵检测什么是防火墙?古时候的防火墙和目前通常说的防火墙有什么联系和区别? 答: 防火墙的本义原指古代人们的房屋之间修建的墙,这道墙可以防止火灾发生时蔓延到别的房屋。现今防火墙不是指为了防火而造的墙,而是指隔离在本地网络与外界网络之间的一道防…...
2024/4/16 10:36:29 - 腾讯T4推荐五本涨薪文档:SSM+微服务+Nginx+Redis+MySQL
SSM第1部分入门和技术基础第1章认识SSM框架和Redis第2章Java设计模式第2部分互联网持久框架- -MyBatis第3章认识MyBatis核心组件第4章MyBatis配置第5章映射器第6章动态SQL第7章MyBatis的解析和运行原理第8章插件第3部分Spring基础第9章Spring IoC的概念第10章装配Spring Bean第…...
2024/4/20 1:30:04 - 计算机网络课程设计-Socket网络通信(C++, MacOS)
实验要求: 利用Socket实现双机通信 实验目的: 利用Socket编程,采用其中的TCP面向连接方式,实现计算机数据的交换 具体要求:操作系统:可在Linux或Windows操作系统下实现 编程语言:C或C++,若使用Java、python等更高级的语言或脚本语言则须实现下面的“扩展功能” 界面要求…...
2024/4/16 10:36:04 - 计算机网络安全教程(第三版)第十一章简答题答案
第 11 章 IP安全与Web安全说明IP安全的必要性。 答: 大型网络系统内运行多种网络协议(TCP/IP、IPX/SPX和NETBEUA等),这些网络协议并非为安全通信设计。而其IP协议维系着整个TCP/IP协议的体系结构,除了数据链路层外,TCP/IP的所有协议的数据都是以IP数据报的形式传输的,目…...
2024/4/16 10:36:04 - 剑指offer-js 顺时针打印矩阵
顺时针打印矩阵 题目描述: 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字, 例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.问题分析: 定义四个变量,表示左上和右下的打…...
2024/4/24 3:55:24 - eNSP模拟器中NE40E与AR通过Eth-Tunk对接由于hash算法不同导致业务不通问题记录
故障现象,查看两端eth-trunk状态正常,但会有eth-trunk IP/DOWN的记录,并且业务不通NE40E设备查看eth-trunk信息如下[~NE]display eth-trunk 10 Eth-Trunk10s state information is: Local: LAG ID: 10 WorkingMode: STATIC Preempt Delay: Disabled …...
2024/4/24 9:35:14 - Nvidia Jetson AGX Xivier 远程开发配置 软件源, ssh, pppoe
这篇文章的目的是记录 Nvidia Jetson AGX Xivier(下面简称 Jetson)开发板的配置过程. 主要是配置了开发板的 pppoe 网络, 软件源, ssh等. 通过本文的配置, 用户可以在个人电脑上通过 ssh 应用连接 Jetson 的终端. 其它运行 Linux 系统的设备(如服务器)也可已通过类似的工作实现…...
2024/5/5 12:04:40 - 深究强化学习在谷歌芯片布局上的应用
谷歌论文:Chip Placement with Deep Reinforcement Learning。目录电路板制作流程芯片制作流程芯片布局布局宏(macros)模型结构Graph Embedding预训练Policy Network学习过程布局标准单元(standard cells)总结电路板制作流程在讲解芯片布局之前,我们先了解电路板的大致制作流…...
2024/4/24 9:35:10 - 2.4构造函数语义(编译器什么时候会生成默认构造)笔记
一.什么是默认构造函数默认构造函数(缺省构造函数):没有参数的构造函数;二.编译器什么时候会为我们生成默认构造函数传统认识认为:如果我们自己没定义任何构造函数,那么编译器就会为我们隐式自动定义 一个默认的构造函数,我们称这种构造函数为:“合成的默认构造函数”.…...
2024/4/24 9:35:03 - 42. Trapping Rain Water(数组积水)左右同时从低到高
题目: 给定n个代表海拔图的非负整数,其中每个条的宽度为1,计算下雨后它能捕获多少水。 输入: [0,1,0,2,1,0,1,3,2,1,2,1] 输出: 6 思路: 从两边开始,最左和最右比较,从较小的那一方开始,因为这样的话从这边开始的每一步的计算的都可以能够把水积住(因为短板效应)。设…...
2024/5/7 21:43:13 - 【Linux命令】《鸟哥Linux基础》第八章 文件与文件系统的压缩
第八章 文件与文件系统的压缩 网站也可以利用文件压缩的技术来进行数据传送,好让网站带宽的可利用率上升。 8.1 压缩文件的用途与技术 1 将没有使用到的空间丢出来【0000 0001---->1】 2 将重复的数据进行统计记录【100个1】 8.2 Linux系统常见的压缩命令压缩文件扩展名 压…...
2024/5/3 2:27:59 - Spring Security 简单认证与授权
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC、DI和AOP功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代…...
2024/4/24 9:35:00 - 温故知新:基于R语言的群体药代动力学数据探索
基于R语言的群体药代动力学数据探索一 、群体药代动力学数据探索目的和方法数据探索目的数据来源方法二、数据探索过程PK数据探索加载的包和设目录读取数据和数据处理平均血药浓度计算和作图每个受试者血药浓度图PD数据探索平均药效指标图每个受试者药效指标图 一 、群体药代动…...
2024/4/18 23:38:49 - 使用python一句话中的字符长度大于5时此字符反序排列输出
给定一句话,若这句话中某一个字符串的长度大于5时,就将此字符串反向排序输出 def spin_words(sentence):# 将句子中单词转化为序列,以空格分隔s = sentence.split( )#根据序列的索引,设定循环,range(len(s))获取的为序列的索引for i in range(len(s)):#获取到对应索引的字…...
2024/4/23 10:13:01 - Xshell如何配置并远程连接Linux服务器详解
如何通过Xshell远程连接Linux服务器,以及如何配置xshell各项参数。说明:本文讲解通过xshell如何连接Linux服务器,不会讲解如何安装xshell。创建会话 创建会话目录 要求:一个项目则有一个会话目录,目录下对应着项目的所有会话。这样的规划更有利于后期会话的管理,免得所有…...
2024/5/5 16:41:21 - 线程8锁机制
1 标准访问,先打印短信还是邮件package com.dym.jvm;class Phone {public synchronized void sendSMS() throws Exception{System.out.println("------sendSMS");}public synchronized void sendEmail() throws Exception{System.out.println("------sendEmail…...
2024/4/30 22:30:55 - Hive表查看各个分区的更新时间
(作者:陈玓玏data-master.net) 查看hive各分区更新的时间: show create table dev.cdl_monitor;找到LOCATION,表示的就是hive表的数据存放的路径 (下面的图片,有些信息被我隐掉啦,不过不影响阅读) 找到路径后,在命令行输入以下命令 hdfs dfs -ls hdfs://nameservice1…...
2024/4/16 10:36:34 - Java中的代理(静态代理和动态代理)
一、代理的概念:定义:为其他对象提供一种代理,以控制对这个对象的访问。关于Java中的代理,有一种常用的设计模式---代理模式;对于代理,根据创建代理类的时间点的不同,又可以分为:静态代理和动态代理。代理模式,是一种常用的Java设计模式,其特征是代理类与委托类有同样…...
2024/4/16 10:37:25 - 软件测试人员如何提升自己?送给职场中迷茫的你【共勉】
很多人在进入软件测试行业几年之后,可能都会进入一个瓶颈期,不知道如何去提升自己,但自己能意识到这个问题就是好事。 我在前面的几年也曾遇到这个问题,走出舒适区确实很难,但如果可以走出来,就会实现自己最终的目标。 今天我们就来说说在进入到行业后,应该如何在职场中…...
2024/5/5 5:24:09
最新文章
- Golang | Leetcode Golang题解之第74题搜索二维矩阵
题目: 题解: func searchMatrix(matrix [][]int, target int) bool {m, n : len(matrix), len(matrix[0])i : sort.Search(m*n, func(i int) bool { return matrix[i/n][i%n] > target })return i < m*n && matrix[i/n][i%n] target }...
2024/5/8 11:00:41 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/5/7 10:36:02 - 【嵌入式开发 Linux 常用命令系列 4.3 -- git add 不 add untracked file】
请阅读【嵌入式开发学习必备专栏 】 文章目录 git add 不add untracked file git add 不add untracked file 如果你想要Git在执行git add .时不添加未跟踪的文件(untracked files),你可以使用以下命令: git add -u这个命令只会加…...
2024/5/5 8:53:25 - 腾讯云容器与Serverless的融合:探索《2023技术实践精选集》中的创新实践
腾讯云容器与Serverless的融合:探索《2023技术实践精选集》中的创新实践 文章目录 腾讯云容器与Serverless的融合:探索《2023技术实践精选集》中的创新实践引言《2023腾讯云容器和函数计算技术实践精选集》整体评价特色亮点分析Serverless与Kubernetes的…...
2024/5/5 8:50:37 - 【外汇早评】美通胀数据走低,美元调整
原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...
2024/5/8 6:01:22 - 【原油贵金属周评】原油多头拥挤,价格调整
原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...
2024/5/7 9:45:25 - 【外汇周评】靓丽非农不及疲软通胀影响
原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...
2024/5/4 23:54:56 - 【原油贵金属早评】库存继续增加,油价收跌
原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...
2024/5/7 14:25:14 - 【外汇早评】日本央行会议纪要不改日元强势
原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...
2024/5/4 23:54:56 - 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响
原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...
2024/5/4 23:55:05 - 【外汇早评】美欲与伊朗重谈协议
原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...
2024/5/4 23:54:56 - 【原油贵金属早评】波动率飙升,市场情绪动荡
原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...
2024/5/7 11:36:39 - 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试
原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...
2024/5/4 23:54:56 - 【原油贵金属早评】市场情绪继续恶化,黄金上破
原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...
2024/5/6 1:40:42 - 【外汇早评】美伊僵持,风险情绪继续升温
原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...
2024/5/4 23:54:56 - 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势
原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...
2024/5/4 23:55:17 - 氧生福地 玩美北湖(上)——为时光守候两千年
原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...
2024/5/7 9:26:26 - 氧生福地 玩美北湖(中)——永春梯田里的美与鲜
原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...
2024/5/4 23:54:56 - 氧生福地 玩美北湖(下)——奔跑吧骚年!
原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...
2024/5/4 23:55:06 - 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!
原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...
2024/5/5 8:13:33 - 「发现」铁皮石斛仙草之神奇功效用于医用面膜
原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...
2024/5/4 23:55:16 - 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者
原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...
2024/5/4 23:54:58 - 广州械字号面膜生产厂家OEM/ODM4项须知!
原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...
2024/5/6 21:42:42 - 械字号医用眼膜缓解用眼过度到底有无作用?
原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...
2024/5/4 23:54:56 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57