六万字带你一次性速通python爬虫基础(1)

运行后出现这样的提示和画面:

之后就可以正常运行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©

print(type©)

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

float转成整数,会返回小数点前的整数,不涉及四舍五入

d = int©

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

d = float©

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

d = str©

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

d = bool©

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§

空列表是False

q = []

print(type(q))

r = bool(q)

print(type®)

print®

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©

多个变量同时赋值

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©

调用时,有两种传参方法:

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(‘编码格式’) 编码格式在 中显示

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查找’'标签的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 = url,headers = headers)

response = urllib.request.urlopen(request)

content = response.read().decode(‘utf-8’)

print(content)

get请求的urlencode()方法:适用于多个参数的编解码,例如下面的案例,有两个参数时这种方法更便捷

首先写出基础部分的url

base_url = ‘https://www.xxx.com/s?’

接下来定义多个参数,这些参数可以是中文的,不需要是unicode码

data = {

‘wd’ : ‘xx’,

‘sex’ : ‘xx’,

‘location’ : ‘xx’

}

此时使用urlencode()把整个多参数全部转成unicode码:

uni_data = urllib.parse.urlencode(data)

拼接url即可:

url = base_url + uni_data

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)


🎯 urllib库之POST请求的处理

这部分主要介绍urllib库对POST请求的处理,下面是urllib库处理POST请求的示例代码

post请求:

import urllib.request

url = ‘https://xxx’

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’

}

data = {

‘data’:‘data’

}

import urllib.parse

post请求的参数 必须 进行编码

data = urllib.parse.urlencode(data).encode(‘utf-8’)

post请求的参数是不会拼接在url 的后面的,而是需要放置在请求对象定制的地方

request = urllib.request.Request(url = url,data = data,headers = headers)

模拟浏览器向服务器发送请求

response = urllib.request.urlopen(request)

获取响应的数据

content = response.read().decode(‘utf-8’)

import json

字符串 - - - > json 对象

obj = json.loads(content)

print(obj)

通过上面的示例代码,我们联系之前的GET请求的处理,可以考虑一下二者处理上的区别。示例代码最后部分转换json对象的原因是获取的数据格式是json字符串,我们通过转为json对象能够具体的对获取的数据进行进一步的分析


🎯 GET请求与POST请求处理的区别

下面总结一下urllib处理GET请求与POST请求的区别:

1️⃣ post请求的参数必须编码+转码,也即编码之后,必须调用encode方法:

data = urllib.parse.urlencode(data).encode(‘utf-8’)

get请求的参数只需要进行编码即可,也即:

data = urllib.parse.urlencode(data)

2️⃣ post请求的参数放在请求对象的定制过程中,而不是拼接字符串

request = urllib.request.Request(url = url,data = data,headers = headers)

response = urllib.request.urlopen(request)

但get请求的参数使用字符串拼接在url上:

url = base_url + uni_data

request = urllib.request.Request(url = url,headers = headers)

response = urllib.request.urlopen(request)


🎯 urllib库之handler处理器

首先简单介绍一下handler处理器

handler处理器是urllib库中继urlopen()方法之后又一种模拟浏览器向服务器发起请求的方法或技术。

它的意义在于使用handler处理器,能够携带代理ip,这为对抗反爬机制提供了一种策略(很多的网站会封掉短时间多次访问的ip地址)。

下面是handler处理器的具体使用方法,其中不含代理ip的部分,代理ip这部分将在下一篇笔记中介绍。

handler处理器的基础使用

需求:使用handler访问百度 获取网页源码

import urllib.request

url = ‘http://www.baidu.com’

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)

handler build_opener open

第一步:获取handler对象

handler = urllib.request.HTTPHandler()

第二步:通过handler获取opener对象

opener = urllib.request.build_opener(handler)

第三步:调用open()函数

response = opener.open(request)

content = response.read().decode(‘utf-8’)

print(content)

代码的步骤很清晰,我们可以简化整个过程为三个步骤:首先通过urllib库新建一个handler对象,而后通过urllib库的build_opener()方法新建一个opener对象,其中build_opener()要传入handler对象,最后通过opener的open()方法,获取响应,传参是我们的request定制请求对象。🌟🌟🌟


🎯 urllib库之代理ip与代理池

首先先介绍一下什么是代理ip地址:

代理IP地址:代理IP地址一般是说代理服务器的IP地址,就是说你的电脑先连接到代理IP,然后通过代理服务器上网,网页的内容 通过代理服务器,传回你自己的电脑**。代理IP就是一个安全保障,这样一来暴露在公网的就是代理IP而不是你的IP了!**

以上是对代理ip的介绍,通过介绍可以看出,我们通过代理ip能够防止自己的ip在爬取内容的时候暴露,这样一方面提高了保密性,最重要的点是通过代理ip,我们可以应对ip被封这一反爬机制了!

下面是使用代理ip的示例代码,代码中主要涉及到的知识点是handler处理器的使用(handler处理器使用方式见本文上面部分)

urllib代理

import urllib.request

url = ‘https://www.xxx’

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’

}

proxies = {

‘http’ : ‘40.83.102.86:80’

}

