Python爬虫从入门到精通系列──第1课 基础知识

本教程所有源码下载链接:https://share.weiyun.com/5xmFeUO 密码:fzwh6g
本教程首发于GitOPEN's Home,转载请征求作者同意

基础知识

环境搭建

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的主页

image

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

image

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

image

安装。按图示操作即可。

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

    image
  • 直接下一步。

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

    image
  • 安装成功

    image

环境变量检测与设置。

  • 打开cmd命令行。

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

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

    image

设置环境变量。

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

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

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

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

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

包管理工具pip

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

pip的基本使用

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

image
# 搜索requests包
pip search requests
# 升级requests包
pip install requests --upgrade
# 卸载requests包
pip uninstall requests
# 查看待更新包
pip list --outdate

升级pip包管理器

python -m pip install --upgrade pip

加速pip下载速度

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

image

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

临时加速
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,例如

[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,下载后,直接在命令行中运行即可:

python on-my-tuna.py

安装IPython

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

使用pip安装IPython

pip install ipython

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

╭─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的基本使用

创建项目:

image

选择项目路径:

image

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

image

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

image

PyCharm常用设置项如图所示:

image

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

<!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

#div01 {
    background-color: #2d78f4;
}

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

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

<!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中的变量就是变量,它本身没有类型,通常所说的“变量类型”,表示的意思是变量所指向的内存中对象的类型。

name = 'GitOPEN'
age = 18
salary = 99999.99

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

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

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

多个变量赋值

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

aa = bb = cc = 11

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

再看一个例子:

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。

示例:

In [3]: aa = 1111

In [4]: isinstance(aa, int)
Out[4]: True
数值运算
# 加法运算
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
浮点数误差

先看一个例子:

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对象,来解决这个问题。如果是浮点数,因为浮点数本身存在误差,在计算前需要先将浮点数转化为字符串。

示例:

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中,字符串用单引号'或者双引号"括起来,如果遇到特殊字符,可以用反斜杠\进行转义。

字符串截取的用法示例:

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]: '是张学友的粉'

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

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

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

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

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中使用最频繁的数据类型。列表中的元素类型可以不相同,它支持数字,字符串甚至可以列表嵌套。

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

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中,元组是用()括起来的,元素不能修改。

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中的字典另一种可变容器模型,可以存储任意类型对象。

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

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

示例:

def sayhello(text):
    """
    这是一个说你好的函数
    :param text: 打招呼内容
    :return: 返回打招呼内容
    """
    result = "你好," + text
    return result

sayhelllo('世界')

参数

参数类型:

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

必备参数

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

def printtext(text):
    print(text)
    return;

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

关键字参数

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

def printmsg(text1, text2):
    print('text1是:', text1)
    print('text2是:', text2)
    return


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

缺省参数

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

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')

不定长参数

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

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

示例:

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

全局变量和局部变量

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

示例:

# 全局变量
total = 0

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

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

命名空间和作用域

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

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

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

面向对象编程

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

面向对象简介

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

创建类

示例:

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
# 实例化对象
emp1 = Employee('张三', 18)
# 对象调用方法
emp1.print_count()
emp1.show_info()

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

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

打印的结果为:

员工总数为: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__ 类的所有父类构成元素,包含一个由所有父类组成的元组

示例:

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__)

输出:

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>}

类的继承

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

示例:

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()

输出:

子类构造函数
Child方法
Parent方法
父类属性: 456

方法重载

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

示例:

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日午夜(历元)经过了多长时间来表示。

获取当前时间戳:

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是决定是否为夏令时的旗帜

获取当前时间

import time

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

输出为:

当前本地时间为: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)

格式化时间

import time

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

输出:

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

格式化日期

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")))

输出:

2018-08-13 21:56:49
Mon Aug 13 21:56:49 2018
1534168340.0

datetime模块

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格式数据:

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数据:

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字段的数据类型。

示例:

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

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

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

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。

输出为:

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

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

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)

输出:

<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')])

写数据

示例:

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文件中。

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搜索首页如图所示:

image

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

image

index.html源码:

<!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源码:

* {
    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源码:

<!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源码:

<!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基础知识。

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

image

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

参考资料推荐

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,423评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,147评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,019评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,443评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,535评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,798评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,941评论 3 407
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,704评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,152评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,494评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,629评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,295评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,901评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,978评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,333评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,499评论 2 348

推荐阅读更多精彩内容