GitOPEN's Home.

《手把手带你学爬虫──初级篇》第1课 基础知识

Word count: 9,205 / Reading time: 40 min
2018/09/14 Share

本教程所有源码下载链接:https://share.weiyun.com/5xmFeUO 密码:fzwh6g

基础知识

环境搭建

Python安装

平时能接触到的操作系统非Windows、macOS、Linux莫属。其中Windows是我们日常中最常用的OS,它软件更多、办公和游戏可以兼得;macOS由于搭载其的电脑外表漂亮、屏幕优秀、性能均衡,而被很多设计者和程序员所喜爱;Linux在服务器领域是无可匹敌,几乎所有大型应用服务器都部署于Linux系统,常用的Linux服务器系统有CentOS、Ubuntu Server等,但是Linux桌面版也在程序员中应用较广,便捷的终端、稳定的性能是编程的首选。

由于macOS和Ubuntu系统都自带python环境,因此,我们只讲解Windows下Python的安装和配置。感兴趣的同学,可以自己在虚拟机中测试和熟悉Linux系统,推荐Ubuntu18.04。

Windows下安装Python

熟悉一下Python的主页

下载。官方的最新版已经更新到了3.7.0,但是我们下载的版本是Python3.6.5,因此,我们点击View the full list of downloads

只需要记住,不同架构的Windows系统,选择不同的安装包下载。

安装。按图示操作即可。

  • 双击安装包,选择自定义安装,方便以后使用。

  • 直接下一步。

  • 修改路径,将路径改为c:\Python36

  • 安装成功

环境变量检测与设置。

  • 打开cmd命令行。

  • 输入python,提示python版本等信息表示环境变量设置成功。

  • 如果输入python后,提示不是内部命令或外部命令,则表示环境变量没有配置好。

设置环境变量。

  • 桌面右击计算机🖥️,选择属性,然后,再次选择高级系统设置

  • 高级一栏中点击环境变量,打开环境变量设置窗口。

  • 点击新建,在变量名中输入PATH(大写),在变量值中输入C:\Python36\Scripts\;C:\Python36\C:\Python36\Scripts\文件夹下有一些常用工具,例如pip包管理工具,也加入到环境变量中,这样方便以后使用;C:\Python36\就是python的安装目录。

  • 将cmd命令行都关闭,重新打开cmd,再次输入python进行验证。

Python环境到这里就安装完毕了。

包管理工具pip

pip是Python的一款包管理工具,由于众所周知的原因,用pip安装库的速度简直是“是可忍孰不可忍”。因此,我们有必要加速pip包管理工具的下载速度。

pip的基本使用

Windows中,打开cmd命令行,输入pip后,可以看到使用方法:

1
2
3
4
5
6
7
8
# 搜索requests包
pip search requests
# 升级requests包
pip install requests --upgrade
# 卸载requests包
pip uninstall requests
# 查看待更新包
pip list --outdate

升级pip包管理器

1
python -m pip install --upgrade pip

加速pip下载速度

在某程序员论坛上,有这样一个软笑话:《安装scrapy快疯了,一个下午没了》😄️

我们使用清华大学开源软件镜像站的pypi镜像进行pip下载加速。

临时加速
1
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple requests

注意,simple不能少,是https而不是http

永久加速1

修改

~/.config/pip/pip.conf (Linux),

%APPDATA%\pip\pip.ini (Windows 10) ,

C:\Users\Administrator\AppData\Roaming\pip\pip.ini(Windows7),

$HOME/Library/Application Support/pip/pip.conf (macOS) (没有就创建一个),

修改 index-url至tuna,例如

1
2
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple

pip 和 pip3 并存时,只需修改 ~/.pip/pip.conf

永久加速2

使用脚本永久加速,只需用Python执行oh-my-tuna.py文件即可设置好镜像站加速,

该脚本在我们的源码中有提供,位置为CrawlerLessons/codes/lesson01/oh-my-tuna.py,下载后,直接在命令行中运行即可:

1
python on-my-tuna.py

安装IPython

ipython是一个python的交互式shell,比默认的python shell好用得多,支持变量自动补全,自动缩进,支持bash shell命令,内置了许多很有用的功能和函数。学习ipython将会让我们以一种更高的效率来使用python。同时它也是利用Python进行科学计算和交互可视化的一个最佳的平台。

使用pip安装IPython

1
pip install ipython

使用IPython,再命令行中输入ipython即可进入交互式shell

1
2
3
4
5
6
7
╭─sunjiajia@Mac /Users/sunjiajia  ‹system›
╰─$ ipython
Python 3.6.5 (default, Jul 2 2018, 18:32:34)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.4.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]:

IDE 的选择

在以后的编程中,我们使用PyCharm这款享誉全球的IDE,开发、调试、支持网页开发和支持数据库,可以满足我们几乎所有的开发需求。

PyCharm是收费软件,但也提供社区免费版本,虽然功能有所减少,但是也够我们后续写爬虫了。

PyCharm下载地址:官方网址

PyCharm的基本使用

创建项目:

选择项目路径:

创建Python文件,命名为test01.py

test01.py中输入以下python代码,右击空白处,选择Run test01,运行当前python文件:

PyCharm常用设置项如图所示:

HTML和CSS基础知识

这一节我们学习网页编程的基础知识。这节课目标是,了解网页的基本知识,在写爬虫的时候可以清晰的分析目标数据所在的结构,从而更轻松的拿到自己想要的数据。