request = urllib.request.Request(url = url, headers = headers)

handler = urllib.request.ProxyHandler(proxies = proxies)

opener = urllib.request.build_opener(handler)

response = opener.open(request)

content = response.read().decode(‘utf-8’)

with open(‘daili.html’,‘w’,encoding = ‘utf-8’) as fp:

fp.write(content)

此时我们对比一下之前的handler处理器的基础使用代码,发现只有一个地方发生了变化:

handler = urllib.request.HTTPHandler()  =>  handler = urllib.request.ProxyHandler(proxies = proxies)

这句代码换成了新的ProxyHandler对象后,我们才能把ip地址作为参数传入(proxies是ip地址的变量)

有了代理ip的基本使用方法,我们可以继续研究一下ip代理池

所谓代理池,就是很多的ip在一起的一个结构,在这个结构里,我们能够在每一次请求中使用不同的ip地址,从而减少同一个ip的使用频率,以降低ip被封掉的风险,对抗反爬机制!

下面展示了一个简易的代理池示例代码:

代理池的使用

import urllib.request

import random

proxies_pool = [

{ ‘http’ : ‘27.203.215.138:8060’ },

{ ‘http’: ‘40.83.102.86:80’ },

{‘http’: ‘14.215.212.37:9168’}

]

proxies = random.choice(proxies_pool)

url = ‘https://www.xxx.com’

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)

handler = urllib.request.ProxyHandler(proxies = proxies)

opener = urllib.request.build_opener(handler)

response = opener.open(request)

content = response.read().decode(‘utf-8’)

with open(‘dail2.html’,‘w’,encoding=‘utf-8’) as fp:

fp.write(content)

对比第一段代码,我们这里的区别在于ip地址有三个,组成了一个简单的代理池,我们通过random.choice(),从代理池这一字典对象随机一个ip地址而后传入handler对象的创建中,同上!🌟🌟🌟


🎯 urllib库的异常处理

在前面提到了python的异常处理,在爬虫中,urllib库的使用过程中会出现几种常见的错误如下:

try:

request = urllib.request.Request(url=url, headers=headers)

response = urllib.request.urlopen(request)

content = response.read().decode(‘utf-8’)

print(content)

except urllib.error.HTTPError:

print(‘系统正在升级…’)

except urllib.error.URLError:

print(‘都说了系统在升级…’)

1️⃣ 第一个错误是HTTPError,这是HTTP请求的错误,我们通过urllib.error.HTTPError这个类型进行匹配,捕捉后对错误进行处理即可,处理方式与之前的笔记介绍的方式相同。

2️⃣ 第二个错误是URLError,这是把url书写错误后的错误,我们通过urllib.error.URLError这个类型进行匹配,捕捉后同样处理错误。


II.II cookie的使用


🎯 什么是cookie?

首先,作为这部分的第一部分,先介绍一下什么是cookie:

Cookie 并不是它的原意“甜饼”的意思, 而是一个保存在客户机中的简单的文本文件, 这个文件与特定的 Web 文档关联在一起, 保存了该客户机访问这个Web 文档时的信息, 当客户机再次访问这个 Web 文档时这些信息可供该文档使用。由于“Cookie”具有可以保存在客户机上的神奇特性, 因此它可以帮助我们实现记录用户个人信息的功能, 而这一切都不必使用复杂的CGI等程序 。

举例来说, 一个 Web 站点可能会为每一个访问者产生一个唯一的ID, 然后以 Cookie 文件的形式保存在每个用户的机器上。如果使用浏览器访问 Web, 会看到所有保存在硬盘上的 Cookie。在这个文件夹里每一个文件都是一个由“名/值”对组成的文本文件,另外还有一个文件保存有所有对应的 Web 站点的信息。在这里的每个 Cookie 文件都是一个简单而又普通的文本文件。透过文件名, 就可以看到是哪个 Web 站点在机器上放置了Cookie(当然站点信息在文件里也有保存)

这是某度对cookie的介绍和我对cookie的理解,用一句话总结就是cookie是携带了用户信息的标识,由于我们的HTTP协议是没有记忆的,通过cookie就能够将用户进行点对点的识别。当你进入某个网站并登录后,关闭网站再次进入,如果不需要再次登录而是直接进入登录状态,那么这个网站就是使用了cookie技术


🎯 利用cookie绕过登录

这是我们的重点:利用cookie绕过登录。

需要这么做的原因在于当使用爬虫爬取一些网页时,这些网页对应的网站会将我们对于某个页面请求重定向到网站的登录页面,也就是这样的一个逻辑顺序

假设我们要爬取页面A,该网站的登录页面是页面B,当我们遇到会重定向到登录页面进行反爬的网站时,会出现请求A  - - - >  返回B 的效果,但是我们需要的效果是:请求A  - - - >  返回A,此时就需要cookie绕过登录的操作:

数据的采集时,绕过登录,进入某个页面,这是cookie登录

import urllib.request

url = ‘https://xxx’

headers = {

cookie中携带着登录信息,如果有登陆之后的cookie,那我们可以携带者cookie进入到任何页面

‘cookie’: ‘xxx’,

referer 判断当前路径是不是由referer链接进来的 如果不是从这个链接进入,则不可访问

‘referer’: ‘https://xxx’,

‘user-agent’: ‘Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36’,

}

