目录
序言:
本文是我的原创博客专栏【python爬虫学习笔记】的精简整合版,尽管是精简版,仍然有6w字,所以大家可以先收藏;与专栏一致,本文的受众也是小白,并且保证小白通过本文能上手爬虫基础。🌟🌟🌟
另,因为篇幅原因,如果有空的朋友也可以去看一看专栏,如果不想麻烦的本文的内容也是足够的!
最后是我的经典开场白:高产量博主,点个关注💓不迷路!
I. python基础篇
I.I python运行方式及pycharm配置
🎯 pip指令的使用
首先简单介绍一下pip指令是什么:
pip(Python Package Index)是一个以 Python 语言写成的软件包管理系統,使用 pip 可以非常方便的安装和管理 python 软件包。
pip常用的指令有:
1️⃣ 安装指令(-i及后面的网址可以加也可以不加,加上后改用国内的源)
pip install 名称 -i https://pypi.douban.com/simple
2️⃣ 卸载指令
pip uninstall 名称
3️⃣ 查看已安装的文件
pip list
🎯 python的三种运行方式
1️⃣ 终端打代码运行:
首先运行终端:快捷键Win + R,输入 cmd,弹出终端:
输入指令:
python
运行后出现这样的提示和画面:
之后就可以正常运行python的代码,例如我们打印一个 跳探戈的小龙虾 字符串:
print('跳探戈的小龙虾')
终端退出python的指令是:
exit()
执行之后,我们就回到了正常的终端状态:
2️⃣ 终端运行py文件:
提前准备一个.py文件,之后我们输入指令:
python 文件路径
即可运行。其中文件路径如果手打不方便,可以直接把文件拖动到终端,它会自动转成路径。
3️⃣ 使用IDE运行:
首先介绍一下IDE:
集成开发环境(IDE,Integrated Development Environment )是用于提供程序开发环境的应用程序,一般包括代码编辑器、编译器、调试器和图形用户界面等工具。集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开发软件服务套。所有具备这一特性的软件或者软件套(组)都可以叫集成开发环境。
使用IDE才是最终开发采用的方法,因为我们的代码文件需要有可修改性。
一般来说pycharm是我们首选的IDE,也有其他的选择,这里我采用pycharm。
🎯 pycharm的基础配置
1️⃣ 设置字体字号:
选择 File->Settings
之后点击 Editor->Font,即可修改
2️⃣ 自动生成指定的注释:
像这样的一段注释,可以在pycharm里设置为每次新建文件默认生成:
-
# _*_ coding : utf-8 _*_
-
# @Time : 2022/1/14 15:27
-
# @Author : Lobster
-
# @File : pythonDemo2
-
# @Project : python基础
首先,仍然是点击File->Settings:
之后,点击 Editor->File and Code Templates->Python Script,里面的内容会作为默认生成的注释:
这里给一下常用的默认注释,大家修改一下AuthorName为自己的名字即可,其他的部分可直接复制。修改后新建的py文件都会生成这段注释。
-
# _*_ coding : utf-
8 _*_
-
# @
Time : ${
DATE} ${
TIME}
-
# @
Author :
AuthorName
-
# @
File : ${
NAME}
-
# @
Project : ${
PROJECT_NAME}
I.II python注释及变量类型
🎯 python注释写法
在python中,分为单行注释和多行注释两种注释模式:
1️⃣ 单行注释:
单行注释在python中的语法是这样的:
# 单行注释
2️⃣ 多行注释:
多行注释在python中的语法是这样的:
-
'''
-
多
-
行
-
注
-
释
-
'''
🎯 python变量类型
在python中,有六种变量类型:
1️⃣ 数字(Numbers)
数字类型下,又细分为两种子数据类型:
🅰️ 整型数据:
money = 100
🅱️ 浮点数:
money = 100.5
2️⃣ 布尔值(Boolean)
布尔型变量有两个取值,分别定义如下:(True和False一定要大写!)
-
a =
True
-
b =
False
3️⃣ 字符串(String)
字符串即多个字符连接成的变量,在python中一个字符也是一个字符串,可以用单引号或双引号表示:
-
a =
'Python yyds'
-
b =
"Python yyds"
4️⃣ 列表(List)
列表也是python中的一个常见的数据类型,它的定义格式如下:
-
#list
-
name_list = [
'A',
'B']
-
print(name_list)
学过其他编程语言的朋友能够发现,它的格式和定义一个数组很相似。
5️⃣ 元组(Tuple)
元组在python爬虫中有很大的意义,同时它也与上面的列表类型有所不同,现阶段最大的不同在于它们的定义格式:
-
# tuple
-
age_tuple = (
18,
19,
20,
21)
-
print(age_tuple)
6️⃣ 字典(Dict)
字典是爬虫技术中最重要的数据类型,是一个键值对的结构,它的定义如下:
-
# dict
-
# 格式:变量的名字 = {key1 : value1,key2 : value2}
-
dict_demo = {
'key1' :
'value1',
'key2' :
'value2'}
-
print(dict_demo)
上面的六种数据类型是python必须掌握的数据类型,也是服务于后面的爬虫技术的基础!🌟🌟🌟
I.III python类型查询与类型转换
🎯 python数据类型查询
python,众所周知,是一个弱类语言,也即它在定义变量的时候,不会事先声明变量的类型,变量的类型真正被确定的地方是在变量的赋值处。
在python中,函数type()可以返回变量的数据类型,例如下面的代码示例:
-
# int
-
a =
1
-
print(a)
-
print(
type(a))
-
-
# float
-
b =
1.2
-
print(b)
-
print(
type(b))
-
-
# boolean
-
c =
True
-
print(c)
-
print(
type(c))
-
-
# string
-
d =
'跳探戈的小龙虾'
-
print(d)
-
print(
type(d))
-
-
# list
-
e = [
1,
2,
3,
4,
5]
-
print(e)
-
print(
type(e))
-
-
# tuple
-
f = (
1,
2,
3,
4,
5)
-
print(f)
-
print(
type(f))
-
-
# dict
-
g = {
'name' :
'张三'}
-
print(g)
-
print(
type(g))
通过type(),在变量赋值步骤被隐藏时,能够很快地找出变量的类型,这在爬虫技术中非常常用(爬取的数据进行类型查询)。
🎯 python类型转换
类型转换在python中也非常的常见,通常情况下类型转换分为这几个情况:
1️⃣ 其他类型转整型(int)
-
a =
'123'
-
print(
type(a))
-
b =
int(a)
-
print(
type(b))
-
print(b)
-
-
# float --> int
-
c =
1.63
-
print(
type(c))
-
# float转成整数,会返回小数点前的整数,不涉及四舍五入
-
d =
int(c)
-
print(
type(d))
-
print(d)
-
-
# boolean --> int
-
# True 代表 1,False 代表 0
-
e =
True
-
print(
type(e))
-
f =
int(e)
-
print(
type(f))
-
print(f)
-
g =
False
-
h =
int(g)
-
print(h)
这部分有两个注意事项:
🅰️ 在float转int过程中,不涉及四舍五入,只是单单的把小数点后面的数据抹掉了(丢失精度)
🅱️ 布尔型变量True转int后的值是 1,False转int后的值是 0
2️⃣ 其他类型转浮点数(float)
-
a =
'12.34'
-
print(
type(a))
-
b =
float(a)
-
print(
type(b))
-
print(b)
-
-
c =
666
-
print(
type(c))
-
d =
float(c)
-
print(
type(d))
-
print(d)
这部分本身没有需要注意的地方,但是要点名的是,第一句 a = '12.34' 的变量a,是不能直接由字符串转成整型int类型的,只能直接转浮点数float(即转int的字符串本身不能包含特殊字符)
3️⃣ 其他类型转字符串(string)
-
# int -> string
-
a =
80
-
print(
type(a))
-
b =
str(a)
-
print(
type(b))
-
print(b)
-
-
# float -> string
-
c =
1.2
-
print(
type(c))
-
d =
str(c)
-
print(
type(d))
-
print(d)
-
-
# boolean -> string
-
e =
True
-
print(
type(e))
-
f =
str(e)
-
print(
type(f))
-
print(f)
要注意的是,布尔型转string的时候,不是转成0或1,而是转成字符串'False'或'True'。
4️⃣ 其他类型转布尔型(boolean)
-
# int -> boolean
-
a =
1
-
print(
type(a))
-
b =
bool(a)
-
print(
type(b))
-
print(b)
-
# 非0的整数都是true,包括负整数和正整数
-
-
c =
0
-
print(
type(c))
-
d =
bool(c)
-
print(
type(d))
-
print(d)
-
-
e = -
1
-
print(
type(e))
-
f =
bool(e)
-
print(
type(f))
-
print(f)
-
-
# float -> boolean
-
g =
1.0
-
print(
type(g))
-
h =
bool(g)
-
print(
type(h))
-
print(h)
-
-
# 0.0相当于0,所以0.0是false,除了0.0的浮点数无论正负都是false
-
-
i =
0.0
-
print(
type(i))
-
j =
bool(i)
-
print(
type(j))
-
print(j)
-
-
# string -> boolean
-
# 只要字符串有内容,都是True(内容甚至包括空格),但是没有内容的,就是False
-
k =
'跳探戈的小龙虾'
-
print(
type(k))
-
l =
bool(k)
-
print(
type(l))
-
print(l)
-
-
# 这个就是包含空格,运行结果是True
-
m =
' '
-
print(
type(m))
-
n =
bool(m)
-
print(
type(n))
-
print(n)
-
-
# list -> boolean
-
# 只要列表有数据,就是True
-
o = [
'a',
'b',
'c']
-
print(
type(o))
-
p =
bool(o)
-
print(
type(o))
-
print(p)
-
-
# 空列表是False
-
q = []
-
print(
type(q))
-
r =
bool(q)
-
print(
type(r))
-
print(r)
-
-
# tuple -> boolean
-
# 只要元组有数据,就是True
-
s = (
'a',
'b')
-
print(
type(s))
-
t =
bool(s)
-
print(
type(t))
-
print(t)
-
-
# 空元组是False
-
u = ()
-
print(
type(u))
-
v =
bool(u)
-
print(
type(v))
-
print(v)
-
-
# dict -> boolean
-
# 只要字典有数据,就是True
-
w = {
'a' :
'1',
'b' :
'2'}
-
print(
type(w))
-
x =
bool(w)
-
print(
type(x))
-
print(x)
-
-
# 空字典是False
-
y = {
'a' :
'1',
'b' :
'2'}
-
print(
type(y))
-
z =
bool(y)
-
print(
type(z))
-
print(z)
这部分的所有规定全部注释在代码中,可认真观察代码学习!🌟🌟🌟
I.IV python运算符
🎯 算术运算符
算术运算符是python中最基础的一类运算符,表示的是运算的关系,示例代码如下:
-
# 算术运算符
-
a =
3
-
b =
2
-
-
# 加法
-
print(a + b)
-
-
# 减法
-
print(a - b)
-
-
# 乘法
-
print(a * b)
-
-
# 除法 默认是保留小数
-
print(a / b)
-
-
# 取整
-
print(a // b)
-
-
# 取余
-
print(a % b)
-
-
# 幂运算
-
print(a ** b)
-
-
# 字符串加法:字符串拼接
-
c =
'123'
-
d =
'456'
-
print(c + d)
-
-
# 在Python中,字符串做加法时,加号两端必须两端都是字符串,若只有一端是字符串,则会报错:
-
e =
'123'
-
f =
456
-
#print(e + f) # 此行会报错
-
print(e +
str(f))
# 这是出现这种情况的处理策略:先转成str再来
-
-
# 在python中,还支持字符串乘法:
-
g =
'hello world '
-
print(g *
3)
其中,想要强调两个细节:
1️⃣ 首先是两个字符串相加,相当于做了字符串拼接,不过这一点在其他编程语言中也是如此。
2️⃣ 其次是与其他编程语言不同,python不支持string类型与int类型直接做加法,这样做会报错!
🎯 赋值运算符
赋值运算符是我们常说的把一个值赋给变量,示例代码如下:
-
# 赋值运算符
-
a =
10
-
print(a)
-
-
# 多个变量赋同一个值
-
b = c =
20
-
print(b)
-
print(c)
-
-
# 多个变量同时赋值
-
d,e,f =
1,
2,
3
-
print(d)
-
print(e)
-
print(f)
-
-
# 复合赋值运算符
-
a =
1
-
-
a = a +
4
-
print(a)
-
-
a +=
2
-
print(a)
-
-
a -=
2
-
print(a)
-
-
a *=
2
-
print(a)
-
-
a /=
2
-
print(a)
-
-
a //=
2
-
print(a)
-
-
a %=
2
-
print(a)
-
-
a **=
2
-
print(a)
这部分有意思的地方在于python支持多个变量同时赋不同的值,但是变量间和值之间都要用逗号隔开!
🎯 比较运算符
比较运算符是表示两个变量之间关系的运算符,返回值是布尔值(boolean),示例代码如下:
-
# 比较运算符
-
a =
10
-
b =
10
-
-
print(a == b)
-
-
print(a != b)
-
-
print(a > b)
-
-
print(a < b)
-
-
print(a >= b)
-
-
print(a <= b)
🎯 逻辑运算符
逻辑运算符在python中一共有三个,即 与、或、非(取反),示例代码如下:
-
# 逻辑运算符 and or not
-
-
# and 与 , 没错python中的and是手打一个and,不是||
-
-
print(
10 >
20
and
10 >
11)
-
-
# or 或者
-
-
print(
10 >
20
or
10 >
21)
-
-
# not 非 取反
-
-
print(
not
True)
-
-
print(
not
False)
-
-
a =
36
关于逻辑运算符,python有别于其他编程语言的地方在于它是用英文单词表示逻辑关系,其他编程语言可能用 & | ! 这样的符号表示。另外关于逻辑运算符的短路示例代码如下:
-
# and 的性能优化:
-
# 左侧是False,因而右侧不再执行(短路and)
-
a <
10
and
print(
'hello world')
-
-
# or的性能优化:
-
# 左侧是True,因而右侧不再执行(短路or)
-
a =
38
-
a >
37
or
print(
'你好世界')
短路的设定,优化了逻辑运算符的执行效率!🌟🌟🌟
I.V python读入与格式化输出
🎯 输出与格式化输出
python中,普通的输出在前面的笔记中已经是经常使用了,因而不再介绍,示例代码如下:
-
# 普通输出
-
print(
'跳探戈的小龙虾')
在python中,支持类似于C、C++的格式化输出,它的具体格式如下示例代码:
-
# 格式化输出:后续爬虫scrapy框架中会使用,将爬取的内容存入 Excel、MySQL、Redis
-
age =
20
-
name =
'Lobster'
-
-
# 格式化输出时,%s 代表字符串,%d 代表数字,其他的数据类型的格式化输出爬虫中一般不使用,
-
# 不做介绍。格式化输出的格式如下:
-
# 在需要放置输出变量的位置根据类型放置对应的符号,之后在print函数引号后面用一个百分号把
-
# 变量名放入即可,一个变量名时无需加括号,多个变量名用一个括号按顺序括起来,逗号隔开
-
print(
'昵称:%s,年龄:%d' % (name,age))
🎯 读入
读入在python中通过调用input()函数实现,它的具体格式示例如下:
-
# python输入
-
nickname =
input(
'请输入你的昵称')
input()函数内的字符串会作为读入的提示语句显示在控制台。
🎯 读入和输出组合小demo
最后是实现一个简单的读入和格式化输出组合的小demo,功能是读入昵称后,回显昵称:
-
# python输入
-
nickname =
input(
'请输入你的昵称')
-
# 输入内容结合格式化输出
-
print(
'昵称:%s' % nickname)
这部分是关于python的格式化输出和读入的内容!🌟🌟🌟
I.VI python流程控制语句
🎯 if-elif-else流程控制
python爬虫中最常用的第一种流程控制语句是if-elif-else控制语句。学过其他编程语言的朋友会觉得elif很陌生,其实elif就是其他编程语句中else if 的缩写而已。具体的示例代码如下:
-
# python流程控制
-
# if、else、elif的语法结构:if 条件:
-
# 四个空格缩进 具体执行内容(if的第二行一定要有缩进,否则会报错,四个空格是一个习惯性写法,不是四个也可运行但不规范)
-
# else:
-
# 四个空格缩进 具体执行内容(同缩进)
-
score =
80
-
-
if score >=
90:
-
print(
'优秀')
-
elif score >=
80:
-
print(
'良好')
-
elif score >=
70:
-
print(
'一般')
-
elif score >=
60:
-
print(
'及格')
-
else:
-
print(
'不及格')
注意一下,python的if-elif-else结构中不含其他编程语言的大括号,因而要注意缩进要有并且要正确地缩进,否则逻辑会发生错误!
最后补一个if-elif-else与读入、输出结合的小demo,实现功能为读入成绩,返回打印成绩的等级:
-
# if、else流程控制小demo:读入分数,判断成绩等级,并输出结果
-
-
# 这里注意,input读入函数默认读入的类型是字符串,
-
# 而python本身不支持字符串与整型比较,因此跟整型比较时,要做一步转换,否则会报错:
-
score =
int(
input(
'输入成绩:'))
-
if score >=
90:
-
print(
'优秀')
-
elif score >=
80:
-
print(
'良好')
-
elif score >=
70:
-
print(
'一般')
-
elif score >=
60:
-
print(
'及格')
-
else:
-
print(
'不及格')
这里注意一个小细节:print()函数读入的内容默认是字符串(string)类型的,我们要先做一步强制类型转换为整型(int),而后与int型数值进行比较,否则会报错。(python不支持int和string直接比较!)
🎯 for循环流程控制
第二类爬虫中常用的是for循环流程控制语句。它的基本格式如下:
-
# python流程控制
-
# for循环格式:
-
# for 变量 in 要遍历的数据:
-
# 方法体
-
s =
'china'
-
# 在字符串类型遍历时,i代表了字符串中的单个字符,s代表要遍历的数据
-
for i
in s:
-
print(i)
for循环通常结合range()函数一起使用,它的格式如下:
-
# range(n),它是一个左闭右开区间
-
# range方法的结果:一个可以遍历的对象,
-
-
# 如果里面是一个数字,会从0到这个数字-1
-
for i
in
range(
5):
-
print(i)
# 输出:0 1 2 3 4
-
-
# 如果里面有两个数字,那么有:
-
# 其中第一个代表起始数字,第二个代表末尾数字,返回这其中的数字
-
for i
in
range(
1,
5):
-
print(i)
# 输出:1 2 3 4
-
-
# 如果里面有三个数字,前两个是起始数字和末尾数字,
-
# 最后一个数字代表间隔值或步长
-
for i
in
range(
1,
10,
3):
-
print(i)
# 输出:1 4 7 注意没有10,因为是左闭右开区间
以上三种是range()函数的三种传参的方式,我们通常结合range()函数对字典、元组、列表进行循环打印。另外要注意range()函数是左开右闭的一个范围!
最后附一个for循环结合列表的小demo,循环打印列表:
-
# for循环小demo,循环打印一个列表
-
a_list = [
'J',
'L',
'T'];
-
for i
in a_list:
-
print(i)
# 这里的i代表了列表的每一项
I.VII python字符串高级应用
python中,字符串有很多内置的函数,详细见下面的示例:
-
# 字符串高级:字符串常见的函数
-
-
# 1.获取长度:len(),返回整型
-
s =
'Lobster'
-
print(
len(s))
-
-
# 2.获取某个字符在字符串中第一次出现的位置索引值(区分大小写): s.find(''),返回整型
-
print(s.find(
'L'))
-
-
# 3.判断是否以某个字符开头、结尾:s.startswith(''),s.endswith(''),返回布尔值
-
print(s.startswith(
'O'))
-
print(s.endswith(
'r'))
-
-
# 4.查找某个字符的个数:s.count('')
-
print(s.count(
'o'))
-
-
# 5.替换某个字符:s.replace('','')
-
print(s.replace(
'L',
'l'))
-
-
# 6.切割字符串:s.split(''),意思是以传入的字符为切割位把原字符串切开,
-
# 传入这个字符会变成空格
-
print(s.split(
'o'))
-
-
# 7.大小写转换:s.upper(),s.lower(),整个字符串转成大写或小写
-
print(s.upper())
-
print(s.lower())
-
-
# 8. 去掉字符串空格的函数:strip(),能把整个字符串所有空格去掉
-
s1 =
' Lobster '
-
print(
len(s1))
-
print(
len(s1.strip()))
# 刚好是Lobster的长度7
-
-
# 9. join()函数,了解即可,是把一个字符串插入
-
# 到另一个字符串的每一位的后面,而不是简单的拼接,不是很常用:
-
s2 =
'aaaaaa'
-
s3 =
'bb'
-
print(s3.join(s2))
# 输出:abbabbabbabbabba
这上面最后一种函数,意义不是很大,不需要太关心,感兴趣的可以跑一跑代码感受一下,其他的八种函数,需要掌握!🌟🌟🌟
I.VIII python列表、元组、字典高级
🎯 列表的高级使用
对于列表来说,它的高级使用将从 增删改查 四个角度进行介绍,下面的示例代码:
-
# 列表高级:添加
-
-
# 1. append 追加,在列表的最后一位添加一个对象/数据
-
food_list = [
'apple',
'banana']
-
print(food_list)
-
food_list.append(
'cock')
-
print(food_list)
-
-
# 2. insert 插入,两个参数,第一个参数代表想要插入的下标位置,
-
# 第二个参数代表你要插入的对象/数据
-
char_list = [
'a',
'c',
'd']
-
print(char_list)
-
char_list.insert(
1,
'b')
-
print(char_list)
# a b c d
-
-
# 3. extend 继承,传入的是一个列表,把传入的列表整个插入到
-
# 调用extend()函数的列表的末尾:
-
num_list = [
1,
2,
3]
-
num_list2 = [
4,
5,
6]
-
num_list.extend(num_list2)
-
print(num_list)
-
-
# 列表高级:修改
-
-
# 将列表中的元素的值修改
-
# 实现的方法类似于其他编程语言中给数组某一位赋一个新的值覆盖旧值:
-
city_list = [
'Beijing',
'Shanghai',
'Shenzhen',
'Henan']
-
print(city_list)
-
# 假设想要修改第三位,Shenzhen,其索引值是2:
-
city_list[
2] =
'Changchun'
-
print(city_list)
-
-
# 列表高级:查询
-
-
# 判断已知数据是否在列表内:
-
# 用关键字:in或者not in即可,in/not in的前面是待查询的元素,in/not in后面是一个列表
-
# 1. in代表待查询的元素在列表中:
-
# 存在时返回true,不存在返回false
-
food_list = [
'apple',
'banana',
'cock']
-
-
food =
'apple'
-
-
if food
in food_list:
-
print(
'存在')
-
else:
-
print(
'不存在')
-
-
# 2. not in也是查询的关键字,代表待查询的元素不在列表中:
-
# 不存在时返回true,存在时返回false
-
ball_list = [
'Basketball',
'Football']
-
-
ball =
'pingpang'
-
-
if ball
not
in ball_list:
-
print(
'不存在')
-
else:
-
print(
'存在')
-
-
# 列表高级:删除
-
-
# 1. 根据下标删除列表中的元素
-
a_list = [
1,
2,
3,
4,
5]
-
print(a_list)
-
# 例如要删除下标为2的元素3,使用关键字del 加列表 加对应索引:
-
del a_list[
2]
-
-
# 2. 删除列表的最后一位元素,使用关键字
-
b_list = [
1,
2,
3,
4,
5]
-
print(b_list)
-
# 使用pop()函数能够删除最后一位元素:
-
b_list.pop()
-
print(b_list)
-
-
# 3. 根据元素的值,删除元素
-
c_list = [
1,
2,
3,
4,
5]
-
print(c_list)
-
# 例如想要删除元素值为3的元素,使用remove()函数即可,传入值:
-
c_list.remove(
3)
-
print(c_list)
# 打印结果:1 2 4 5,如果是索引,那应是 1 2 3 5
要注意的是,对于增和删,有几种不同的模式,每种模式适用于不同的场景!
🎯 元组的高级使用
元组的高级使用,介绍的思路是从元组与列表的联系与区别入手,它们有如下联系与区别:
-
# 元组高级:与列表区别与联系:
-
-
# 首先,元组是圆括号(),列表是[]
-
a_tuple = (
1,
2,
3,
4)
-
a_list = [
1,
2,
3,
4]
-
-
# 其次,元组和列表访问某个元组的格式是一样的,
-
# 都是 变量名[index]
-
print(a_tuple[
0])
-
print(a_list[
0])
-
-
# 最后,元组的元素不可修改,列表的元素显然可以修改
-
# a_tuple[0] = 2 #这句话会报错,因为元组不可修改
-
a_list[
0] =
2
# 但是列表支持修改
-
-
# 补充:当元组中只有一个元素的时候,它是一个整型数据
-
b_tuple = (
5)
-
print(
type(b_tuple))
# int
-
# 如果这时候只有一个元组,还想让它是元组类型,需要在数据后面加一个逗号:
-
c_tuple = (
5,)
-
print(
type(c_tuple))
# tuple
由上述可以看出,元组更像其他编程语言中的 constant 变量,也即声明之后就不能再修改的变量类型。
🎯 切片
切片是一种经常运用于字符串、列表和元组中的技术方法,它的意思是将字符串、列表和元组中的元素切割成不同的片段,并把这些片段返回。下面的示例代码以字符串的切片为例,列表和元组的使用方法大同小异:
-
# 切片:适用于字符串、列表和元组,这里以字符串为例
-
# 列表和元组使用方法完全相同:
-
-
s =
'hello world'
-
# 1.在[]中直接写下标,此时可以看做切片,也可以看做对单个元素的访问:
-
print(s[
4])
-
-
# 2.在[]中写起始位索引 : 终止位索引,
-
# 此时切片是从起始位到终止位的字符串,且 【左闭右开】
-
print(s[
0 :
4])
-
-
# 3. 在[]中写 n :
-
# 此时表示从第n位索引对应元素开始,一直到最后一位
-
print(s[
1 :])
-
-
# 4. 在[]中写 : n
-
# 此时表示从第0位索引对应元素开始,到第n位索引,且【左闭右开】
-
print(s[:
3])
-
-
# 5. 在[]中写 n : m : o
-
# 从下标为 n 的位置开始,到下标为 m 的位置结束,且【左闭右开】
-
# 步长是 o (每次增加的位置数),且【左闭右开】
-
print(s[
0:
5:
2])
# hlo,代表索引 0 2 4
🎯 字典的高级使用
字典的高级使用,和列表类似,思路是从字典的增删改查入手,并且增加了一项,那就是对字典的不同遍历方法,下面是五种操作的详细示例代码(增删改查+遍历):
-
# 字典高级
-
-
# 定义一个字典:
-
person = {
'name' :
'跳探戈的小龙虾',
'age' :
20}
-
-
# 字典高级:查询
-
-
# (1). 字典变量名['key'] 查询元素
-
print(person[
'name'])
-
print(person[
'age'])
-
# 当访问不存在的'key'值时,出现的情况是会报错:
-
# print(person['sex'] 会报错 key error
-
-
# (2). get()函数 查询元素
-
print(person.get(
'name'))
-
print(person.get(
'age'))
-
-
# 字典高级:修改
-
-
# 例如修改上例中 'name' 键的值为 '张三'
-
person[
'name'] =
'张三'
-
print(person[
'name'])
-
-
# 字典高级:添加
-
-
# 例如添加一个新的 键值对:'sex' 'nan'
-
person[
'sex'] =
'nan'
-
# 添加的格式与修改相同,只是此时 键 key 是不存在的,
-
# 因此会新建该键值对,如果该键存在,那就是修改操作
-
-
# 字典高级:删除
-
-
# (1) del 关键字删除:删除字典中指定的某一个元素
-
del person[
'sex']
-
print(person)
-
-
# (2) del 关键字删除:删除整个字典,包括字典对象本身
-
del person
-
# print(person) # 这时打印会报错,因为person字典已经不存在了
-
-
# (3) clear 清空字典内容,但是保留字典对象
-
person = {
'name' :
'跳探戈的小龙虾',
'age' :
20}
-
person.clear()
-
print(person)
# 此时打印的结果只有一个 {},因为内容已被清空!但不会报错
-
-
# 字典高级:遍历
-
-
# (1) 遍历字典的key
-
# 字典.keys() 方法,获取字典所有的key值,而后用
-
# for循环即可,用一个临时变量进行遍历
-
person = {
'name' :
'跳探戈的小龙虾',
'age' :
20}
-
for key
in person.keys():
-
print(key)
-
-
# (2) 遍历字典的value
-
# 字典.values() 方法,获取字典所有的value值,而后用
-
# for循环即可,用一个临时变量进行遍历
-
for value
in person.values():
-
print(value)
-
-
# (3) 遍历字典的key和value
-
# 字典.items() 方法,获取所有的key value键值对,
-
# 并且用两个临时变量通过for循环遍历
-
for key,value
in person.items():
-
print(key,value)
-
-
# (4) 遍历字典的项/元素
-
# 仍然是字典.items() 方法,但是此时只用一个临时变量去循环遍历
-
# 即可获取字典的每一项,这与上一种的区别在于获取的
-
# 键值对会用一个()包围,即打印的结果是(key,value)
-
for item
in person.items():
-
print(item)
最后关于遍历的最后一种方式,也即遍历字典的项,这里稍作说明:
遍历字典的项,它和前一种遍历key和value很相似,区别在于遍历项的结果被包含进了括号里面,也即遍历的结果是:(key,value) 的形式,这更符合‘项’的定义。🌟🌟🌟
I.IX python函数的使用介绍
🎯 函数的定义
在python中,为了减少代码块的重复性,与其它编程语言一样,也有函数的相关概念与实现方式,首先介绍python中函数的定义,它的格式是这样的:
-
# python 函数
-
-
# 定义函数
-
# 格式为:def 函数名():
-
# 四个空格 函数体
-
def
f_1():
-
print(
'Hello,Function')
-
# 函数体前面的空格个数也可以不是4个,但是为了标准起见,尽量保持四个空格!
-
-
# 调用函数
-
# 格式为:函数名() 即可
-
f_1()
函数定义的时候,要注意缩进的规范性,尽量按照统一标准,有四个空格或者一个tab键的缩进(用pycharm打完def关键字后,会车会自动生成四个空格的缩进,不需要手动敲四个空格)。调用时,与其他编程语言类似,也是直接放一个函数名()即可。
🎯 函数的传参
在python中,函数同样支持传参,只不过与其他编程语言不同的是传参是不包含类型的,这也是python的特色。函数传参的格式如下:
-
# 函数的参数
-
-
# 定义格式为:
-
# def 函数名(参数1,参数2,参数3...)
-
def
sum(
a,b):
-
c = a + b
-
print(c)
-
-
# 调用时,有两种传参方法:
-
-
# 1. 位置传参,即直接传递参数,按照函数定义参数的顺序传参
-
sum(
1,
9)
-
-
# 2. 关键字传参,即按照函数定义的参数名称进行传参
-
sum(b =
1, a =
9)
第二种关键字传参的方式,实际开发中运用很少,了解即可。另外关于传参,对小白稍微解释一下:定义函数时,书写的参数叫做形参;调用函数时,书写的参数叫实参或传参。
🎯 函数的返回值
返回值这块,python的格式与其他编程语言也类似,区别仍然在于python没有类型,因而即使有返回值,在定义函数时也无需提前声明。它的具体格式如下:
-
# 函数的返回值
-
-
# 返回值的格式为:
-
# def 函数名():
-
# return 返回值
-
def
sum(
a,b):
-
c = a + b
-
return c
🎯 局部变量与全局变量
在函数部分的最后,简单聊一下局部变量与全局变量,这部分仅面向小白,有其他语言基础的可以跳过。对于函数来说,在函数体内定义的变量称为局部变量,它的作用域仅限于函数体内,在函数体外该变量等价于不存在;在函数体外定义的变量称为全局变量,它的作用域是全局,也即既可以在函数体内使用,也可以在函数体外使用。下面是一个简单的demo演示:
-
# 局部变量和全局变量
-
-
# 局部变量:在函数的内部定义的变量,我们称为局部变量
-
# 特点:作用域范围是函数内部,在外部不可用
-
def
f1():
-
a =
1
-
print(a)
-
# 在外部,就不能再次print(a),因为a只在函数f1()可用
-
-
# 全局变量:定义在函数外部的变量,我们称之为全局变量
-
# 特点:可以在函数的外部或内部使用
-
a =
1
-
print(a)
-
def
f2():
-
print(a)
-
f2()
以上是关于python函数的基础知识介绍。🌟🌟🌟
I.X python文件基础操作
🎯 文件的创建和写入
python中,一个文件可以被创建和写入,它的示例代码如下:
-
# python文件操作
-
#
-
# 创建/打开一个文件:test.txt
-
# 格式为:open(文件的路径;文件的模式)
-
# 模式有:w 可写 r 可读 a 追加
-
fp =
open(
'demo/test.txt',
'w')
-
-
# 文件的关闭
-
# 执行打开、读写操作后要及时关闭文件,释放内存!
-
fp.close()
-
-
# 文件的读写
-
-
# 向文件内写入内容:
-
# 格式为 文件对象.write('内容')
-
fp_w =
open(
'demo/test1.txt',
'w')
-
fp_w.write(
'hello,world\n' *
5)
-
fp_w.close()
-
-
# 在w 写入模式下,每一次打开后,写入的位置都是开头,也即会覆盖之前的内容
-
# 在a 追加模式下,每一次会紧接着上一次写入的内容,不会覆盖:
-
fp_a =
open(
'demo/test2.txt',
'a')
-
fp_a.write(
'hello\n' *
5)
-
fp_a.close()
需要注意的是,当文件在路径下不存在的时候,运行'w'写入模式时会自动创建文件并定为写入模式;'a'追加模式下,我们才可以每一次接着前一次的结尾写入,否则'w'模式下每一次都会覆盖前一次写入的内容!
🎯 文件的读出
文件的读操作有很多不同的类型,它的示例代码如下:
-
# 读取文件的内容
-
# read函数是按每字节读取,效率较低
-
fp_r =
open(
'demo/test2.txt',
'r')
-
content = fp_r.read()
-
print(content)
-
fp_r.close()
-
-
# readline函数是一行一行的读取,但是调用一次只能读取一行:
-
fp_l =
open(
'demo/test2.txt',
'r')
-
line = fp_l.readline()
-
print(line)
-
fp_l.close()
-
-
# readlines函数也是按照行来读取,并且可以一次性把所有行都读取到,
-
# 并返回一个列表的形式:
-
fp_ls =
open(
'demo/test2.txt',
'r')
-
lines = fp_ls.readlines()
-
print(lines)
-
fp_ls.close()
需要注意的是,当文件不存在时,运行'r'读出模式是不会新建文件的,反而会抛出异常,因此要注意先新建好文件再读出。
🎯 文件的序列化与反序列化
最后介绍一下序列化和反序列化,先介绍一下序列化和反序列化的定义:
序列化:将列表、元组、字典等对象转成有序的字符串类型数据。
反序列化:将字符串类型数据转回列表、元组、字典等对象
下面是具体操作的示例代码:
-
# 文件的序列化和反序列化
-
-
# 默认情况下,只能直接将字符串写入文件,列表、元组、字典等对象无法写入文件:
-
fp =
open(
'demo/test3.txt',
'w')
-
fp.write(
'hello world')
-
fp.close()
-
name_list = [
'张三',
'李四']
-
fp_1 =
open(
'demo/test4.txt',
'w')
-
# fp_1.write(name_list) 这句话就会报错,因为无法直接向文件写入列表对象,
-
# 只能先进行序列化,而后写入
-
fp_1.close()
-
-
# 序列化:对象 - - - > 字节序列(json字符串)
-
-
# 序列化有两种方式:
-
# (1) dumps() 函数 法
-
# 首先创建一个文件,并定义一个列表:
-
fp_2 =
open(
'demo/test5.txt',
'w')
-
name_list = [
'zhangsan',
'lisi']
-
# 导入json模块到python文件:
-
import json
-
# 进行序列化:使用json库的dumps()函数进行对象序列化:
-
names = json.dumps(name_list)
-
fp_2.write(names)
-
fp_2.close()
-
-
# (2) dump() 函数 法
-
# 它与dumps()的区别在于
-
# dump()函数在完成序列化的同时,会指定目标文件,并完成写入操作
-
# 类似于一步完成dumps()的两个操作:
-
fp_3 =
open(
'demo/test6.txt',
'w')
-
# 这里可以看出,传入的参数多了一个文件对象,也即这就是指定的目标文件,序列化的内容会直接写进去:
-
json.dump(name_list,fp_3)
-
fp_3.close()
-
-
fp_4 =
open(
'demo/test6.txt',
'r')
-
# 此时执行读取,它的结果是一个字符串类型:
-
content = fp_4.read()
-
print(
type(content))
-
print(content)
-
fp_4.close()
-
# 但是我们的目的是要读出一个列表/元组/字典对象,因此需要做反序列化:
-
-
# 反序列化:字节序列 (json字符串)- - - > 对象
-
-
# 反序列化也有两种方法:
-
# (1) loads() 函数 法
-
fp_5 =
open(
'demo/test6.txt',
'r')
-
content = fp_5.read()
-
# 调用json库中的loads()函数,传入被序列化的字符串变量,返回反序列化的json字符串:
-
import json
-
content = json.loads(content)
-
print(
type(content))
-
print(content)
-
fp_5.close()
-
-
# (2) load()函数 法:
-
# 此法与dumps和dump的区别一样,也是实现了两步合成一步
-
# 即读取字符串与字符串转json对象(列表、元组、字典)合并在一步:
-
fp_6 =
open(
'demo/test6.txt',
'r')
-
# 调用json库中的load()函数,同时完成读取+转换json对象:
-
result = json.load(fp_6)
-
print(result)
-
print(
type(result))
-
fp_6.close()
之所以要做序列化和反序列化,在代码中有解释,这里再重复一下,原因在于文件的写入操作不支持字典、元组、列表等对象的写入操作,因而需要先序列化后写入文件,而后读出时执行反序列化操作。🌟🌟🌟
I.XI python异常处理介绍
python中,有时候运行一段代码会报错,这时我们使用的IDE会给我们返回错误的类型在控制台,例如这样的情况,在没有创建对应文件的情况下执行读操作:
fp = open('text.txt','r')
此时控制台打印出这样的错误:
这固然是错误的类型,但是这样的提示是很不友好的,尤其面向客户开发的过程中,这样的错误提示会让人摸不着头脑。因此我们可以使用python中的try catch语句来自定义抛出异常提示:
-
# 异常处理:由于代码错误后,默认弹出的错误不利于用户理解,
-
# 因而在写代码时,对于可能出错的部分,做异常处理,使得弹
-
# 出的错误能被用户理解为上上策。
-
# 异常处理格式:
-
# try:
-
# 可能出现异常的代码
-
# except 异常的类型
-
# 便于用户理解的提示
-
try:
-
fp =
open(
'text.txt',
'r')
-
except FileNotFoundError:
-
print(
'文件可能暂时丢失')
此时再次运行,我们能够看到错误的提示是这样的:
这样就更方便我们去查看了!🌟🌟🌟
到这里,python的基础内容介绍完毕,如果是小白看到这里,请认真再复习一下上面的部分,然后可开始下面的部分,python基础扎实的朋友请直接进入下一部分:【python爬虫】!
II. python爬虫篇
II.I urllib库的使用介绍
🎯 初识urlliib库:爬取某网站的源代码
urllib库是爬虫常用的一个库,通过这个库的学习,能够了解一些爬虫的基础技术。
下面以爬取某网站首页源码的示例代码介绍urilib库中常用的request()方法:
-
# 导入urllib库
-
import urllib.request
-
-
# urllib爬取某网站首页的步骤:
-
-
# (1) 定义一个url 即目标地址
-
url =
'http://www.xxx.com'
-
-
# (2) 模拟浏览器向服务器发送请求
-
response = urllib.request.urlopen(url)
-
-
# (3) 获取响应中的页面的源码
-
# 这里read()函数可以获取响应,但是响应的格式是二进制的,需要解码
-
# 解码:decode('编码格式') 编码格式在 <head><meta chaset ></head>中显示
-
content = response.read().decode(
'utf-8')
-
-
# (4) 打印数据
-
print(content)
注意上面的解码步骤,如果不解码,获得的内容将会是二进制的格式,不利于我们的正常使用。
🎯 HttpResponse响应的六种常见的读取方法
这部分的开头,首先说明通过urllib.request()获取的对象是类型是HttpReponse型的,针对这种类型,有六种常见的读取方法,它们的示例如下:
-
# HTTPResponse这个类型
-
# 六个方法:read、readline、readlines、getcode、geturl、getheaders
-
# response = urllib.request.urlopen(url)
-
# print(type(response)) # response是HTTPResponse的类型
-
-
# (1) 按照一个字节一个字节去读
-
content = response.read()
-
print(content)
-
-
# 读取具体的n个字节,在read()函数中传参即可
-
content2 = response.read(
5)
-
print(content2)
-
-
# (2) 按行读取,但是只能读取一行
-
content3 = response.readline()
-
print(content3)
-
-
# (3) 按行读取,并且读取所有行
-
content4 = response.readlines()
-
print(content4)
-
-
# (4) 返回状态码的方法:200状态码没有问题,其他的状态码可能有问题
-
print(response.getcode())
-
-
# (5) 返回访问的目标的url地址
-
print(response.geturl())
-
-
# (6) 获取的是响应头
-
print(response.getheaders())
上述的response是在第一部分获取的响应变量,大家注意!
🎯 urllib库之下载图片、音频、视频
下面介绍一下用urllib.request()方法如何下载文件:
-
# urllib下载文件的操作
-
-
# (1) 下载网页
-
url_page =
'http://www.baidu.com'
-
# 使用urillib.request.urlretrieve() 函数,
-
# 传参分别是url(网页的地址路径)、filename(网页文件的名字)
-
urllib.request.urlretrieve(url_page,
'baidu.html')
-
-
# (2) 下载图片
-
url_img =
'https://xxx'
-
urllib.request.urlretrieve(url_img,
'xxx.jpg')
-
-
# (3) 下载视频
-
url_video =
'https://xxx'
-
urllib.request.urlretrieve(url_video,
'xxx.mov')
图片和视频的路径,可以通过在网页中右键、按F12查看网页元素找到。其中视频通常可以通过按F12,之后按ctrl+f查找'<video>'标签的src属性后面拿到。另外所有的第二个传参都代表文件的名字,这个名字是自己起的,因此不用太拘谨,但是要注意后缀.xxx要正确,否则后缀错误导致文件将不可访问!🌟🌟🌟
🎯 urllib库之定制请求头
承接前文,此时我们开始在请求中定制我们的请求,也即要开始伪装,下面介绍最基本是一种伪装的方式,也即添加请求头:
-
# 请求对象的定制:为了解决反爬虫的第一种手段
-
url =
'https://www.baidu.com'
-
# 用户代理:UA
-
headers = {
-
'user-agent' :
'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36'
-
}
-
# urlopen()方法中不能传参字典,因而用户代理UA不能作为传参传入
-
# 此时需要定制一个请求对象:
-
# 这里要注意,因为resquest.Resquest()函数有三个传参,这里我们传入两个参数,所以要写成关键字传参
-
# 如果request = urllib.request.Request(url,headers) 写会报错
-
request = urllib.request.Request(url = url,headers = headers)
-
response = urllib.request.urlopen(request)
-
content = response.read().decode()
-
print(content)
这里再次强调,由于urllib.request.Request()函数有三个传参,但是我们此时只用到了两个,因此我们一定要用关键字传参法去传参,不知道什么是关键字传参的请翻阅本篇博客上面部分python函数介绍。
🎯 urllib库之GET请求的爬虫操作
下面是urllib库关于GET请求的用例代码:
-
# get请求的quote()方法:单个参数的情况下常用该方法进行编解码
-
-
# 需求:用get请求的quote()方法获取源码
-
-
# (1) 传统方法:
-
# 找到网页地址url:此时复制的汉字会自动转成unicode编码,如下,即这段编码就是周杰伦三个汉字的编码
-
url =
'https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6'
-
# 寻找UA
-
headers = {
-
'User-Agent' :
'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36'
-
}
-
# 定制请求对象
-
request = urllib.request.Request(url = url,headers = headers)
-
# 模拟浏览器向服务器发起请求
-
response = urllib.request.urlopen(request)
-
# 获取响应内容
-
content = response.read().decode(
'utf-8')
-
# 打印内容
-
print(content)
-
-
# (2) get请求的quote()方法:
-
# 定义固定的url部分
-
url =
'https://www.xxx.com/s?wd='
-
# 名字的汉字传入quote()方法做一步unicode进行编解码操作
-
name = urllib.parse.quote(
'xxx')
-
url = url + name
-
headers = {
-
'User-Agent' :
'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36'
-
}
-
request = urllib.request.Request(url =