无论是动态加载,还是延迟加载,无论是文字还是多媒体,最终在浏览器中展示给我们,都是以HTML语法来展示;无论是绚丽的动画页面效果,还是表格的样式,都可以用CSS来进行定制。

下面来一个概念简介,来自百度百科的内容:

HTML,即超文本标记语言(英语:HyperText Markup Language),是标准通用标记语言下的一个应用,也是一种规范,一种标准,它通过标记符号来标记要显示的网页中的各个部分。网页文件本身是一种文本文件,通过在文本文件中添加标记符,可以告诉浏览器如何显示其中的内容(如:文字如何处理,画面如何安排,图片如何显示等)。

CSS,即层叠样式表(英文全称:Cascading Style Sheets),是一种用来表现HTML或XML等文件样式的计算机语言。CSS不仅可以静态地修饰网页,还可以配合各种脚本语言动态地对网页各元素进行格式化。

HTML基本标签

标签名 含义
<!--...--> 注释标签用于在源代码中插入注释。注释不会显示在浏览器中。
<!DOCTYPE> <!DOCTYPE> 声明必须是 HTML 文档的第一行,位于 <html> 标签之前。<!DOCTYPE> 声明不是 HTML 标签;它是指示 web 浏览器关于页面使用哪个 HTML 版本进行编写的指令。在 HTML5 中只有一种写法<!DOCTYPE html>
<html> <html></html> 标签限定了文档的开始点和结束点,在它们之间是文档的头部和主体。正如您所了解的那样,文档的头部由 <head>标签定义,而主体由<body>标签定义。
<head> 用于定义文档的头部,它是所有头部元素的容器。<head> 中的元素可以引用脚本、指示浏览器在哪里找到样式表、提供元信息等等。
<meta> 提供有关页面的元信息(meta-information),比如针对搜索引擎和更新频度的描述和关键词。
<title> 定义文档的标题。
<style> 用于为 HTML 文档定义样式信息。type 属性是必需的,定义 style 元素的内容。唯一可能的值是 "text/css"
<link> 定义文档与外部资源的关系,最常见的用途是链接样式表。
<body> body 元素定义文档的主体,包含文档的所有内容(比如文本、超链接、图像、表格和列表等等。)

HTML常用标签

标签名 含义
<a href="http://news.baidu.com/" target="_blank">新闻</a> 定义超链接
<img src="images/logo.png" alt="GitOPEN搜索,最贴心搜索"> 插入图片
<table border="1"><tr><th>Month</th><th>Savings</th></tr><tr><td>January</td> <td>$100</td></tr></table> 表格
<div>我是div</div> 可定义文档中的分区或节
<p><span>some text.</span>some other text.</p> 被用来组合文档中的行内元素。
<ul><li>Coffee</li><li>Milk</li></ul> 无序列表
<ol><li>Coffee</li><li>Milk</li></ol> 有序列表
<input type="button" value="搜索一下"/> 用于搜集用户信息。根据不同的 type 属性值,输入字段可以是text、复选框checkbox、单选按钮radiobuttonsubmit等等。

CSS语法

HTML整合CSS的方式一

直接将css写在HTML文件中,代码CrawlerLessons/codes/lesson01/HTMLDemo/demo01.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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>我是GitOPEN</title>
<style>
#div01 {
background-color: #2d78f4;
}

.div02 {
background-color: cadetblue;
font-style: oblique;
font-weight: bold;
}
</style>
</head>
<body>
<div id="div01">
我是div01,我的样式使用了id选择器(div01)
</div>
<div class="div02">
我是div02,我的样式使用了类选择器(div02)
</div>
<div class="div02">
我是div03,我的样式使用了类选择器(div02)
</div>

</body>
</html>

HTML整合CSS的方式二

css写在单独的文件中,代码CrawlerLessons/codes/lesson01/HTMLDemo/demo02.css

1
2
3
4
5
6
7
8
9
#div01 {
background-color: #2d78f4;
}

.div02 {
background-color: cadetblue;
font-style: oblique;
font-weight: bold;
}

html也是一个单独的文件,代码CrawlerLessons/codes/lesson01/HTMLDemo/demo02.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>我是GitOPEN</title>
<link rel="stylesheet" href="demo02.css">
</head>
<body>
<div id="div01">
我是div01,我的样式使用了id选择器(div01)
</div>
<div class="div02">
我是div02,我的样式使用了类选择器(div02)
</div>
<div class="div02">
我是div03,我的样式使用了类选择器(div02)
</div>

</body>
</html>

CSS常用属性

属性名 作用
font-size 字号大小
font-style 字体格式
font-weight 字体粗细
color 文本颜色
text-decoration 超链接设置。line-through添加删除线;blink文字闪动;none不显示上述任何效果
background-color 背景颜色
backgroud-image 背景图片(地址)
background-repeat 是否重复。no-repeat不重复平铺;repeat-x或者y:只在水平或者垂直方向上平铺
text-align 文本对齐。left左对齐;right右对齐;center居中对齐;justify:相对左右两端对齐
display 显示样式。block块级元素,在对象前后都换行;inline在对象前后都不换行;list-item在对象前后都换行,增加了项目符号

Python必备知识点

基础数据类型

变量及其类型的含义

Python中的变量不需要声明,变量在使用前都必须赋值,在赋值以后,该变量才会被创建。