request = urllib.request.Request(url = url,headers = headers)

response = urllib.request.urlopen(request)

content = response.read().decode(‘utf-8’)

保存本地

with open(‘xxx.html’,‘w’,encoding=‘utf-8’)as fp:

fp.write(content)

cookie的具体值可以通过F12检查网络源代码后获取:按F12 - - - > 选择 Network - - - > Headers - - - > cookie,我以一个网站为例:

最后简单介绍一下参数referer,这个参数的含义是源url,也就是通过这个源url,我们进入了这个目标页面,因此很多的网站会通过referer这个源url参数来进行一个反爬判定,我们可以添加referer这个参数在headers里,作为对抗这一机制的方法!🌟🌟🌟


II.III requests库的学习


🎯 requests库的介绍与安装

首先,了解一下什么是requests库:

它是一个Python第三方库,处理URL资源特别方便,可以完全取代之前学习的urllib库,并且更加精简代码量(相较于urllib库)。

那么话不多说,我们安装一下:

1️⃣ 首先,我们依旧是打开pycharm,查看一下自己的python解释器的安装位置File - - - > Settings - - - > Project - - - > Python Interpreter


2️⃣ 进入python解释器安装目录下打开终端: Win + R,输入cmd ,回车,之后输入指令 cd,把Scripts文件夹拖入cd后的光标中并执行切换:


3️⃣ 输入安装指令并执行:

pip install requests


🎯 requests库的基本语法

接下来,介绍requests的基本语法,与urllib库类似,requests库的语法大致分为一种类型与六种属性:

首先回忆一下urllib库,在urllib库中,我们通过测试发现,它获取的服务器响应是HTTPResponse的类型,而requests库获取的服务器响应是requests.models.Response的类型。

然后我们用requests库模拟浏览器,向服务器发起一次普通的请求,这次请求只是为了辅助下面的六种属性:

import requests

url = ‘http://www.xxx.com’

response = requests.get(url = url)

用requests库时,我们发起请求是通过requests.get()函数进行的,传参是目的网页的url(后续会有其他的传参,暂时此处传入一个url),并且用response变量接受服务器的响应

接下来是requests库的六种属性

1️⃣ text属性:字符串形式返回网页源码(由于此时编码格式是gbk,中文部分可能会乱码,稍后解决)

(1) text属性:以字符串形式返回网页源码

print(response.text) # 由于没有设置编码格式,中文会乱码


2️⃣ **encoding属性:**设置相应的编码格式

(2) encoding属性:设置相应的编码格式:

response.encoding = ‘utf-8’

这之后的response就不会出现中文乱码现象了。


3️⃣ url属性:返回url地址

(3) url属性:返回url地址

url = response.url


4️⃣ content属性:返回二进制的数据

(4) content属性:返回二进制的数据

content_binary = response.content


5️⃣ status_code属性:返回状态码 200是正常

(5) status_code属性:返回状态码 200是正常

status_code = response.status_code


6️⃣ headers属性:返回响应头

(6) headers属性:返回响应头

headers = response.headers


🎯 requests库的GET请求

requests库的get请求的示例代码如下:

import requests

url = ‘https://www.xxx.com’

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’

}

data = {

‘data’ : ‘data’

}

三个参数:

url:请求路径

params:请求参数

kwargs:字典

不需要请求对象的定制

参数使用params进行传递

参数无需编码

同时不需要请求对象定制

请求路径的?字符可以加也可以省略

response = requests.get(url = url,params = data,headers = headers)

response.encoding = ‘utf-8’

content = response.text

print(content)

从上面可以看出来,requests最省代码的地方在于,它不需要进行请求对象的定制,如果换成urllib库,我们需要先封装一个request请求对象而后把这个对象传入urllib.request.urlopen()函数中,而在requests库中,我们只需要把三个参数,即url、data和headers传入即可完成get请求,十分方便!(上面的代码执行的是在百度中搜索‘跳探戈的小龙虾’返回的网页源码)


🎯 requests库的POST请求

接下来是requests库的post请求

requests_post请求

import requests

url = ‘https://www.com’

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’

}

data = {

‘data’ : ‘xxx’

}

四个参数:

url:请求路径

data:请求参数

json数据

kwargs:字典

response = requests.post(url = url,data = data,headers = headers)

content = response.text

import json

obj = json.loads(content.encode(‘utf-8’))

print(obj)

如果说get请求requests库只比urllib库简单一点点的话,那么post请求绝对是requests库更加便捷,它不仅省去的请求对象的定制,而且省略了参数的编码和转码的操作,可以说非常方便只需要和get请求一样把三个参数url、data和headers传入即可,因此post请求个人强烈推荐用requests库代替urllib库


🎯 requests库的代理ip方法

最后介绍一下requests使用代理ip的方式,它又简化了urllib库,回忆urllib库代理ip,我们需要创建handler处理器,还要定义opener对象,但requests库中,我们只需要把代理ip作为一个普通的参数,传入requests.get()/requests.post()函数即可(简直太方便了!)

