python基础
1.Python有6种标准数据类型
- 数字
- 布尔(Boolean)
- 字符串(string)
- 列表(List)
- 元组(tuple)
- 字典(dict)
2.Python支持4种数字类型
- int(整形)
- long(长整型,python3取消,变为int)
- float(浮点型)
- complex(复数)
3.输入与输出
- print不换行: print(x, end=" ")
- input("请输入x值:")
- python保留字
4.数据结构 List
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
26lst = [ 'abcd', 786 , 2.23, 'john', 70.2 ]
print(lst)
print(lst[2])
# 向后添加元素
lst.append('hello')
print(lst)
# 删除最后一个元素
lst.pop()
print(lst)
# 删除内容为'abcd'的元素
lst.remove('abcd')
print(lst)
list_ = [2,3,5,1,4,6]
# 按数字大小进行排序
list_.sort()
print(list_)
#列表的便利
list_ = [1,2,3,4]
for i in list_:
print(i)
i = 0
while i < len(list_):
print(list_[i])
i+=1
元组 tuple,与列表基本相同,区别是使用()而不是[],而且元组是只读的
1
2
3tp = ( 'abcd', 786 , 2.23, 'john', 70.2 )
print(tp)
print(tp[2])
切片 字符串和列表都存在切片操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23a = "abcdef"
b = ['a','b','c','d','e','f']
#len方法可以计算字符串、列表的长度
len_ = len(a)
print(len_)
# 完整格式
print(a[0:6:1])
print(b[0:6:1])
# 简写格式
print(a[1:4])
print(b[1:4])
# 设置步进,不写默认最前到最后
print(a[::2])
print(b[::2])
# 逆步进(倒序)
print(a[::-1])
print(b[::-1])
# 前五个2步进
print(a[0:5:2])
print(b[0:5:2])
# 前3个后3个
print(a[:-3])
print(a[-3:])
字典
字典是另一种可变容器模型,且可存储任意类型对象。
格式如下所示:d = {key1 : value1, key2 : value2 }
键必须是唯一的,但值则不必。
值可以取任何数据类型,但键必须是不可变数据类型,如字符串,数字或元组。
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
34dict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
# 获取元素
name1 = dict['Name']
# get第二个参数默认是None
name2 = dict.get('Name')
print(name1)
print(name2)
# 添加元素
dict['Address'] = 'beijing'
print(dict)
# 修改元素,直接用键值覆盖
dict['Name'] = 'xiaotian'
print(dict)
# 删除字典元素
del dict['Address']
print(dict)
# 字典的遍历
dict_ = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
# 遍历keys(键)
for i in dict_.keys():
print(i)
print('---------------------------')
# 遍历values(值)
for i in dict_.values():
print(i)
print('---------------------------')
# 遍历items(键、值)
for i in dict_.items():
print(i)
for key,value in dict_.items():
print (key,end='-')
print (value)
函数
在Python之中定义函数要遵循以下几点:
- python中定义函数使用 def 关键字,后面接着函数名称和括号(),最后跟着冒号
- 函数的参数应当写在括号之中,也可以在括号中定义参数
- 函数中的 docstring 是可选的,可写可不写,建议写上
- 函数中的代码块要进行缩进
- return 可以用于返回函数返回值或者表达式,return后面什么都不写与 return None 或者不写return 等价
1.参数
调用参数的时候可以使用以下几种参数:
- 必要(required)参数
- 关键(keyword)字参数
- 默认(default)参数
- 变长(variable-length)参数
必要参数是指必须按照函数定义的参数列表的定义,按照顺序传入,如change_list函数就必须传入mylist参数,如果没有按照要求进行传递参数,将会报错:
1
2def change_list(mylist):
mylist.append('test')
当使用关键字参数对函数进行调用的时候,要按照函数定义的参数名进行赋值,这样允许不按照函数定义的参数顺序进行赋值,因为Python解释器这是可以将参数与传入变量进行对应。
1
2
3
4def test(a, b):
print(a)
print(b)
test(b=2, a=1)
默认参数指的是当参数的值没有在调用时指定的话,函数将为参数赋值一个预先定义好的值,<font color='red'>默认参数的位置应当位于参数列表的最后</font>:
1
2
3
4
5def test(a, b=5):
print(a)
print(b)
test(1)
test(1, 2)
当函数需要处理的变量的数目不确定的时候可以使用变长参数,变长参数在函数定义的时候名字没有预先确定,在定义函数的时候在变量前面增加一个星号(*)表示这是一个变长变量:
1
2
3
4
5
6# *args接收单个参数
# **kwargs接收字典型键值对
def printinfo(*args,**kwargs):
print(args)
print(kwargs)
printinfo(1,'asdas',name='asd',age=12)
2.全局变量与局部变量
在函数体中定义的变量具有局部作用域,他们只能在定义他们的函数之内被访问;全局变量可以在程序内被所有的函数访问。
1
2
3
4
5
6
7# 如果在局部使用全局变量,不加global视为在局部新建一个变量,与原变量地址空间不同。
a = 50
def test():
a = 100
print(a)
test()
print(a)
1
2
3
4
5
6
7
8# 添加global,标记为全局变量
a = 50
def test():
global a
a = 100
print(a)
test()
print(a)
1
2
3
4
5
6a = 50
def test():
num = a
print(num)
test()
print(a)
3.参数传递
python中参数的传递都是引用的传递,传递的是地址空间,也可以说传递的是变量所占的地址空间
1
2
3
4
5
6
7
8
9
10
11
12
13def change_list(mylist,str_):
mylist.append('test')
print('Inside function {}'.format(mylist))
# a指向传过来的str_的地址空间
str_ = str_ + 'def'
print(str_)
lst = [1, 2, 3]
b = 'abc'
change_list(lst,b)
# 经过函数的处理,lst最后增加了一个元素
# 经过函数的处理,a,b都指向'abc'的地址空间
print(lst)
print(b)
4.匿名函数
匿名函数的定义方法与前面讲的传统的使用def
的方法是不同,使用lambda
关键词定义匿名函数。
- 匿名函数可以接收任意数目的参数,但是返回值只能是一个值或者表达式,他们不能包含命令或者多个表达式。
- lambda 函数具有自己的命名空间,他们除了参数列表中的变量以及全局变量之外无法访问其他的变量。
- lambda 函数无法直接被用来打印变量,lambda 函数需要一个表达式
1
2
3 sm = lambda x, y: x + y
res = sm(1, 2)
print(res)
文件操作
1.open函数
open函数被用来打开或者创建文件,它将会返回一个file对象。
1
file object = open(file_name [, access_mode][, buffering][,encoding])
有几种常见的模式:
- r 表示以只读方式打开 (默认模式)
- rb 表示以二进制只读打开
- r+ 以读写方式打开
- rb+ 以二进制读写方式打开
- w 以只写方式打开(如果已有文件,将会覆盖,如果没有将会创建)
- wb 以二进制只写打开(如果已有文件,将会覆盖,如果没有将会创建)
- w+ 以读和写的方式打开一个文件(如果已有文件,将会覆盖,如果没有将会创建)
- wb+ 以二进制方式读和写的方式打开一个文件(如果已有文件,将会覆盖,如果没有将会创建)
- a 表示 append,追加模式,如果文件存在的话,指针将位于文件的末尾,如果没有文件的话将会创建一个
- ab 以二进制格式追加模式打开一个文件
- a+ 以追加和读的方式打开一个文件
- ab+ 以追加和读的方式打开二进制格式文件
buffer是读写的缓冲区间,有可以选三种值: 0 表示不适用buffer,1 表示 buffer 文件中的一行,其余正整数表示buffer的字节数
encoding是指明对文件编码,仅适用于文本文件。如果不明编码方式,默认是使用locale.getpreferredencoding()函数返回的编码方式。
2.file对象属性
- file.close 返回文件是否关闭
- file.mode 返回打开文件的模式
- file.name 返回文件的名字
1
2
3
4
5 fo = open("foo.txt", "wb")
print ("Name of the file: ", fo.name)
print ("Closed or not : ", fo.closed)
print ("Opening mode : ", fo.mode)
fo.close()
close()方法 file对象的close()方法用于将没有写入文件的信息写入文件以后关闭文件,<font color='red'>在打开文件以后要记得关闭文件。</font>
3.read()和write()
file 对象可以使用 read() 对文件的内容进行读取,在使用read()对文件进行读取的时候会一次性的读取文件的全部内容。还可以使用readline(),每次读取文件的一行,readlines()则可以一次读取文件中的全部行,并且返回一个列表。
write() 文件可以用于将内容写入文件,在写完文件之后一定要记得使用close()方法保证对于文件的更改已经写入了硬盘。
在对文件进行读写操作的时候,常用的一种方式是使用with
,这样Python在对文件读写完成后会自动调用close()
方法:
1
2
3
4
5
6
7
8
9
10
11
12fo = open("foo.txt", "w+")
fo.write("hello world")
fo.close()
fo = open("foo.txt", "r")
t = fo.read()
print(t)
with open("foo.txt", "w+") as f:
for i in range(10):
f.write(str(i) + '\n')
with open("foo.txt", "r") as f:
print(f.readlines())
Python 进阶
1.生成器
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。
在Python中,这种一边循环一边计算的机制,称为生成器generator。
1
2
3
4
5
6
7
8
9
10
11# 这是一个列表生成式
L = [ x*2 for x in range(5)]
# 最简单的生成器写法
G = ( x*2 for x in range(5))
print(type(L))
print(type(G))
print(next(G))
print(next(G))
print(next(G))
# send输入高级用法
print(G.send(None))
<font color='red'>经常我们的生成的生成器不会使用next(),而是直接使用for循环遍历,而生成器的写法也就是将函数的return变成yield,我们后面的AI学习中可能遇到很大的数据量,因此生成器是我们必不可少的工具</font>
1
2
3
4
5
6
7
8# 通过生成器实现斐波那契数列
def fib(times):
n = 0
a,b = 0,1
while n<times:
yield b
a,b = b,a+b
n+=1
2. 迭代器
迭代是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。 1、可迭代对象 可以直接作用于 for 循环的数据类型有以下几种:
- 一类是集合数据类型,如 list 、 tuple 、 dict 、 set 、 str 等;
- 一类是 generator ,包括生成器和带 yield 的generator function。
这些可以直接作用于 for 循环的对象统称为可迭代对象: Iterable <font color='red'>迭代器都是可迭代对象</font>
2、迭代器
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
<font color='red'>生成器都是迭代器</font>
3、iter()函数
生成器都是 Iterator 对象,但 list 、 dict 、 str 虽然是 Iterable ,却不是 Iterator 。
把 list 、 dict 、 str 等 Iterable 变成 Iterator 可以使用 iter() 函数:
1
2
3
4# list 是可迭代对象
a = [1,2,3,4]
for i in a:
print(i)
3.装饰器
装饰器是由python闭包系统实现的,本质上,就是一个返回函数的高阶函数,请看:
1
2
3
4
5
6
7
8
9
10
11
12from time import ctime
def timefun(func):
def wrappedfunc(*args,**kwargs):
print("%s called at %s"%(func.__name__, ctime()))
return func(*args,**kwargs)
return wrappedfunc
def test(a,b):
print(a+b)
test(1,2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16# 通过装饰器验证登陆 只有输入1才可以运行
def login(func):
def wfunc(*args,**kwargs):
pop = input('输入编号')
if pop == '1':
print('欢迎登陆')
return func(*args,**kwargs)
else:
print('陌生访问')
return wfunc
def test(a,b):
print(a+b)
test(1,2)
错误处理
1.异常处理
在python中对异常进行处理时经常使用以下结构:
1
2
3
4
5
6
7
8try:
pass
except error0:
pass
except error1:
pass
finally:
pass
try
后面跟着需要执行的代码块,except
后面标注异常的类型,在出现对应的异常的时候执行对应代码块,无论程序是否正确执行finally
后面接着的代码块都会在最后执行。Python 中内置的异常类型,参考这个连接。
2.Assert语句
assert
使用方法:
1
assert Expression[, Expression]
assert 将会判断后面跟的表达式是否为真,如果为false的话将会抛出AssertionError
异常,经常可以用于对变量类型,或者程序逻辑进行检查,比如我们写一个计算两个向量内积的程序:
1
2
3
4
5
6def mul(x, y):
assert len(x) == len(y), "size of 2 vectors should be same"
t = 0
for i in range(len(x)):
t += x[i] * y[i]
return t
Python 爬虫基础、技巧
1.JSON
JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式,是前后端交互中常用的数据格式,它与python内建的字典很相似,可以相互转换,然后供我们提取数据
python3 中可以使用 json 模块来对 JSON 数据进行编解码,它包含了两个函数:
1
2json.dumps(): 对数据进行编码,也就是字典变为json.
json.loads(): 对数据进行解码,也就是json变为字典.
<font color='red'>json.dumps()中 可以将ensure_ascii 设为 False可以避免一些不必要的问题</font>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import json
# 一个标准的python字典
data = {
'no' : 1,
'name' : 'Runoob',
'url' : 'http://www.runoob.com'
}
# 将字典转换成json
json_str = json.dumps(data,ensure_ascii=False)
print(json_str)
print(type(json_str))
# 一串json数据
json_str = '{"name": "Runoob", "no": 1, "url": "http://www.runoob.com"}'
# 将json转为字典
dict_ = json.loads(json_str)
print(dict_)
print(dict_['name'])
print(type(dict_))
2.Requests库
Requests is an elegant and simple HTTP library for Python, built for human beings.
简单的请求模式:
1
2
3
4# get请求
response = requests.get(url, params={}, headers={}, cookie={}, proxies={}, verify=False)
# post请求
response = requests.post(url, data={}, headers={}, cookie={}, proxies={}, verify=False)
response的方法:
1
2
3
4
5
6response.status_code #响应状态码
response.content #字节方式的响应体,会自动为你解码 gzip 和 deflate 压缩
response.text #字符串方式的响应体,会自动根据响应头部的字符编码进行解码
response.json() #Requests中内置的JSON解码器
response.headers #响应的响应行
response.request.headers #请求的请求行
我们可以通过Cookie或者Session进行模拟登陆,获取登录后的数据。
1
2
3
4
5
6
7
8
9# Cookie进行模拟登陆
import re
import requests
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36','Cookie':'anonymid=jd5aevsb-2nuy7n; _r01_=1; __utmz=151146938.1520997522.1.1.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; __utma=151146938.942267969.1520997521.1520997521.1520997521.1; depovince=BJ; _de=84C13AEF64FC380CAE794CB9CCA086D2; ln_uact=18610864225; ln_hurl=http://head.xiaonei.com/photos/0/0/men_main.gif; jebe_key=59aeee30-3816-4484-9881-4f6690bdce3f%7C100ad246dd59063859de7b1ea3f6ad38%7C1526957380310%7C1%7C1526957382140; jebecookies=74f2005f-ba3d-4a61-a1d0-19948a4d8970|||||; JSESSIONID=abcD_hI_-8WDRf9JK4fow; ick_login=cc4c902c-a43d-4481-8cb3-04ecdc2b9c2f; p=9a54e6619286a17266723fc6b08cc5f04; first_login_flag=1; t=97663cf647a6e85e1bd5d13636b0a2724; societyguester=97663cf647a6e85e1bd5d13636b0a2724; id=963865664; xnsid=7a1d85fa; loginfrom=syshome; wp_fold=0'}
url = 'http://www.renren.com/963865664/profile'
resp = requests.get(url, headers=headers)
html = resp.content.decode()
print(re.findall(r"李**",html))
1
2
3
4
5
6
7
8
9
10
11
12
13# Session进行模拟登陆
import requests
import re
url = "http://www.renren.com/PLogin.do"
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36'}
data = {
'email':'186****4225',
'password':'q****6'
}
session_my = requests.session()
session_my.post(url, data=data, headers=headers)
html = session_my.get('http://www.renren.com/963865664/profile', headers=headers).content.decode()
print(re.findall(r"李**",html))
3.Xpath
XPath 是一门在 XML 文档中查找信息的语言。XPath 用于在 XML 文档中通过元素和属性进行导航。 lxml库:
- 导入lxml的etree库
- 利用etree.HTML,将字符串转化为Element对象
- Element对象具有xpath的方法
- lxml 可以自动修正 html 代码
看一个实例
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
39ht = """
<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>·
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="CHILDREN">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="WEB">
<title lang="en">XQuery Kick Start</title>
<author>James McGovern</author>
<author>Per Bothner</author>
<author>Kurt Cagle</author>
<author>James Linn</author>
<author>Vaidyanathan Nagarajan</author>
<year>2003</year>
<price>49.99</price>
</book>
<book category="WEB">
<title lang="en111">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
"""
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
29from lxml import etree
xml = etree.HTML(ht)
# 由于etree将xml修正,根节点已经不是bookstore,因此我们采用//
# 注意xpath返回的内容都是列表
# 选取所有 title的文本
titles = xml.xpath('//bookstore/book/title/text()')
print(titles)
# 选取第一个 title的文本
one_title = xml.xpath('//bookstore/book[1]/title/text()')
print(one_title)
# 选取价格大于35的book的year信息
year = xml.xpath('//bookstore/book[price>35]/year/text()')
print(year)
# 选取book category="CHILDREN"的书的price
price = xml.xpath('//bookstore/book[@category="CHILDREN"]/price/text()')
print(price)
# 选取book category=“WEB”的书的title的lang属性
lang = xml.xpath('//bookstore/book[@category="WEB"]/title/@lang')
print(lang)
# xpath如果不去选择属性和txt,会返回Element对象,可以对Element对象再次xpath
aaa = xml.xpath('//bookstore/book[@category="WEB"]/title')
print(aaa)
for i in aaa:
bbb = i.xpath('./@lang')
print(bbb)
参考资料
4.反反爬
反反爬虫措施,就是反反爬,当然还有反反反爬虫。 反反爬虫措施有以下几种:
- 降低访问频率(在requests前加time.sleep())
- 模拟请求头
- 模拟登陆
- 使用代理IP
- 携带cookie
- 设置Referer header(躲过referer检测)
- 逆向js(解密别人的反爬手段,这个比较高级)