Python中的变量就是变量,它本身没有类型,通常所说的“变量类型”,表示的意思是变量所指向的内存中对象的类型。

1
2
3
name = 'GitOPEN'
age = 18
salary = 99999.99

等号(=)叫做运算符,用来给变量nameagesalary赋值,左边是一个变量名,右边是存储在变量中的值。

在给变量赋值不同类型的对象,那么,变量就有了类型。

name是字符串变量,age是整型变量,salary是浮点型变量。

多个变量赋值

Python中,可以同时为多个变量赋值:

1
aa = bb = cc = 11

这个例子的含义为,创建一个整型对象,值为11,从后向前赋值,3个变量都指向同一个内存地址。

再看一个例子:

1
dd, ee, ff = 22, 33, "GitOPEN"

这个例子中,将整型对象2233分别分配给变量ddee,字符串对象GitOPEN分配给变量ff

标准数据类型

  • Number(数字)── 不可变数据
  • String(字符串)──不可变数据
  • List(列表)──可变数据
  • Tuple(元组)──不可变数据
  • Set(集合)──可变数据
  • Dictionary(字典)──可变数据

Number(数字)

Python3中的支持int、float、bool、complex(复数),在Python3中,只有一种整数类型int,表示为长整型,没有python2中的Long。

示例:

1
2
3
4
In [3]: aa = 1111

In [4]: isinstance(aa, int)
Out[4]: True
数值运算
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
# 加法运算
In [5]: 11 + 11
Out[5]: 22

# 减法
In [6]: 5.21 - 5.20
Out[6]: 0.009999999999999787

# 减法
In [10]: 4.3 - 2
Out[10]: 2.3

# 取余
In [11]: 18 % 4
Out[11]: 2

# 乘方
In [12]: 2 ** 5
Out[12]: 32

# 除法,得到一个浮点数
In [13]: 2 / 4
Out[13]: 0.5

# 除法,得到一个整数
In [14]: 2 // 4
Out[14]: 0

# 除法,得到一个整数
In [15]: 5 // 2
Out[15]: 2
  • 注意:混合计算时,Python会把整型转换成为浮点数。
数值类型实例
int float complex
10 0.0 3.14j
100 15.20 45.j
-786 -21.9 9.322e-36j
080 32.3e+18 .876j
-0490 -90. -.6545+0J
-0x260 -32.54e100 3e+26J
0x69 70.2E-12 4.53e-7j
浮点数误差

先看一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
In [24]: x = 4.20

In [25]: y = 2.10

In [26]: x + y
Out[26]: 6.300000000000001

In [27]: (x + y) == 6.3
Out[27]: False

In [28]: x = 1.2

In [29]: y = 2.3

In [30]: x + y
Out[30]: 3.5

In [31]: (x + y) == 3.5
Out[31]: True

产生上述问题的原因,就来自于浮点数计算精度问题。

浮点数在计算机中表达为二进制(binary)小数,

例如,0.1251/10 + 2/100 + 5/100的值;

又例如0.0010/2 + 0/4 + 1/8的值。

这两个数值相同。唯一的实质区别是第一个写为十进制小数记法,第二个是二进制。

问题就来了,大多数十进制小数不能完全用二进制小数来表示,导致的结果是,一般情况下,你输入的十进制浮点数,由实际存储在计算机中的近似的二进制浮点数表示。

这个问题可以参见文档《浮点数算法:争议和限制》进行详细了解。

浮点数误差的解决方法

Python中的decimal模块可以解决浮点数误差的烦恼。这个模块可以通过整数、字符串、或者构建decimal.Decimal对象,来解决这个问题。如果是浮点数,因为浮点数本身存在误差,在计算前需要先将浮点数转化为字符串。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
In [32]: from decimal import Decimal

In [33]: from decimal import getcontext

In [34]: Decimal('4.20') + Decimal('2.10')
Out[34]: Decimal('6.30')

In [35]: x = 4.20

In [36]: y = 2.10

In [37]: z = Decimal(str(x)) + Decimal(str(y))

In [38]: z
Out[38]: Decimal('6.3')

# 设置精度
In [39]: getcontext().prec = 4

In [40]: Decimal('1.00') / Decimal('3.0')
Out[40]: Decimal('0.3333')
  • 注意,精度提升的同时,会伴随性能的损失。在对数据要求特别高的场景下,例如财务计算等,性能的损失是值得的。

String(字符串)

在Python中,字符串用单引号'或者双引号"括起来,如果遇到特殊字符,可以用反斜杠\进行转义。

字符串截取的用法示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
In [41]: aa = '我爱学习'

In [42]: bb = '我是张学友的粉丝'

In [44]: aa[1:3]
Out[44]: '爱学'

In [45]: aa[1:4]
Out[45]: '爱学习'

In [47]: bb[-6:-1]
Out[47]: '张学友的粉'

In [48]: bb[-7:-1]
Out[48]: '是张学友的粉'

加号+是字符串的连接符,星号*表示复制当前字符串多少次:

1
2
3
4
5
In [50]: aa + "," + bb
Out[50]: '我爱学习,我是张学友的粉丝'

In [51]: (aa + "," + bb + "。") * 10
Out[51]: '我爱学习,我是张学友的粉丝。我爱学习,我是张学友的粉丝。我爱学习,我是张学友的粉丝。我爱学习,我是张学友的粉丝。我爱学习,我是张学友的粉丝。我爱学习,我是张学友的粉丝。我爱学习,我是张学友的粉丝。我爱学习,我是张学友的粉丝。我爱学习,我是张学友的粉丝。我爱学习,我是张学友的粉丝。'