requests_ip代理

import requests

url = ‘http://www.baidu.com/s’

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’

}

data = {

‘wd’ : ‘ip’

}

proxy = {

‘http:’ : ‘218.14.108.53’

}

response = requests.get(url = url, params = data,headers = headers,proxies = proxy)

content = response.text


🎯 requests库小结

最后,简单总结一下requests库,首先对于requests库,不再是六种方法,而是有六个属性;其次是对于get请求和post请求,requests库都不再需要请求对象的定制,而且post请求不再需要编解码操作;最后对于ip代理,不需要定义一些中间对象,直接传入代理ip,作为一个普通参数即可。同时,我们的requests.get()/requests.post()函数,能够传入四个参数:url、data、headers、ip代理。🌟🌟🌟


II.IV 爬虫解析方法之xpath解析


🎯 xpath的安装

在第一部分安装的介绍之前,先介绍一下什么是xpath,以及为什么我们要学习xpath:

xpath是一门在XML文档中查找信息的语言。xpath可用来在XML文档中对元素和属性进行遍历。

通俗的说,xpath可以用来精确的定位和切割某个标签,标签指的是我们的html文件的源码中的标签,例如

、 这些标签。

那么这个和我们的爬虫有什么关系呢?在之前的笔记中,我们大体上只获得过页面的源代码,这很大程度是不够的,我们需要的是精确的信息,这些信息就需要从混乱的源码中提取出来,而xpath就提供了这样的一种方法。总结,我们用xpath来精确提取html源码中的信息

下面我们进行xpath的安装:

1️⃣ 在python的解释器所在的文件目录中Script文件夹内安装lxml库:

lxml库包含了我们需要的xpath,因此我们需要先安装lxml库,这个库要怎么安装呢,这里提供了详细的步骤:

首先,我们打开pycharm,选中File - - - > setting:

打开后,选择Project - - - > Python Interpreter:

之后能够看到python interpreter 的路径,我们可以选择进入这个路径也可以稍后手打路径我这边推荐我们先进入这个路径对应的文件,也即我们进入Python38文件夹

之后我们打开终端(Win + R,而后输入cmd),并输入指令:cd

之后我们不必手打后面的路径,而是可以把Scripts文件拖动到cd的光标后(cd后面要留一个空格!) :

拖动后,路径会被自动输入,我们回车确认即可。而后我们通过终端进入了Scripts文件夹,之后我们输入这句指令安装lxml库

pip install lxml -i https://pypi.douban,com/simple

安装后,我们就可以在pycharm中导入lxml库中的xpath了,导入xpath的代码是这样的

from lxml import etree


2️⃣ 接下来我们安装浏览器插件:xpath插件:

针对谷歌浏览器的朋友,打开自己的扩展程序:

而后保持扩展程序被打开的状态,我们下载xpath的zip文件(提取码:dxzj):

点击链接下载xpath

下载后,不要解压zip,而是把这个zip文件拖入我们刚才打开的扩展程序页面,之后xpath插件就会被自动安装在浏览器上了


🎯 xpath的基本语法

xpath的基本语法,都展示在了下面的示例代码中,这些语法与正则表达式很类似:

解析:xpath的基础使用

from lxml import etree

xpath解析

1. 本地文件:etree.parse

2. 解析服务器响应的数据 response.read().decode(‘utf-8’) ***** etree.HTML()

xpath解析本地文件

tree = etree.parse(‘new.html’)

查找ul下面的li

