Python 爬虫(Spider)基础 - 大约16万字
- 爬虫(Spider)
- 1、Python 基础
- 2、Urllib
- 3、解析
- 4、Selenium
- 5、Requests
- 6、scrapy 框架
爬虫(Spider)
1、Python 基础
1.Python 环境安装
1.1 下载 Python
1.2 安装 Python
一路傻瓜式安装
1.3 测试是否安装成功
Win + R
,输入 cmd
,回车
若出现错误:'python',不是内部命令或外部命令,也不是可运行的程序或批处理文件。
原因:环境变量的问题,可能是因为在安装 Python 的过程中没有勾选 Add Python 3.x to PATH
选项,此时需要手动对 Python 进行配置。
1.4 配置 Python 环境变量
注意:如果在安装过程中,已经勾选了 Add Python 3.x to PATH
选项,并且在 cmd
命令模式下,输入 python 指令显示版本信息等不报错,就不需要再手动的配置 Python。(跳过手动配置环境变量这一步)
右键此电脑
,选择属性
,
选择 高级系统设置
--> 环境变量
-->找到并且双击 Path
双击 Path
,在弹框里点击 新建
,添加 Python 的安装目录,把路径添加进去,然后到 Path 里 编辑
环境变量,用% %
来读取python的安装路径即可
2.pip 的使用
pip 是一个现代的,通用的Python包管理工具。提供了对 Python 包的查找、下载、安装、卸载的功能,便于我们对Python的资源包进行管理。
2.1 安装
在安装 Python 时,会自动下载并且安装 pip.
2.2 配置
在windows命令行里,输入 pip -V
可以查看 pip 的版本。
# 查看pip版本(大写V)
pip -V
如果在命令行里,运行 pip -V
,出现如下提示:'pip',不是内部命令或外部命令,也不是可运行的程序或批处理文件。
原因:环境变量的问题,可能是因为在安装 Python 的过程中没有勾选 Add Python 3.x to PATH
选项,此时需要手动对 Python 进行配置。
右键 此电脑
--> 环境变量
-->找到并且双击 Path
-->在弹窗里点击 编辑
–>找到pip的安装目录(也就是python安装目录下Scripts的路径),把路径添加进去。
配置环境变量(已配请跳过,方式有很多种,随便怎么配都可以)
2.3 使用 pip 管理 Python 包
pip install <包名> # 安装指定的包
pip uninstall <包名> # 删除指定的包
pip list # 显示已经安装的包
pip freeze # 显示已经安装的包,并且以指定的格式显示
2.4 修改 pip 下载源
- 运行
pip install
命令会从网站上下载指定的python包,默认是从 https://files.pythonhosted.org/ 网站上下载。这是个国外的网站,遇到网络情况不好的时候,可能会下载失败,我们可以通过命令,修改pip现在软件时的源。 - 格式:
pip install 包名 -i 国内源地址
- 示例:
pip install ipython -i https://pypi.mirrors.ustc.edu.cn/simple/
就是从中国科技大学(ustc)的服务器上下载requests(基于python的第三方web框架)
国内常用的pip下载源列表:
- 阿里云:http://mirrors.aliyun.com/pypi/simple/
- 中国科技大学:https://pypi.mirrors.ustc.edu.cn/simple/
- 豆瓣(douban):http://pypi.douban.com/simple/
- 清华大学:https://pypi.tuna.tsinghua.edu.cn/simple/
- 中国科学技术大学:[http://pypi.mirrors.ustc.edu.cn/simple/](
2.4.1 临时修改
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/
2.4.2 永久修改
Linux下,修改~/.pip/pip.conf
(或者创建一个),将index-url变量修改为所要更换的源地址:
[global]
index-url = https://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host = mirrors.ustc.edu.cn
windows下,在 user 目录中创建一个 pip 目录,如:C:\Users\xxx\pip
,新建文件 pip.ini
,内容如下:
3.运行 Python 程序
3.1 终端运行
-
直接在python解释器中书写代码
# 退出python环境 exit() Ctrl+Z,Enter
-
使用ipython解释器编写代码
使用pip命令,可以快速的安装IPython.
# 安装ipython pip install ipython
3.2 运行 Python 文件
使用python指令运行后缀为.py的python文件
python 文件路径\xxx.py
3.3 Pycharm(IDE 集成开发环境)
IDE的概念
IDE(Integrated Development Environment)又被称为集成开发环境。说白了,就是有一款图形化界面的软件,它集成了编辑代码,编译代码,分析代码,执行代码以及调试代码等功能。在Python开发中,常用的IDE是Pycharm.
pycharm由捷克公司JetBrains开发的一款IDE,提供代码分析、图形化调试器,集成测试器、集成版本控制系统等,主要用来编写Python代码。
3.3.1 下载 Pycharm
官网下载地址:http://www.jetbrains.com/pycharm/download
3.3.2 安装 Pycharm
一路傻瓜式安装
目前已更新到 2021.2.2
版本,可以到 官网下载 使用,官网更新时间:2021.09.15
3.3.3 使用 Pycharm
新建一个项目
可以选择已存在的解释器
运行测试
4.注释
注释是给程序员看的,为了让程序员方便阅读代码,解释器会忽略注释。使用自己熟悉的语言,适当的对代码进行注释说明是一种良好的编码习惯。
4.1 注释的分类
在Python中支持单行注释
和多行注释
。
单行注释
以 #
开头。
多行注释
以 '''
开始,并以 '''
结束,为多行注释。
5.变量及数据类型
5.1 变量的定义
对于重复使用,并且经常需要修改的数据,可以定义为变量,来提高编程效率。
变量即是可以变化的量,可以随时进行修改。
程序就是用来处理数据的,而变量就是用来存储数据的。
5.2 变量的语法
变量名 = 变量值 。(这里的 = 作用是赋值。)
5.3 变量的访问
定义变量后可以使用变量名来访问变量值。
5.4 变量的数据类型
在 Python 里为了应对不同的业务需求,也把数据分为不同的类型。
变量没有类型,数据才有类型
5.5 查看数据类型
在python中,只要定义了一个变量,而且它有数据,那么它的类型就已经确定了,不需要开发者主动的去说明它的类型,系统会自动辨别。也就是说在使用的时候 “变量没有类型,数据才有类型
”。
查看一个变量存储的数据类型,可以使用 type(变量的名字)
,来查看变量存储的数据类型。
# 变量的数据类型
# 数值
money = 100000
print(type(money)) # <class 'int'>
# 布尔
gender = True
sex = False
print(type(gender)) # <class 'bool'>
# 字符串
s = '字符串'
s1 = "字符串1"
s2 = '"单双引号交叉嵌套"'
s3 = "'单双引号交叉嵌套'"
print(s2)
print(type(s)) # <class 'str'>
# 列表
name_list = ['Tomcat', 'Java']
print(type(name_list)) # <class 'list'>
# tuple 元组
age_tuple = (16, 17, 18)
print(type(age_tuple)) # <class 'tuple'>
# dictionary 字典 变量名 = {key:value,key:value,...}
person = {'name': 'admin', 'age': 18}
print(type(person)) # <class 'dict'>
6.标识符与关键字
计算机编程语言中,标识符是用户编程时使用的名字,用于给变量、常量、函数、语句块等命名,以建立起名称与使用之间的关系。
- 标识符由
字母
、下划线
和数字
组成,且数字不能开头
。 - 严格
区分大小写
。 - 不能使用关键字。
6.1 命名规范
标识符命名要做到顾名思义(见名知意)。
遵守一定的命名规范。
-
驼峰命名法,又分为
大驼峰
命名法和小驼峰
命名法。- 小驼峰式命名法(lower camel case): 第一个单词以小写字母开始;第二个单词的首字母大写,例如:myName、aDog
- 大驼峰式命名法(upper camel case): 每一个单字的首字母都采用大写字母,例如:FirstName、LastName.
-
还有一种命名法是用下划线“_”来连接所有的单词,比如send_buf. Python的命令规则遵循PEP8标准
6.2 关键字
关键字:一些具有特殊功能的标识符。
关键字,已经被python官方使用了,所以不允许开发者自己定义和关键字相同名字的标识符。
False | None | True | and | as | assert | break | class | continue | def | del |
---|---|---|---|---|---|---|---|---|---|---|
elif | else | except | finally | for | from | global | if | import | in | is |
lambda | nonlocal | not | or | pass | raise | return | try | while | with | yield |
7.类型转换
函数 | 说明 |
---|---|
int(x) | 将 x 转换为一个整数 |
float(x) | 将 x 转换为一个浮点数 |
str(x) | 将对象 x 转换为字符串 |
bool(x) | 将对象 x 转换成为布尔值 |
转换为整数
print(int("10")) # 10 将字符串转换成为整数
print(int(10.98)) # 10 将浮点数转换成为整数
print(int(True)) # 1 布尔值True转换成为整数是 1
print(int(False)) # 0 布尔值False转换成为整数是 0
# 以下两种情况将会转换失败
'''
123.456 和 12ab 字符串,都包含非法字符,不能被转换成为整数,会报错
print(int("123.456"))
print(int("12ab"))
'''
转换成为浮点数
f1 = float("12.34")
print(f1) # 12.34
print(type(f1)) # float 将字符串的 "12.34" 转换成为浮点数 12.34
f2 = float(23)
print(f2) # 23.0
print(type(f2)) # float 将整数转换成为了浮点数
转换成为字符串
str1 = str(45)
str2 = str(34.56)
str3 = str(True)
print(type(str1),type(str2),type(str3))
转换成为布尔值
print(bool('')) # False
print(bool("")) # False
print(bool(0)) # False
print(bool({})) # False
print(bool([])) # False
print(bool(())) # False
8.运算符
8.1 算术运算符
算术运算符 | 描述 | 示例(a=10 ,b=20) |
---|---|---|
+ | 加 | 两个对象相加 a + b 输出结果 30 |
- | 减 | 得到负数或是一个数减去另一个数 a - b 输出结果 -10 |
* | 乘 | 两个数相乘或是返回一个被重复若干次的字符串 a * b 输出结果 200 |
/ | 除 | b / a 输出结果 2 |
// | 整除 | 返回商的整数部分 9//2 输出结果 4 , 9.0//2.0 输出结果 4.0 |
% | 取余 | 返回除法的余数 b % a 输出结果 0 |
** | 指数 | a**b 为10的20次方 |
() | 小括号 | 提高运算优先级,比如: (1+2) * 3 |
# 注意:混合运算时,优先级顺序为: ** 高于 * / % // 高于 + - ,为了避免歧义,建议使用 () 来处理运算符优先级。 并且,不同类型的数字在进行混合运算时,整数将会转换成浮点数进行运算。
>>> 10 + 5.5 * 2
21.0
>>> (10 + 5.5) * 2
31.0
# 如果是两个字符串做加法运算,会直接把这两个字符串拼接成一个字符串。
In [1]: str1 ='hello'
In [2]: str2 = ' world'
In [3]: str1+str2
Out[3]: 'hello world'
# 如果是数字和字符串做加法运算,会直接报错。
In [1]: str1 = 'hello'
In [2]: a = 2
In [3]: a+str1
---------------------------------------------------------------------------
TypeError Traceback (most recent call last) <ipython-input-3-993727a2aa69> in <module>
----> 1 a+str1
TypeError: unsupported operand type(s) for +: 'int' and 'str'
# 如果是数字和字符串做乘法运算,会将这个字符串重复多次。
In [4]: str1 = 'hello'
In [5]: str1*10
Out[5]: 'hellohellohellohellohellohellohellohellohellohello'
8.2 赋值运算符
赋值运算符 | 描述 | 示例 |
---|---|---|
= | 赋值运算符 | 把 = 号右边的结果 赋给 左边的变量,如 num = 1 + 2 * 3,结果num的值为7 |
复合赋值运算符 | 描述 | 示例 |
---|---|---|
+= | 加法赋值运算符 | c += a 等效于 c = c + a |
-= | 减法赋值运算符 | c -= a 等效于 c = c - a |
*= | 乘法赋值运算符 | c *= a 等效于 c = c * a |
/= | 除法赋值运算符 | c /= a 等效于 c = c / a |
//= | 整除赋值运算符 | c //= a 等效于 c = c // a |
%= | 取模赋值运算符 | c %= a 等效于 c = c % a |
**= | 幂赋值运算符 | c **= a 等效于 c = c ** a |
# 单个变量赋值
>>> num = 10
>>> num
10
# 同时为多个变量赋值(使用等号连接)
>>> a = b = 4
>>> a
4
>>> b
4
>>>
# 多个变量赋值(使用逗号分隔)
>>> num1, f1, str1 = 100, 3.14, "hello"
>>> num1
100
>>> f1
3.14
>>> str1
"hello"
# 示例:+=
>>> a = 100
>>> a += 1 # 相当于执行 a = a + 1
>>> a
101
# 示例:*=
>>> a = 100
>>> a *= 2 # 相当于执行 a = a * 2
>>> a
200
# 示例:*=,运算时,符号右侧的表达式先计算出结果,再与左边变量的值运算
>>> a = 100
>>> a *= 1 + 2 # 相当于执行 a = a * (1+2)
>>> a
300
8.3 比较运算符
<>
:Python version 3.x does not support <>, use != instead,Python 2 版本支持 <>
,Python 3 版本不再支持 <>
,用 !=
代替。
所有比较运算符,返回1表示真,返回0表示假,这分别与特殊的变量True和False等价。
比较运算符 | 描述 | 示例(a=10,b=20) |
---|---|---|
== | 等于:比较对象是否相等 | (a == b) 返回 False |
!= | 不等于:比较两个对象是否不相等 | (a != b) 返回 True |
> | 大于:返回x是否大于y | (a > b) 返回 False |
>= | 大于等于:返回x是否大于等于y | (a >= b) 返回 False |
< | 小于:返回x是否小于y | (a < b) 返回 True |
<= | 小于等于:返回x是否小于等于y | (a <= b) 返回 True |
8.4 逻辑运算符
逻辑运算符 | 表达式 | 描述 | 示例 |
---|---|---|---|
and | x and y | 只要有一个运算数是False,结果就是False; 只有所有的运算数都为True时,结果才是True 若前面为False,后面不执行(短路与) |
True and True and False–>结果为False True and True and True–>结果为True |
or | x or y | 只要有一个运算数是True,结果就是True; 只有所有的运算数都为False时,结果才是False 若前面为True,后面不执行(短路或) |
False or False or True–>结果为True False or False or False–>结果为False |
not | not x | 布尔"非" - 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。 | not True --> False |
9.输入输出
9.1 输出
普通输出:
print('xxx')
格式化输出:
# %s:代表字符串 %d:代表数值
age = 18
name = "admin"
print("我的姓名是%s, 年龄是%d" % (name, age))
9.2 输入
在Python中,获取键盘输入的数据的方法是采用 input 函数
- input()的小括号中放入的是提示信息,用来在获取数据之前给用户的一个简单提示
- input()在从键盘获取了数据以后,会存放到等号右边的变量中
- input()会把用户输入的任何值都作为字符串来对待
name = input("请输入姓名:")
print('您输入的姓名是:%s' % name)
10.流程控制语句
10.1 if 条件判断语句
# ① 单if语句
if 判断条件:
当条件成立时,执行语句
# 如:
age = 16
if age >= 18:
print("长大了")
# ② if-else 语句
if 判断条件:
条件成立,执行语句
else:
条件不成立,执行语句
# 如:
height = input('请输入您的身高(cm):\n')
if int(height) <= 150:
print('科技园免票')
else:
print('需要买票哦')
# ③ elif 语句
if 判断条件1:
条件1成立,执行语句
elif 判断条件2:
条件2成立,执行语句
elif 判断条件3:
条件3成立,执行语句
elif 判断条件n:
条件n成立,执行语句
# 如:
score = 77
if score>=140:
print('成绩为A')
elif score>=130:
print('成绩为B')
elif score>=120:
print('成绩为C')
elif score>=100:
print('成绩为D')
elif score<90:
print('成绩为E')
10.2 for 循环
# for 循环
for 临时变量 in 列表、字符串等可迭代对象:
循环体
# 如:
name = 'admin'
for i in name:
print(i)
# range(x)的范围:[0,x)
for i in range(3):
print(i) # 0 1 2
# range(a,b)的范围:[a,b)
for i in range(2, 5):
print(i) # 2 3 4
# range(a,b,c)的范围:[a,b),c为步长,在这个范围内按步长值增幅
for i in range(2, 10, 3):
print(i) # 2 5 8
11.数据类型
11.1 字符串
字符串中常见的方法/函数
方法/函数 | 描述 |
---|---|
len() | 获取字符串的长度 |
find() | 查找指定内容在字符串中是否存在,如果存在,就返回该内容在字符串中第一次出现的开始位置索引值,如果不存在,则返回-1 |
startswith()/endswith | 判断字符串是不是以谁谁谁开头/结尾 |
count() | 返回 subStr 在 start 和 end 之间 在 objectStr 里面出现的次数 |
replace() | 替换字符串中指定的内容,如果指定次数count,则替换不会超过count次 |
split() | 通过参数的内容切割字符串 |
upper()/lower() | 转换大小写 |
strip() | 去除字符串两边空格 |
join() | 字符串拼接 |
str1 = ' Administrators '
print(len(str1)) # 18
print(str1.find('d')) # 3
print(str1.startswith('a')) # False
print(str1.endswith('s')) # False
print(str1.count('s')) # 2
print(str1.replace('s', '', 1)) # Adminitrators
print(str1.split('n')) # [' Admi', 'istrators ']
print(str1.upper()) # ADMINISTRATORS
print(str1.lower()) # administrators
print(str1.strip()) # Administrators
print(str1.join('admin')) # a Administrators d Administrators m Administrators i Administrators n
11.2 列表
列表的增删改查
添加元素 | 描述 |
---|---|
append() | 在列表末尾追加一个新元素 |
insert() | 在指定索引位置处插入新元素 |
extend() | 在列表末尾追加一个新列表的所有元素 |
# 添加元素
name_list = ['zhang', 'cheng', 'wang', 'li', 'liu']
print(name_list) # ['zhang', 'cheng', 'wang', 'li', 'liu']
name_list.append('tang')
print(name_list) # ['zhang', 'cheng', 'wang', 'li', 'liu', 'tang']
name_list.insert(2, 'su')
print(name_list) # ['zhang', 'cheng', 'su', 'wang', 'li', 'liu', 'tang']
subName = ['lin', 'qing', 'xue']
name_list.extend(subName)
print(name_list) # ['zhang', 'cheng', 'su', 'wang', 'li', 'liu', 'tang', 'lin', 'qing', 'xue']'xue']
修改元素 | 描述 |
---|---|
list[index] = modifyValue | 通过指定下标赋值,来修改列表元素 |
# 修改元素name_list[0] = 'zhao'
print(name_list) # ['zhao', 'cheng', 'su', 'wang', 'li', 'liu', 'tang', 'lin', 'qing', 'xue']
查找元素 | 描述 |
---|---|
in | 判断存在,若存在,结果为true,否则为false |
not in | 判断不存在,若不存在,结果为true,否则false |
# 查找元素
findName = 'li'
# 在列表 ['zhao', 'cheng', 'su', 'wang', 'li', 'liu', 'tang', 'lin', 'qing', 'xue'] 中,查到了姓氏:li
if findName in nameList:
print('在列表 %s 中,查到了姓氏:%s' % (nameList, findName))
else:
print('在列表 %s 中,没查到姓氏:%s' % (nameList, findName))
findName1 = 'qian'
# 在列表 ['zhao', 'cheng', 'su', 'wang', 'li', 'liu', 'tang', 'lin', 'qing', 'xue'] 中,没查到姓氏:qian
if findName1 not in nameList:
print('在列表 %s 中,没查到姓氏:%s' % (nameList, findName1))
else:
print('在列表 %s 中,查到了姓氏:%s' % (nameList, findName1))
删除元素 | 描述 |
---|---|
del | 根据下标进行删除 |
pop() | 默认删除最后一个元素 |
remove | 根据元素的值进行删除 |
# 删除元素
print(nameList) # ['zhao', 'cheng', 'su', 'wang', 'li', 'liu', 'tang', 'lin', 'qing', 'xue']
# del nameList[1] # 删除指定索引的元素
# print(nameList) # ['zhao', 'su', 'wang', 'li', 'liu', 'tang', 'lin', 'qing', 'xue']
# nameList.pop() # 默认输出最后一个元素
# print(nameList) # ['zhao', 'cheng', 'su', 'wang', 'li', 'liu', 'tang', 'lin', 'qing']
# nameList.pop(3) # 删除指定索引的元素
# print(nameList) # ['zhao', 'cheng', 'su', 'li', 'liu', 'tang', 'lin', 'qing', 'xue']
nameList.remove('zhao') # 删除指定元素值的元素
print(nameList) # ['cheng', 'su', 'wang', 'li', 'liu', 'tang', 'lin', 'qing', 'xue']
11.3 元组
Python的元组与列表类似,不同之处在于元组的元素数据不能修改,而列表的元素数据是可以修改的
,元组使用小括号
,列表使用中括号
。
# 元组
nameTuple = ('zhang', 'cheng', 'wang', 'li', 'liu')
print(nameTuple) # ('zhang', 'cheng', 'wang', 'li', 'liu')
# nameTuple[3] = 'su' # 元组不可以修改里面元素的值
# print(nameTuple) # TypeError: 'tuple' object does not support item assignment
ageInt = (16) # 若不写逗号,则是int类型
print(ageInt, type(ageInt)) # 16 <class 'int'>
ageTuple = (17,) # 定义只有一个元素的元组,需要在唯一的元素后写一个逗号
print(ageTuple, type(ageTuple)) # (17,) <class 'tuple'>
11.4 切片
切片是指对操作的对象截取其中一部分的操作。字符串
、列表
、元组
都支持切片操作。
切片的语法
# 切片的区间[起始索引,结束索引),步长表示切片间隔,切片跟截取没啥区别,注意是左闭右开区间
[起始索引:结束索引:步长] # 按指定步长,从起始索引到结束索引截取
[起始索引:结束索引] # 默认步长1,可以简化不写
# 切片
str_slice = 'Hello World!'
# 切片遵循左闭右开区间,切左不切右
print(str_slice[2:]) # llo World!
print(str_slice[0:5]) # Hello
print(str_slice[2:9:2]) # loWr
print(str_slice[:8]) # Hello Wo
11.5 字典
字典的增删改查
使用key查找数据和使用get()来获取数据
查看元素 | 描述 |
---|---|
dictionaryName[‘key’] | 指定key查找对应的value值,访问不存在的key,报错 |
dictionaryName.get(‘key’) | 使用其get(‘key’)方法来获取key对应的value值,访问不存在的key,返回None |
# 查看元素
personDictionary = {'name': '王者', 'age': 16}
print(personDictionary) # {'name': '王者', 'age': 16}
print(personDictionary['name'], personDictionary['age']) # 王者 16
# print(personDictionary['noExistKey']) # KeyError: 'noExistKey',以中括号指定key的形式,访问不存在的key,会报错
print(personDictionary.get('name')) # 王者
print(personDictionary.get('noExistKey')) # None,以get()的形式,访问不存在的key,会返回 None,不报错
修改元素 | 描述 |
---|---|
dictionaryName[‘key’] = modifiedValue | 将新值赋值给需要修改的key的值 |
# 修改元素
petDictionary = {'name': '荣耀', 'age': 17}
print(petDictionary) # {'name': '荣耀', 'age': 17}
petDictionary['age'] = 18
print(petDictionary) # {'name': '荣耀', 'age': 18}
添加元素 | 描述 |
---|---|
dictionaryName[‘key’] = newValue | 使用 变量名[‘键’] = 数据 时,这个“键”在字典中,不存在,就新增这个元素 |
# 添加元素
musicDictionary = {'name': '网易', 'age': 19}
print(musicDictionary) # {'name': '网易', 'age': 19}
# musicDictionary['music'] = 'xxx' # key 不存在时,新增元素
# print(musicDictionary) # {'name': '网易', 'age': 19, 'music': 'xxx'}
musicDictionary['age'] = '20' # key 存在时,覆盖元素
print(musicDictionary) # {'name': '网易', 'age': '20'}
删除元素 | 描述 |
---|---|
del | 删除指定的某一个元素或整个字典 |
clear() | 清空字典,保留字典对象 |
# 删除元素
carDictionary = {'name': '宝马', 'age': 20}
print(carDictionary) # {'name': '宝马', 'age': 20}
# del carDictionary['age'] # 删除指定key的元素
# print(carDictionary) # {'name': '宝马'}
# del carDictionary # 删除整个字典
# print(carDictionary) # NameError: name 'xxx' is not defined,字典已删,所以会报未定义
carDictionary.clear() # 清空字典
print(carDictionary) # {}
遍历元素 | 描述 |
---|---|
for key in dict.keys(): print(key) |
遍历字典的key(键) |
for value in dict.values(): print(value) |
遍历字典的value(值) |
for key,value in dict.items(): print(key,value) |
遍历字典的key-value(键值对) |
for item in dict.items(): print(item) |
遍历字典的element/item(元素/项) |
# 遍历元素
airDictionary = {'name': '航空', 'age': 21}
# 遍历字典的key
# for key in airDictionary.keys():
# print(key) # name age
# 遍历字典的value
# for value in airDictionary.values():
# print(value) # 航空 21
# 遍历字典的key-value
# for key, value in airDictionary.items():
# print(key, value) # name 航空 age 21
# 遍历字典的item/element
for item in airDictionary.items():
print(item) # ('name', '航空') ('age', 21)
12.函数
12.1 定义函数
格式
# 定义函数,定义完函数后,函数是不会自动执行的,需要调用它才可以
def 函数名():
方法体
代码
# 定义函数
def f1():
print('定义完函数后,函数是不会自动执行的,需要调用它才可以')
12.2 调用函数
格式
# 调用函数
函数名()
代码
# 调用函数
f1()
12.3 函数参数
形参
:定义函数中小括号的参数,用来接收于调用函数的参数。
实参
:调用函数中小括号的参数,用来传递给定义函数的参数。
12.3.1 位置传参(顺序传参)
按照参数位置顺序一一对应的关系来传递参数
格式
# 定义带参的函数
def 函数名(arg1,arg2,...):
方法体
# 调用带参的函数
函数名(arg1,arg2,...)
代码
# 定义带参的函数
def sum_number(a, b):
c = a + b
print(c)
# 调用带参的函数
sum_number(10, 6)
12.3.2 关键字传参(非顺序传参)
按照指定的参数顺序传参
格式
# 定义带参的函数
def 函数名(arg1,arg2,...):
方法体
# 调用带参的函数
函数名(arg2=xxx,arg1=xxx,...)
代码
# 定义带参的函数
def sum_number(a, b):
c = a + b
print(c)
# 调用带参的函数
sum_number(b=6, a=10)
12.4 函数返回值
返回值
:程序中函数完成一件事情后,最后返回给调用者的结果
格式
# 定义带有返回值的函数
def 函数名():
return 返回值
# 接收带有返回值的函数
接收者 = 函数名()
# 使用结果
print(接收者)
代码
# 定义带有返回值的函数
def pay_salary(salary, bonus):
return salary + bonus * 16
# 接收带有返回值的函数
receive_salary = pay_salary(1000000, 100000)
print(receive_salary)
13.局部变量与全局变量
13.1 局部变量
局部变量
:函数内部、函数形参上定义的变量。
局部变量的作用域
:函数内部使用(函数外部不可以使用)。
# 局部变量
def partial_variable(var1, var2):
var3 = var1 + var2
var4 = 15
return var3 + var4
local_variable = partial_variable(12, 13)
print(local_variable)
13.2 全局变量
全局变量
:函数外部定义的变量。
全局变量的作用域
:函数内部、外部都可以使用
# 全局变量
globalVariable = 100
def global_variable(var1, var2):
return var1 + var2 + globalVariable
global_var = global_variable(10, 20)
print(global_var, globalVariable)
14.文件
14.1 文件的打开与关闭
打开/创建文件
:在python中,使用open()函数,可以打开一个已经存在的文件,或者创建一个新文件 open(文件路径,访问模式)
关闭文件
:close()函数
绝对路径
:绝对位置,完整描述目标所在地,所有目录层级关系一目了然。
相对路径
:相对位置,从当前文件所在文件夹(目录)开始的路径。
访问模式
:r、w、a
访问模式 | 描述 |
---|---|
r | 以只读方式打开文件。文件的指针放在文件开头。如果文件不存在,则报错。这是默认模式。 |
w | 打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 |
w+ | 打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。 |
wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。 |
wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
ab+ | 以二进制格式打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
# 创建一个文件 open(文件路径,访问模式)
testFile = open('file/test.txt', 'w', encoding='utf-8')
testFile.write('写入文件内容')
# 关闭文件【建议】
testFile.close()
14.2 文件的读写
14.2.1 写数据
写数据
:write()可以向文件写入数据。如果文件不存在,那么创建;如果存在,就先清空文件,然后写入数据
# 写数据
writeFile = open('file/write.txt', 'w', encoding='utf-8')
writeFile.write('写入文件数据\n' * 5)
writeFile.close()
14.2.2 读数据
读数据
:read(num) 可以从文件中读取数据,num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据
# 读数据
readFile = open('file/write.txt', 'r', encoding='utf-8')
# readFileCount = readFile.read() # 默认一字节一字节读,读取文件所有数据
# readFileCount1 = readFile.readline() # 一行一行的读,只能读取文件的一行数据
readFileCount2 = readFile.readlines() # 按行读取,读取文件所有数据,以一个列表的形式返回所有数据,列表的元素是一行一行的数据
print(readFileCount2)
readFile.close()
14.3 文件的序列化与反序列化
通过文件操作,我们可以将字符串写入到一个本地文件。但是,如果是一个对象(例如:列表、字典、元组等),就无法直接写入到一个文件里,需要对这个对象进行序列化,然后才能写入到文件里。
序列化
:把内存中的数据(对象)转换为字节序列,从而保存到文件或网络传输。(对象–>字节序列)
反序列化
:把字节序列恢复到内存中,重建对象。(字节序列–>对象)
序列化与反序列化的核心
:对象状态的保存与重建。
Python中提供了 JSON
模块来实现数据的序列化和反序列化。
JSON模块
JSON(JavaScriptObjectNotation, JS对象简谱)是一种轻量级的数据交换标准。JSON的本质是字符串。
使用JSON实现序列化
JSON提供了dumps和dump方法,将一个对象进行序列化。
使用JSON实现反序列化
使用loads和load方法,可以将一个JSON字符串反序列化成为一个Python对象。
14.3.1 序列化
dumps():把对象转换成为字符串,它本身不具备将数据写入到文件的功能。
import json
# 序列化① dumps()
serializationFile = open('file/serialization1.txt', 'w', encoding='utf-8')
name_list = ['admin', 'administrator', 'administrators']
names = json.dumps(name_list)
serializationFile.write(names)
serializationFile.close()
dump():在将对象转换成为字符串的同时,指定一个文件对象,把转换后的字符串写入到这个文件里。
import json
# 序列化② dump()
serializationFile = open('file/serialization2.txt', 'w', encoding='utf-8')
name_list = ['admin', 'administrator', 'administrators']
json.dump(name_list, serializationFile) # 相当于合并的dumps()和write()的两个步骤
serializationFile.close()
14.3.2 反序列化
loads():需要一个字符串参数,用来将一个字符串加载成为Python对象。
import json
# 反序列化① loads()
serializationFile = open('file/serialization1.txt', 'r', encoding='utf-8')
serializationFileContent = serializationFile.read()
deserialization = json.loads(serializationFileContent)
print(deserialization, type(serializationFileContent), type(deserialization))
serializationFile.close()
load():可以传入一个文件对象,用来将一个文件对象里的数据加载成为Python对象。
import json
# 反序列化② load()
serializationFile = open('file/serialization2.txt', 'r', encoding='utf-8')
deserialization = json.load(serializationFile) # 相当于合并的loads()和read()的两个步骤
print(deserialization, type(deserialization))
serializationFile.close()
15.异常
程序在运行过程中,由于我们的编码不规范,或者其他原因一些客观原因,导致我们的程序无法继续运行,此时,程序就会出现异常。如果我们不对异常进行处理,程序可能会由于异常直接中断掉。为了保证程序的健壮性,在程序设计里提出了异常处理这个概念。
15.1 try…except 语句
try…except语句可以对代码运行过程中可能出现的异常进行处理。
语法结构:
try:
可能会出现异常的代码块except
异常的类型:
出现异常以后的处理语句
# 示例:
try:
fileNotFound = open('file/fileNotFound.txt', 'r', encoding='utf-8')
fileNotFound.read()
except FileNotFoundError:
print('系统正在升级,请稍后再试...')
2、Urllib
1.互联网爬虫
1.1 爬虫简介
如果把互联网比作一张大的Spiders网,那一台计算机上的数据便是Spiders网上的一个猎物,而爬虫程序就是一只小Spiders,沿着Spiders网抓取自己想要的数据。
解释1:通过一个程序,根据Url(如:http://www.taobao.com)进行爬取网页,获取有用信息。
解释2:使用程序模拟浏览器,去向服务器发送请求,获取响应信息
1.2 爬虫核心
-
爬取网页
:爬取整个网页,包含网页中所有内容 -
解析数据
:将网页中你得到的数据进行解析 -
难点
:爬虫和反爬虫之间的博弈
1.3 爬虫的用途
-
数据分析/人工数据集
-
社交软件冷启动
-
舆情监控
-
竞争对手监控等
-
List item
1.4 爬虫的分类
1.4.1 通用爬虫
示例:百度、360、google、sougou等搜索引擎—伯乐在线
功能:访问网页->抓取数据->数据存储->数据处理->提供检索服务
robots协议:一个约定俗成的协议,添加robots.txt文件,来说明本网站哪些内容不可以被抓取,起不到限制作用 自己写的爬虫无需遵守。
网站排名(SEO):
- 根据pagerank算法值进行排名(参考个网站流量、点击率等指标)
- 竞价排名(谁给钱多,排名就靠前)
缺点:
- 抓取的数据大多是
无用
的 - 不能根据用户的需求来精准获取数据
1.4.2 聚焦爬虫
功能:根据需求,实现爬虫程序,抓取需要的数据
设计思路:
- 确定要爬取的url (如何获取Url)
- 模拟浏览器通过http协议访问url,获取服务器返回的html代码 (如何访问)
- 解析html字符串(根据一定规则提取需要的数据) (如何解析)
1.5 反-反爬手段
1.5.1 User-Agent
User Agent 中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
1.5.2 代理 IP
-
西次代理
-
快代理
匿名、高匿名、透明代理及它们之间的区别
-
使用透明代理,对方服务器可以知道你使用了代理,并且也知道你的真实IP。
-
使用匿名代理,对方服务器可以知道你使用了代理,但不知道你的真实IP。
-
使用高匿名代理,对方服务器不知道你使用了代理,更不知道你的真实IP。
1.5.3 验证码访问
- 打码平台
- 云打码平台
- 超级