我们有这样一个字符串GitOPEN\niubi,看一下下面的操作:

1
2
3
4
5
6
7
8
9
10
In [53]: cc = "GitOPEN\niubi"

In [54]: print(cc)
GitOPEN
iubi

In [55]: dd = r"GitOPEN\niubi"

In [56]: print(dd)
GitOPEN\niubi

如果字符串本身有特殊字符,但是想让字符串中的特殊字符不转义,那么在字符串前面加上r,表示按照原始字符串进行输出。

List(列表)

List可以说是Python中使用最频繁的数据类型。列表中的元素类型可以不相同,它支持数字,字符串甚至可以列表嵌套。

下面是列表,列表截取操作,列表排序操作:

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
In [57]: a_list = ['aa', 'bb', 'cc', 'dd', 'ee']

In [58]: b_list = [11, 22, 33.22, 44.05]

In [59]: print(a_list[1])
bb

In [60]: print(a_list[1:3])
['bb', 'cc']

In [61]: print(a_list[2:])
['cc', 'dd', 'ee']

In [62]: print(b_list)
[11, 22, 33.22, 44.05]

# reverse = False表示升序,这是默认值
In [64]: b_list.sort(reverse=False)

In [65]: print(b_list)
[11, 22, 33.22, 44.05]

# reverse = True表示降序
In [66]: b_list.sort(reverse=True)

In [67]: print(b_list)
[44.05, 33.22, 22, 11]

Tuple(元组)

Python中,元组是用()括起来的,元素不能修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
a_tup = ('锄禾','日','当午')
b_tup = (1, 2, 3, 4, 5)
c_tup = "a", "b", "c", "d"

# 创建空元组
d_tup = ()

# 元组中只有一个元素时,需要在元素后面添加逗号
e_tup = (50,)

f_tup = a_tup + b_tup

print(f_tup)

# 删除元组
del f_tup
print(f_tup)
元组内置函数

Python元组包含了以下内置函数:

序号 方法及描述
1 cmp(tuple1, tuple2)比较两个元组元素。
2 len(tuple) 计算元组元素个数。
3 max(tuple) 返回元组中元素最大值。
4 min(tuple)返回元组中元素最小值。
5 tuple(seq) 将列表转换为元组。

Dictionary(字典)

Python中的字典另一种可变容器模型,可以存储任意类型对象。

键值对的键和值用:冒号分割,每个键值对用,逗号分割;键是唯一的,值不需要唯一,如果键重复,那么最后一个键值对会覆盖前面的。

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
In [69]: a_dict = {'a':'1', 'b':'2', 'c':'3', 'b':'4'}

# 取值
In [70]: a_dict['b']
Out[70]: '4'

In [71]: a_dict
Out[71]: {'a': '1', 'b': '4', 'c': '3'}

# 更新值
In [72]: a_dict['a'] = 11

In [73]: a_dict
Out[73]: {'a': 11, 'b': '4', 'c': '3'}

# 删除某个键对应的值
In [74]: del a_dict['c']

In [75]: a_dict
Out[75]: {'a': 11, 'b': '4'}

# 清空字典中所有的值
In [76]: a_dict.clear()

In [77]: a_dict
Out[77]: {}

# 删除字典
In [78]: del a_dict

In [79]: a_dict
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-79-374973eefd04> in <module>()
----> 1 a_dict

NameError: name 'a_dict' is not defined
字典中键的特性
  • 同一个键不允许出现两次。创建时如果同一个键被赋值两次,后一个值会被记住。
  • 键必须是不可变数据类型,可以用数字、字符串、元组,但是列表就不行。
字典的内置函数
序号 函数及描述
1 cmp(dict1, dict2)比较两个字典元素。
2 len(dict)计算字典元素个数,即键的总数。
3 str(dict)输出字典可打印的字符串表示。
4 type(variable)返回输入的变量类型,如果变量是字典就返回字典类型。
字典的内置方法
序号 函数及描述
1 dict.clear()删除字典内所有元素
2 dict.copy()返回一个字典的浅复制
3 dict.fromkeys(seq[, val])创建一个新字典,以序列 seq 中元素做字典的键,val 为字典所有键对应的初始值
4 dict.get(key, default=None)返回指定键的值,如果值不在字典中返回default值
5 dict.has_key(key) 如果键在字典dict里返回true,否则返回false
6 dict.items()以列表返回可遍历的(键, 值) 元组数组
7 dict.keys()以列表返回一个字典所有的键
8 dict.setdefault(key, default=None)get()类似, 但如果键不存在于字典中,将会添加键并将值设为default
9 dict.update(dict2)把字典dict2的键/值对更新到dict里
10 dict.values()以列表返回字典中的所有值
11 pop(key[,default])删除字典给定键 key 所对应的值,返回值为被删除的值。key值必须给出。 否则,返回default值。
12 popitem()随机返回并删除字典中的一对键和值。

函数

函数是组织好的,可重复使用的,用来实现单一或者相关功能的代码段。它能够提高应用的模块性,以及代码的重复利用率。我们已经使用过很多内建函数,比如print(),但是,也可以创建用户自定义函数。

定义一个函数