li_list = tree.xpath(‘//body//li’)

判断列表的长度:length

print(li_list)

print(len(li_list))

查找带有id属性的li标签

li_list = tree.xpath(‘//ul/li[@id]’)

print(li_list)

print(len(li_list))

获取标签的内容:text()

li_list = tree.xpath(‘//ul/li[@id]/text()’)

print(li_list)

print(len(li_list))

获取指定id的标签,属性值id要加引号

li_list = tree.xpath(‘//ul/li[@id = “l1”]/text()’)

print(li_list)

查找指定id的标签的class属性值

li_list = tree.xpath(‘//ul/li[@id = “l1”]/@class’)

print(li_list)

模糊查询:

(1) id中含有l的li标签

li_list = tree.xpath(‘//ul/li[contains(@id,“l”)]/text()’)

print(li_list)

(2) id的值以l开头的li标签

li_list = tree.xpath(‘//ul/li[starts-with(@id,“c”)]/text()’)

print(li_list)

逻辑运算:

(1) 查询id为l1和class为c1的标签:

li_list = tree.xpath(‘//ul/li[@id = “l1” and @ class = “c1”]/text()’)

print(li_list)

(2) 查询id为l1或l2的标签:

li_list = tree.xpath(‘//ul/li[@id = “l1”]/text() | //ul/li[@id = “l2”]/text()’)

print(li_list)

xpath解析服务器响应文件:从某网站html文件中提取内容

(1) 获取源码

import urllib.request

url = “https://xxx.com”

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) xpath解析服务器响应的文件

from lxml import etree

解析服务器响应的文件的核心操作:

tree = etree.HTML(content)

注意xpath的返回数据类型是列表,我们可以用索引值:

result = tree.xpath(‘//input[@id = “su”]/@value’)[0]

print(result)

最后强调一下,xpath既可以处理本地html文件,也可以处理服务器的响应html文件,这是它的一个特性,这个特性在后面其他的提取技术(jsonpath)中可能不具备!🌟🌟🌟


II.V 爬虫解析方法之jsonpath解析


🎯 jsonpath的介绍

首先介绍一下jsonpath是什么:

jsonpath是一种简单的方法来提取给定JSON文档的部分内容。

那么我们为什么要学习jsonpath?原因其实很简单,因为有时候我们拿到的数据是以json为格式的数据,此时我们不再能够使用之前学习的xpath对内容进行解析,因此我们需要一种方法来解析json格式的数据,它就是jsonpath


🎯 jsonpath的安装

在语法介绍之前,先安装一下jsonpath库:

安装的方法是这样的:

1️⃣ 首先,我们打开pycharm,选中File - - - > setting

之后选择 Project:xxxx - - - > Python Interpreter

最后按照图中位置,找到自己的python的安装地址,并且进入改地址。


2️⃣ 之后,在地址所示的这个位置,我们按 Win + R调出终端框,并输入 cd,之后路径还是用拖拽法把Scripts文件夹拖进cd光标后(要在cd后面间隔一个空格):


3️⃣ 最后,在终端框输入下面的指令,安装jsonpath:

pip install jsonpath


🎯 jsonpath的基础语法介绍

介绍语法之前,先强调一点,那就jsonpath只能处理本地的json文件,不能直接处理服务器的响应,这是它与xpath的第二点区别(第一点是处理的对象不同)。

然后我们先以下面这个json源码为例子,进行语法介绍:

{

“store”: {

“book”: [

{

“category”: “reference”,

“author”: “Nigel Rees”,

“title”: “Sayings of the Century”,

“price”: 8.95

},

{

“category”: “fiction”,

“author”: “Evelyn Waugh”,

“title”: “Sword of Honour”,

“price”: 12.99

},

{

“category”: “fiction”,

“author”: “Herman Melville”,

“title”: “Moby Dick”,

“isbn”: “0-553-21311-3”,

“price”: 8.99

},

{

“category”: “fiction”,

“author”: “J. R. R. Tolkien”,

“title”: “The Lord of the Rings”,

“isbn”: “0-395-19395-8”,

“price”: 22.99

}

],

“bicycle”: {

“author”: “Tony”,

“color”: “red”,

“price”: 19.95

}

},

“expensive”: 10

}

新建一个json文件,把上面的代码拷贝进去,并命名文件,我这里命名为store.json。(或者直接点击这里下载:store.json,提取码:yrso)

1️⃣ 读取一个json文件:

首先介绍如何读入一个json文件,它的语法格式是这样的:

import json

import jsonpath

注意,默认打开文件的格式是gbk,但json.load()返回的的对象格式要求编码为utf-8,

因此我们要强制编码为utf-8

obj = json.load(open(‘store.json’,‘r’,encoding = ‘utf-8’))

这里要注意,我们调用函数之前,要先导入json库和jsonpath库;此外,我们通过json.load()函数导入我们的json文件这个函数的传参不是文件名,而是一个文件对象

这里多解释一下,也就是说,我们传参是:json.load(文件对象)而不是json.load(‘store.json’),后者是一个字符串,会报错,至于这个文件对象,我们可以直接用open()函数创建,也可以在外面先用open函数新建一个文件对象,之后将对象传入,二者均可


2️⃣ 解析json文件:

导入后,我们开始学习jsonpath的语法,首先我们参考下表,对照一下jsonpath的语法与xpath:

XPathJSONPath描述
/$根元素
.@当前元素
/. or []当前元素的子元素
..n/a当前元素的父元素
//..当前元素的子孙元素
**通配符
@n/a属性的访问字符

注意,第一行的/是根元素的意思,也就是说在jsonpath中,每一句jsonpath语言都要以一个$符号开头,后面的部分按照上面与xpath对照进行理解即可。(n/a表示该项不存在)

基于上面的表格,我们能够对前面提到的store.json做如下的实战演练,加强对jsonpath使用的理解:

import json

import jsonpath

注意,默认打开文件的格式是gbk,但json.load()返回的的对象格式要求编码为utf-8,

因此我们要强制编码为utf-8

obj = json.load(open(‘store.json’,‘r’,encoding = ‘utf-8’))

解析书店所有书的作者

book_author_list = jsonpath.jsonpath(obj,‘$.store.book[*].author’)

print(book_author_list)

可以用索引值标注第几本书:

author = jsonpath.jsonpath(obj,‘$.store.book[1].author’)

print(author)

所有的作者,包括自行车

author_list = jsonpath.jsonpath(obj,‘$…author’)

print(author_list)

store下面所有的元素

tag_list = jsonpath.jsonpath(obj,‘$.store.*’)

print(tag_list)

store下面所有的price

price_list = jsonpath.jsonpath(obj,‘$.store…price’)

print(price_list)

第三个书

book = jsonpath.jsonpath(obj,‘$.store.book[2]’) # 也可以写作 $…book[2]

print(book)

最后一本书

@相当于this,指代当前的每一个对象

@.length表示当前的json的字典长度

last_book = jsonpath.jsonpath(obj,‘$…book[(@.length-1)]’)

print(last_book)

前两本书

用切片思维:

book_list = jsonpath.jsonpath(obj,‘$…book[0,1]’)

另一种写法:

book_list = jsonpath.jsonpath(obj,‘$…book[:2]’)

过滤包含版本号isbn的书:

条件过滤需要在圆括号前面添加一个问号

book_list = jsonpath.jsonpath(obj,‘$…book[?(@.isbn)]’)

print(book_list)

过滤超过十元的书

book_list = jsonpath.jsonpath(obj,‘$…book[?(@.price > 10)]’)

print(book_list)


II.VI 爬虫解析方法之bs4解析


🎯 bs4的介绍

首先,介绍一下bs4,它是又一种解析的手段,之前有xpath和jsonpath。bs4的特点是这样的:

BS4全称是Beatiful Soup,它提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。

bs4最舒服的一点是提供了更适合前端开发工作者使用的语言习惯,它的语法很大程度对前端开发工作者是友好的,同时它解析的对象是本地html文件和服务器的响应html文件


🎯 bs4的安装

接下来,我们安装一下bs4

1️⃣ 首先,我们打开pycharm,选中File - - - > setting

之后选择 Project:xxxx - - - > Python Interpreter

最后按照图中位置,找到自己的python的安装地址,并且进入该地址:


2️⃣ 之后,在地址所示的这个位置,我们按 Win + R,调出终端框,并输入 cd,之后路径还是用拖拽法把Scripts文件夹拖进cd光标后(要在cd后面间隔一个空格)

3️⃣ 最后,在终端框输入下面的指令,安装jsonpath:

pip install bs4


🎯 bs4的基本语法使用

前面提到bs4可以解析本地和服务器响应html文件,为了方便介绍bs4的基本语法,我们以本地的html为例,下面是本地html的源码:

soupDemo
    • 张三
    • 李四
    • 王五
    • 周六
    • soupDemo

      hhh

      soupDemo2

      把这个文件命名为soup.html,后面以这个名字作为读入的名称。

      1️⃣ 导入本地html文件:

      from bs4 import BeautifulSoup

      解析本地文件:bs4基础语法的学习

      soup = BeautifulSoup(open(‘soup.html’,encoding = ‘utf-8’),‘lxml’)

      这部分首先肯定要导入bs4,导入的格式是 from bs4 import BeautifulSoup,之后我们把本地的html文件读入即可。之前新建的soup.html文件最好放在与当前的python项目文件同级目录下方便我们进行路径的输入

      bs4读入本地文件的格式与jsonpath基本上相同,它传入两个参数(比jsonpath多了一个):一个是文件对象一个是字符串’lxml’前者是一个变量,后者是一个字符串’lxml’,固定的,我们只需要每一次更改文件对象即可操作不同的文件


      2️⃣ bs4的基本操作语法:

      from bs4 import BeautifulSoup

      解析本地文件:bs4基础语法的学习

      soup = BeautifulSoup(open(‘soup.html’,encoding = ‘utf-8’),‘lxml’)

      bs4的基础操作:

      (1) 根据标签名查找节点,找到的是第一个符合条件的节点:

      print(soup.a) # 返回的是soupDemo而不是soupDemo2

      (2) 获取标签的属性:

      print(soup.a.attrs)

      上面是两个bs4的基础语法,获取标签元素和标签元素的属性,其中属性那一项指的是标签的所有属性,都会被打印出来。另外注意一下,它获取的是第一个符合条件的节点,而不是所有符合条件的节点!(这里的标签就是指的是h5的标签)


      3️⃣ bs4常用的六个函数介绍:

      from bs4 import BeautifulSoup

      解析本地文件:bs4基础语法的学习

      soup = BeautifulSoup(open(‘soup.html’,encoding = ‘utf-8’),‘lxml’)

      bs4的常见函数:

      (1) find()

      返回的是第一个符合条件的节点(数据)

      print(soup.find(‘a’)) # 返回的是soupDemo而不是soupDemo2

      find()还可以根据标签的属性值查找符合条件的节点,

      例如下面通过title属性值查找:

      print(soup.find(‘a’,title = ‘s2’))

      class属性也可以被查找,但是注意class本身是python的关键字

      因此我们要加一个下划线:class_

      print(soup.find(‘a’,class_ = “a1”))

      (2) find_all() :返回结果是一个列表,包含了所有目标标签(这里是a标签)

      print(soup.find_all(‘a’))

      如果想要多标签的数据,需要在find_all中传入列表对象,如下例:[‘a’,‘span’]

      print(soup.find_all([‘a’,‘span’]))

      如果想要限制返回的标签数量,可以加一个limit,它的值表示查找前n个数据

      print(soup.find_all(‘li’,limit = 2)) # 查找前两个数据

      (3) select() (推荐)

      select()返回一个列表,同时和find_all一样返回所有的目标标签

      print(soup.select(‘a’))

      类选择器(在前端的一种叫法):可以通过加一个 .类名 来筛选class

      print(soup.select(‘.s1’))

      id选择器(也是前端的一种叫法):可以通过加一个 #id名 来筛选id

      print(soup.select(‘#s2’))

      属性选择器:可以通过属性存在与否、属性的具体值来筛选

      print(soup.select(‘li[id]’)) # 这表示查找所有的 li标签 中含有 id 的标签li

      print(soup.select(‘li[id = “l2”]’)) # 这表示查找所有的 li标签 中含有 id 且id的值为l2的标签li

      层级选择器:

      a.后代选择器:一个空格,查找某个标签的后代,包括儿子、孙子标签

      print(soup.select(‘div li’))

      b.子代选择器:一个大于号,只能查找某个标签的儿子标签,不包括孙子标签

      print(soup.select(‘div > ul > li’)) # 这里写 div > li,则没有内容返回,因为li是div的孙子标签而非子标签

      多个标签都拿到:

      在select()中,我们无需用列表的传参表示多个标签,直接以逗号隔开多个标签即可:

      print(soup.select(‘a,li’))

      (4) 获取节点具体的信息的函数

      a.获取节点的内容

      注意要加一个索引,因为我们的select会返回一个列表,不加索引,就无法处理成字符串

      obj = soup.select(‘#s2’)[0]

      如果标签对象中只有内容,那么string和 get_text()都可以使用

      但是如果标签对象中有内容也有标签,那么string就无法使用,只能用get_text()

      print(obj.get_text())

      b.获取某个具体的节点(标签)的属性

      首先获取id值是s2的标签

      tag = soup.select(‘#s2’)[0]

      返回这个标签的名字,例如a标签,就返回一个a

      print(tag.name)

      将所有的标签属性以字典的格式返回

      print(tag.attrs)

      获取某个节点的具体某一个属性,原理是可以根据attrs的字典对象特点,

      用字典对象的get函数,传入键,来获取某一个键值对的值

      print(tag.attrs.get(‘title’)) # 获取id值是s2的标签的title属性

      关于最后一条,补充一下,就是说tag.attrs会返回一个字典,这个字典是该标签所有的属性,那么我们需要其中一个属性,可以用字典的一个方法get()传入键,获得对应的值,这是一个键值对的关系!🌟🌟🌟


      🎯 bs4处理服务器响应文件

      最后,我们学习一下如何用bs4处理服务器响应文件

      from bs4 import BeautifulSoup

      soup = BeautifulSoup(content,‘lxml’)

      服务器的响应应当用上述的格式进行书写:使用Beautifulsoup()函数,传入两个参数,第一个参数是服务器的响应的内容第二个参数是’lxml’这个固定的参数


      II.VII selenium库的介绍


      🎯 selenium库的安装及相关浏览器工具的下载

      首先,我们介绍一下什么是selenium库:

      selenium是一个自动化测试工具,支持Firefox,Chrome等众多浏览器 在爬虫中的应用主要是用来解决JS渲染的问题。

      那我们能用selenium做些什么呢:

      1️⃣ 爬虫,selenium能够模拟真人打开浏览器,因此可以更好的获取我们需要的数据。(有时候,使用urllib库模拟浏览器的时候,会被服务器识别,返回的数据有所缺失,因此我们的确需要selenium做爬虫)

      2️⃣ 自动化小工具,例如可以帮我们操作一些浏览器的交互等等。


      下面我们介绍一下selenium库以及相关的浏览器工具的安装方法

      首先,我们安装selenium库:

      1️⃣ 打开pycharm,选择 File - - - > Settings

      之后我们点击 Project - - -> Python Interpreter,查看我们python解释器的位置,进入这个位置。


      2️⃣ 进入python解释器安装的位置后,我们 按 Win + R,输入cmd,调出终端

      之后我们在终端输入:cd,并把左侧的Scripts 文件夹拖入cd后的光标中(空一格空格),并执行这指令:

      此时我们的终端已经进入了Scripts文件夹中。


      3️⃣ 执行安装指令:

      pip install selenium==3.4

      这里注意一下,我们的指令是安装3.4版本的selenium,大家不要省略 == 及之后的部分,否则安装是selenium可能因为版本问题影响后面的语法和操作


      自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

      深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

      因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

      img

      img

      img

      img

      img

      img

      既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

      由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

      如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)

      条件的节点**!(这里的标签就是指的是h5的标签)


      3️⃣ bs4常用的六个函数介绍:

      from bs4 import BeautifulSoup

      解析本地文件:bs4基础语法的学习

      soup = BeautifulSoup(open(‘soup.html’,encoding = ‘utf-8’),‘lxml’)

      bs4的常见函数:

      (1) find()

      返回的是第一个符合条件的节点(数据)

      print(soup.find(‘a’)) # 返回的是soupDemo而不是soupDemo2

      find()还可以根据标签的属性值查找符合条件的节点,

      例如下面通过title属性值查找:

      print(soup.find(‘a’,title = ‘s2’))

      class属性也可以被查找,但是注意class本身是python的关键字

      因此我们要加一个下划线:class_

      print(soup.find(‘a’,class_ = “a1”))

      (2) find_all() :返回结果是一个列表,包含了所有目标标签(这里是a标签)

      print(soup.find_all(‘a’))

      如果想要多标签的数据,需要在find_all中传入列表对象,如下例:[‘a’,‘span’]

      print(soup.find_all([‘a’,‘span’]))

      如果想要限制返回的标签数量,可以加一个limit,它的值表示查找前n个数据

      print(soup.find_all(‘li’,limit = 2)) # 查找前两个数据

      (3) select() (推荐)

      select()返回一个列表,同时和find_all一样返回所有的目标标签

      print(soup.select(‘a’))

      类选择器(在前端的一种叫法):可以通过加一个 .类名 来筛选class

      print(soup.select(‘.s1’))

      id选择器(也是前端的一种叫法):可以通过加一个 #id名 来筛选id

      print(soup.select(‘#s2’))

      属性选择器:可以通过属性存在与否、属性的具体值来筛选

      print(soup.select(‘li[id]’)) # 这表示查找所有的 li标签 中含有 id 的标签li

      print(soup.select(‘li[id = “l2”]’)) # 这表示查找所有的 li标签 中含有 id 且id的值为l2的标签li

      层级选择器:

      a.后代选择器:一个空格,查找某个标签的后代,包括儿子、孙子标签

      print(soup.select(‘div li’))

      b.子代选择器:一个大于号,只能查找某个标签的儿子标签,不包括孙子标签

      print(soup.select(‘div > ul > li’)) # 这里写 div > li,则没有内容返回,因为li是div的孙子标签而非子标签

      多个标签都拿到:

      在select()中,我们无需用列表的传参表示多个标签,直接以逗号隔开多个标签即可:

      print(soup.select(‘a,li’))

      (4) 获取节点具体的信息的函数

      a.获取节点的内容

      注意要加一个索引,因为我们的select会返回一个列表,不加索引,就无法处理成字符串

      obj = soup.select(‘#s2’)[0]

      如果标签对象中只有内容,那么string和 get_text()都可以使用

      但是如果标签对象中有内容也有标签,那么string就无法使用,只能用get_text()

      print(obj.get_text())

      b.获取某个具体的节点(标签)的属性

      首先获取id值是s2的标签

      tag = soup.select(‘#s2’)[0]

      返回这个标签的名字,例如a标签,就返回一个a

      print(tag.name)

      将所有的标签属性以字典的格式返回

      print(tag.attrs)

      获取某个节点的具体某一个属性,原理是可以根据attrs的字典对象特点,

      用字典对象的get函数,传入键,来获取某一个键值对的值

      print(tag.attrs.get(‘title’)) # 获取id值是s2的标签的title属性

      关于最后一条,补充一下,就是说tag.attrs会返回一个字典,这个字典是该标签所有的属性,那么我们需要其中一个属性,可以用字典的一个方法get()传入键,获得对应的值,这是一个键值对的关系!🌟🌟🌟


      🎯 bs4处理服务器响应文件

      最后,我们学习一下如何用bs4处理服务器响应文件

      from bs4 import BeautifulSoup

      soup = BeautifulSoup(content,‘lxml’)

      服务器的响应应当用上述的格式进行书写:使用Beautifulsoup()函数,传入两个参数,第一个参数是服务器的响应的内容第二个参数是’lxml’这个固定的参数


      II.VII selenium库的介绍


      🎯 selenium库的安装及相关浏览器工具的下载

      首先,我们介绍一下什么是selenium库:

      selenium是一个自动化测试工具,支持Firefox,Chrome等众多浏览器 在爬虫中的应用主要是用来解决JS渲染的问题。

      那我们能用selenium做些什么呢:

      1️⃣ 爬虫,selenium能够模拟真人打开浏览器,因此可以更好的获取我们需要的数据。(有时候,使用urllib库模拟浏览器的时候,会被服务器识别,返回的数据有所缺失,因此我们的确需要selenium做爬虫)

      2️⃣ 自动化小工具,例如可以帮我们操作一些浏览器的交互等等。


      下面我们介绍一下selenium库以及相关的浏览器工具的安装方法

      首先,我们安装selenium库:

      1️⃣ 打开pycharm,选择 File - - - > Settings

      之后我们点击 Project - - -> Python Interpreter,查看我们python解释器的位置,进入这个位置。


      2️⃣ 进入python解释器安装的位置后,我们 按 Win + R,输入cmd,调出终端

      之后我们在终端输入:cd,并把左侧的Scripts 文件夹拖入cd后的光标中(空一格空格),并执行这指令:

      此时我们的终端已经进入了Scripts文件夹中。


      3️⃣ 执行安装指令:

      pip install selenium==3.4

      这里注意一下,我们的指令是安装3.4版本的selenium,大家不要省略 == 及之后的部分,否则安装是selenium可能因为版本问题影响后面的语法和操作


      自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

      深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

      因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

      [外链图片转存中…(img-68ADiSrQ-1712646813307)]

      [外链图片转存中…(img-guqoRMOF-1712646813308)]

      img

      img

      img

      img

      既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

      由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

      如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)

      img
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值