定义一个函数非常简单,它有几个规则:

  • 函数以def关键字开头,后接函数名称和():
  • 传入参数和自变量必须放在()
  • 函数代码块的内部第一行可以使用文档字符串进行函数说明
  • return [表达式]用来结束函数,选择是否返回值给调用者,不带表达式的return相当于返回None

示例:

1
2
3
4
5
6
7
8
9
10
def sayhello(text):
"""
这是一个说你好的函数
:param text: 打招呼内容
:return: 返回打招呼内容
"""
result = "你好," + text
return result

sayhelllo('世界')

参数

参数类型:

  • 必备参数
  • 关键字参数
  • 默认参数
  • 不定长参数

必备参数

必备参数必须以正确的顺序传入函数,调用的时候,数量必须和声明的一样。

1
2
3
4
5
6
7
def printtext(text):
print(text)
return;

printtext('你好,世界')
# 报错 TypeError: printtext() missing 1 required positional argument: 'text'
printtext()

关键字参数

使用关键字参数允许函数在调用时参数的顺序与声明时不一致。

1
2
3
4
5
6
7
def printmsg(text1, text2):
print('text1是:', text1)
print('text2是:', text2)
return


printmsg(text2='世界', text1='你好')

缺省参数

调用函数时,如果缺省参数的值没有传入,那么会使用默认值。

1
2
3
4
5
6
7
8
9
def printemployee(uid, name, salary=1000.00):
print('Uid:', uid)
print('Name:', name)
print('Salary:', salary)
return


printemployee('001', '张1', 2000.00)
printemployee('002', '张2')

不定长参数

有的时候,我们需要一个函数,它能够处理比当初声明时更多的参数,这些参数叫做不定长参数。加了星号(*)的变量名会存放所有未命名的变量参数。

1
2
3
4
5
6
7
8
9
10
def printinfo(arg1, *args):
print('输出参数:')
print('arg1:', arg1)
for arg in args:
print('arg', arg)
return


printinfo(1, 2)
printinfo(3, 4, 5, 6)

匿名函数

创建匿名函数的方法是使用lambda

示例:

1
2
sum = lambda x, y: x + y
print(sum(1, 2))

全局变量和局部变量

定义在函数内部的是局部变量,拥有局部作用域;定义在函数外的变量是全局变量,拥有全局作用域。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。

示例:

1
2
3
4
5
6
7
8
9
10
# 全局变量
total = 0

def sum(x, y):
total = x + y
print('函数内是局部变量:', total)
return total

sum(11, 22)
print('函数外是全局变量:', total)

命名空间和作用域

变量就是一个名字(标识符),它指向了对象。命名空间是一个字典,它的键是变量名称,对应的值是对象。

Python表达式可以访问局部命名空间和全局命名空间里面的变量。如果一个局部变量和一个全局变量重名,则局部变量会覆盖全局变量。

每一个函数都有自己的命名空间,类的方法的作用域的规则和一般的函数一样。Python会智能地猜测变量是局部还是全局的,并且假设在函数内赋值的变量都是局部的。

面向对象编程

Python是一门面向对象语言,因此在Python中创建类和对象是轻而易举的事情。

面向对象简介

概念 含义
类,Class 类是一个集合,描述了具有相同的属性和方法的对象
实例化 就是创建类的实例,类的具体对象
类变量 在实例化对象中,类变量是公用的;类变量定义在类内部并且在函数体之外
数据成员 类变量或者实例变量,用于处理类及其实例对象的相关的数据
继承 派生类继承基类(父类)的字段和方法。允许把一个派生类对象作为父类对象对待。
方法重写 子类从父类继承过来的方法,不能满足子类的需求,可以对其进行重写(override)
方法 类中的函数
对象 类的实例,包括两个数据成员(类变量、实例变量)和方法
实例变量 定义在方法中的变量

创建类

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Employee:
count = 0

def __init__(self, name, age):
self.name = name
self.age = age
Employee.count += 1

def print_count(self):
print("员工总数为:{}".format(Employee.count))

def show_info(self):
print("Name:{},Age:{}".format(self.name, self.age))

def prt(self):
print(self)
print(self.__class__)
  • count是一个类变量,它的值在这个类的实例对象之间共享。
  • __init__()方法是一个特殊的方法,叫做类的构造函数或者初始化方法,当实例化该类的对象时就会调用这个方法
  • self代表类的实例,在定义类的方法时是必须的,但在调用时不必传入相应的参数
  • 类的方法与普通的函数只有一个区别,它必须有一个额外的第一个参数名称,按照习惯,它的名称是self
1
2
3
4
5
6
7
8
9
10
11
12
# 实例化对象
emp1 = Employee('张三', 18)
# 对象调用方法
emp1.print_count()
emp1.show_info()

emp2 = Employee('张四', 17)
emp2.print_count()
emp2.show_info()

# self是类的实例,代表当前对象的地址;self.__class__指向类。
emp1.prt()

打印的结果为:

1
2
3
4
5
6
员工总数为:1
Name:张三,Age:18
员工总数为:2
Name:张四,Age:17
<__main__.Employee object at 0x1120564a8>
<class '__main__.Employee'>

一些访问属性的函数:

函数 含义
getattr(obj, name[,default]) 访问对象的属性
hasattr(obj,name) 检查是否存在一个属性
setattr(obj,name,value) 设置一个属性,如果属性不存在,则创建一个新属性
delattr(obj,name) 删除属性

内置类属性

名称 含义
__dict__ 类的属性,包含一个字典,由类的数据属性组成
__doc__ 类的文档字符串
__name__ 类名
__module__ 类所在的模块,全名为__main__className
__bases__ 类的所有父类构成元素,包含一个由所有父类组成的元组

示例:

1
2
3
4
5
print("Employee.__doc__:", Employee.__doc__)
print("Employee.__name__:", Employee.__name__)
print("Employee.__module__:", Employee.__module__)
print("Employee.__bases__:", Employee.__bases__)
print("Employee.__dict__:", Employee.__dict__)

输出:

1
2
3
4
5
6
7
Employee.__doc__: 
员工基类

Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: (<class 'object'>,)
Employee.__dict__: {'__module__': '__main__', '__doc__': '\n 员工基类\n ', 'count': 2, '__init__': <function Employee.__init__ at 0x105180268>, 'print_count': <function Employee.print_count at 0x1051802f0>, 'show_info': <function Employee.show_info at 0x105180378>, 'prt': <function Employee.prt at 0x105180400>, '__dict__': <attribute '__dict__' of 'Employee' objects>, '__weakref__': <attribute '__weakref__' of 'Employee' objects>}

类的继承

代码重用是面向对象编程带来的主要好处之一,实现重用的方法之一就是继承机制

示例:

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
class Parent:
parent_attr = 123

def __init__(self):
print("Parent构造函数")

def parentMethod(self):
print("Parent方法")

def setAttr(self, attr):
Parent.parent_attr = attr

def getAttr(self):
print("父类属性:", Parent.parent_attr)


class Child(Parent):
def __init__(self):
print("子类构造函数")

def childMethod(self):
print("Child方法")


child1 = Child()
child1.childMethod()
child1.parentMethod()
child1.setAttr(456)
child1.getAttr()

输出:

1
2
3
4
子类构造函数
Child方法
Parent方法
父类属性: 456

方法重载

如果父类的方法的功能不能满足你的需求,在子类中可以重写父类的方法。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
class A:
def myMethod(self):
print("父类方法")


class B(A):
def myMethod(self):
print("子类方法")


b = B()
b.myMethod()

time模块、datetime模块、json模块、csv模块使用方法

time 模块

在编写Python程序时,转换日期时间是一个常见的功能。时间间隔是以秒为单位的浮点小数。每个时间戳都以自从1970年1月1日午夜(历元)经过了多长时间来表示。

获取当前时间戳:

1
2
3
4
import time

ticks = time.time()
print("当前的时间戳为:{}".format(ticks))

时间元组

struct_time元组,具有如下属性:

序号 字段 属性
0 4位年 tm_year 2018
1 tm_mon 1到12
2 tm_mday 1到31
3 小时 tm_hour 0到23
4 分钟 tm_min 0到59
5 tm_sec 0到61(60或61是润秒)
6 一周的第几日 tm_wday 0到6(0是周一)
7 一年的第几日 tm_yday 1到366
8 夏令时 tm_isdst -1, 0, 1, -1是决定是否为夏令时的旗帜

获取当前时间

1
2
3
4
import time

localtime = time.localtime(time.time())
print("当前本地时间为:{}".format(localtime))

输出为:

1
当前本地时间为:time.struct_time(tm_year=2018, tm_mon=8, tm_mday=13, tm_hour=21, tm_min=49, tm_sec=53, tm_wday=0, tm_yday=225, tm_isdst=0)

格式化时间

1
2
3
4
import time

localtime = time.asctime(time.localtime(time.time()))
print("格式化后的时间为:{}".format(localtime))

输出:

1
格式化后的时间为:Mon Aug 13 21:52:20 2018

格式化日期

1
2
3
4
5
6
7
8
9
10
11
import time

# 格式化成2018-08-13 21:55:46形式
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

# 格式化成Mon Aug 13 21:52:20 2018形式
print(time.strftime("%a %b %d %H:%M:%S %Y", time.localtime()))

# 将格式字符串转换为时间戳
a = "Mon Aug 13 21:52:20 2018"
print(time.mktime(time.strptime(a, "%a %b %d %H:%M:%S %Y")))

输出:

1
2
3
2018-08-13 21:56:49
Mon Aug 13 21:56:49 2018
1534168340.0

datetime模块

1
2
3
4
5
6
7
8
9
10
11
12
import datetime

i = datetime.datetime.now()
print("当前的日期和时间是 %s" % i)
print("ISO格式的日期和时间是 %s" % i.isoformat())
print("当前的年份是 %s" % i.year)
print("当前的月份是 %s" % i.month)
print("当前的日期是 %s" % i.day)
print("dd/mm/yyyy 格式是 %s/%s/%s" % (i.day, i.month, i.year))
print("当前小时是 %s" % i.hour)
print("当前分钟是 %s" % i.minute)
print("当前秒是 %s" % i.second)

json模块

在使用Python进行数据处理的过程中,我们经常和json数据打交道。

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。

json模块的两个常用函数为:

函数名 含义
json.dumps 将Python对象编码成JSON字符串
json.loads 将已编码的JSON字符串解码为Python对象

json.dumps

示例:

将Python对象(数组)编码为JSON格式数据:

1
2
3
4
5
6
7
import json

data = [{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}]

json_str = json.dumps(data)
print(json_str)
print(type(json_str))

格式化输出JSON数据:

1
2
3
data = {'name': 'GitOPEN', 'salary': 70000.01}
json_str = json.dumps(data, sort_keys=True, indent=4, separators=(', ', ': '))
print(json_str)

python 原始类型向 json 类型的转化对照表:

Python JSON
dict object
list, tuple array
str, unicode string
int, long, float number
True true
False false
None null

json.loads

用于解码JSON数据,返回Python字段的数据类型。

示例:

1
2
3
4
5
6
7
import json

json_str = '{"a":1,"b":2,"c":3,"d":4,"e":5}'

text = json.loads(json_str)
print(type(text))
print(text)

csv模块

csv库可以帮助我们解决大多数CSV格式的数据读写问题。

读数据

准备一个csv格式的文件,命名为data.csv

1
2
3
4
5
Uid,Name,Age,Score
1000,"张1",18,99.99
1001,"张2",19,89.99
1002,"张3",20,79.99
1003,"张4",21,69.99

示例:将这个数据文件读取为一个元组序列:

1
2
3
4
5
6
import csv

with open('data.csv', 'r', encoding='utf-8') as f:
f_csv = csv.reader(f)
for row in f_csv:
print(row)

注意:data.csv和py文件的编码格式应当统一为utf-8。

输出为:

1
2
3
4
5
['Uid', 'Name', 'Age', 'Score']
['1000', '张1', '18', '99.99']
['1001', '张2', '19', '89.99']
['1002', '张3', '20', '79.99']
['1003', '张4', '21', '69.99']

示例:将这个数据读取为一个字典:

1
2
3
4
5
6
7
import csv

with open('data.csv', 'r', encoding='utf-8') as f:
f_csv = csv.DictReader(f)
for row in f_csv:
print(type(row))
print(row)

输出:

1
2
3
4
5
6
7
8
<class 'collections.OrderedDict'>
OrderedDict([('Uid', '1000'), ('Name', '张1'), ('Age', '18'), ('Score', '99.99')])
<class 'collections.OrderedDict'>
OrderedDict([('Uid', '1001'), ('Name', '张2'), ('Age', '19'), ('Score', '89.99')])
<class 'collections.OrderedDict'>
OrderedDict([('Uid', '1002'), ('Name', '张3'), ('Age', '20'), ('Score', '79.99')])
<class 'collections.OrderedDict'>
OrderedDict([('Uid', '1003'), ('Name', '张4'), ('Age', '21'), ('Score', '69.99')])

写数据

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
import csv

headers = ['Uid', 'Name', 'Age', 'Score']
rows = [
('1000', '张1', '18', '99.99'),
('1001', '张2', '19', '89.99'),
('1002', '张3', '20', '79.99'),
('1003', '张4', '21', '69.99')
]
with open('data1.csv', 'w', newline='') as f:
f_csv = csv.writer(f)
f_csv.writerow(headers)
f_csv.writerows(rows)

注意:newline=''这个参数,你会发现,如果不加,生成的csv文件中每一行下面总是会多一行空白行。

示例:

写入字典序列数据到csv文件中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import csv

headers = ['Uid', 'Name', 'Age', 'Score']
rows = [
{'Uid': 1000, 'Name': '张1', 'Age': 18, 'Score': 99.99},
{'Uid': 1001, 'Name': '张2', 'Age': 19, 'Score': 89.99},
{'Uid': 1002, 'Name': '张3', 'Age': 20, 'Score': 79.99},
{'Uid': 1003, 'Name': '张4', 'Age': 21, 'Score': 69.99}
]

with open('data2.csv', 'w', newline='') as f:
f_csv = csv.DictWriter(f, headers)
f_csv.writeheader()
f_csv.writerows(rows)

实战──搜索引擎首页实战

写好的GitOPEN搜索首页如图所示:

整个项目的结构如图所示,项目源码位置CrawlerLessons/codes/lesson01/SearchDemo

index.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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>GitOPEN搜索,最贴心搜索</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div id="root">
<div id="header">
<div id="links">
<a href="http://news.baidu.com/" target="_blank">新闻</a>
<a href="https://www.hao123.com/" target="_blank">hao123</a>
<a href="http://map.baidu.com/" target="_blank">地图</a>
<a href="http://v.baidu.com/" target="_blank">视频</a>
<a href="table.html" target="_blank">员工</a>
<a href="list.html" target="_blank">列表</a>
</div>
</div>
<div id="content">
<img src="images/logo.png" alt="GitOPEN搜索,最贴心搜索">
<br>
<form action="https://www.so.com/s?" method="get">
<input id="input_search" type="text" name="q">
<input id="btn_search" type="submit" value="搜索一下"/>
</form>
</div>
<div id="footer">
Powered by GitOPEN ® Hosted by <a href="https://www.vultr.com/?ref=7147564" target="_blank">Vultr</a>
</div>
</div>
</body>
</html>

index.css源码:

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
* {
margin: 0px;
padding: 0px;
}

html, body {
width: 100%;
height: 100%;
}

#root {
width: 100%;
height: 100%;
align-self: center;
}

#header {
height: fit-content;
text-align: right;
}

#header #links {
padding: 10px;
}

#header #links a {
color: black;
font-size: 16px;
font-weight: bold;
margin-right: 16px;
}

#content {
height: 70%;
text-align: center;
padding-top: 60px;
}

#content img {
width: 300px;
}

#content #btn_search {
height: 34px;
width: 80px;
padding: 5px;
border: 0px;
background-color: #3D5984;
font-size: 16px;
color: #FFFFFF;
}

#content #input_search {
height: 34px;
width: 500px;
font-size: 18px;
border-color: #3D5984;
}

#footer {
height: 20%;
text-align: center;
font-style: oblique;
}

list.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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>列表示例</title>
</head>
<body>

<h3>无序列表</h3>
<ul>
<li>张1</li>
<li>张2</li>
<li>张3</li>
<li>张4</li>
</ul>
<hr>
<h3>有序列表</h3>
<ol>
<li>张1</li>
<li>张2</li>
<li>张3</li>
<li>张4</li>
</ol>
</body>
</html>

table.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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>员工信息</title>
<style>
table, th, td {
border: 1px #2d78f4 dashed;
border-collapse: collapse;
text-align: center;
}

table {
width: auto;
}

th, td {
width: 90px;
}

th {
color: crimson;
}

#total {
color: blueviolet;
}
</style>
</head>
<body>

<table>
<tr>
<th>编号</th>
<th>姓名</th>
<th>月薪</th>
</tr>
<tr>
<td>0001</td>
<td>张1</td>
<td>20000.00</td>
</tr>
<tr>
<td>0002</td>
<td>张2</td>
<td>10000.00</td>
</tr>
<tr>
<td>0003</td>
<td>张3</td>
<td>8000.00</td>
</tr>
<tr>
<td colspan="2">总计</td>
<td colspan="1" id="total">38000.00</td>
</tr>
</table>

</body>
</html>

实战──简易学生管理系统

这是一个玩具代码项目,用来练习刚刚学会的Python基础知识。

这个实战例子我们不再做代码演示,请大家自行运行代码,找出代码的不足之处,写出自己的《简易学生管理系统》,要求具有的功能如下图所示:

参考代码位置:CrawlerLessons/codes/lesson01/StudentSystem

参考资料推荐


欣慰帮到你 一杯热咖啡
【奋斗的Coder!】企鹅群
【奋斗的Coder】公众号
CATALOG
  1. 1. 基础知识
  2. 2. 环境搭建
    1. 2.1. Python安装
      1. 2.1.1. Windows下安装Python
      2. 2.1.2. 包管理工具pip
        1. 2.1.2.1. pip的基本使用
        2. 2.1.2.2. 升级pip包管理器
        3. 2.1.2.3. 加速pip下载速度
          1. 2.1.2.3.1. 临时加速
          2. 2.1.2.3.2. 永久加速1
          3. 2.1.2.3.3. 永久加速2
        4. 2.1.2.4. 安装IPython
    2. 2.2. IDE 的选择
      1. 2.2.1. PyCharm的基本使用
  3. 3. HTML和CSS基础知识
    1. 3.1. HTML基本标签
    2. 3.2. HTML常用标签
    3. 3.3. CSS语法
      1. 3.3.1. HTML整合CSS的方式一
      2. 3.3.2. HTML整合CSS的方式二
      3. 3.3.3. CSS常用属性
  4. 4. Python必备知识点
    1. 4.1. 基础数据类型
      1. 4.1.1. 变量及其类型的含义
      2. 4.1.2. 多个变量赋值
      3. 4.1.3. 标准数据类型
        1. 4.1.3.1. Number(数字)
          1. 4.1.3.1.1. 数值运算
          2. 4.1.3.1.2. 数值类型实例
          3. 4.1.3.1.3. 浮点数误差
          4. 4.1.3.1.4. 浮点数误差的解决方法
        2. 4.1.3.2. String(字符串)
        3. 4.1.3.3. List(列表)
        4. 4.1.3.4. Tuple(元组)
          1. 4.1.3.4.1. 元组内置函数
        5. 4.1.3.5. Dictionary(字典)
          1. 4.1.3.5.1. 字典中键的特性
          2. 4.1.3.5.2. 字典的内置函数
          3. 4.1.3.5.3. 字典的内置方法
    2. 4.2. 函数
      1. 4.2.1. 定义一个函数
      2. 4.2.2. 参数
        1. 4.2.2.1. 必备参数
        2. 4.2.2.2. 关键字参数
        3. 4.2.2.3. 缺省参数
        4. 4.2.2.4. 不定长参数
      3. 4.2.3. 匿名函数
      4. 4.2.4. 全局变量和局部变量
      5. 4.2.5. 命名空间和作用域
    3. 4.3. 面向对象编程
      1. 4.3.1. 面向对象简介
      2. 4.3.2. 创建类
      3. 4.3.3. 内置类属性
      4. 4.3.4. 类的继承
        1. 4.3.4.1. 方法重载
    4. 4.4. time模块、datetime模块、json模块、csv模块使用方法
      1. 4.4.1. time 模块
        1. 4.4.1.1. 时间元组
        2. 4.4.1.2. 获取当前时间
        3. 4.4.1.3. 格式化时间
        4. 4.4.1.4. 格式化日期
      2. 4.4.2. datetime模块
      3. 4.4.3. json模块
        1. 4.4.3.1. json.dumps
        2. 4.4.3.2. json.loads
      4. 4.4.4. csv模块
        1. 4.4.4.1. 读数据
        2. 4.4.4.2. 写数据
  5. 5. 实战──搜索引擎首页实战
  6. 6. 实战──简易学生管理系统
  7. 7. 参考资料推荐