一.python基础知识
1 python概述
1.1优点
1.开源,易于维护。
2.可移植。
3.易于使用,简单优雅。
4.广阔的标准库,功能强大。
5.可扩展,可嵌入。
1.2劣势
1.运行速度慢。(解释型语言,翻译为机器码耗时)
2.代码不能加密。(发布程序为源代码)
2 python语法
2.1注释
-
单行注释:
#这是一个单行注释
-
多行注释:
''' 这是一个多行注释 这是一个多行注释 '''
3 基础语句
3.1 输出print语句
print(“具体的字符”)
print(变量名)print(“xxxxx %变量类型缩写” %变量名)
#具体输出
print("具体的字符")
#变量输出
int a=10
print(a)
#格式化输出
print("输出%d具体字符"%a)
#连接符
print("具体字符","具体字符","具体字符",sep="分隔符(默认为空格)")
print("",end="")#直接连接后方字符串
print("",end="\t")#空格后链接后方字符串
print("",end="\n")#换行后链接后方字符串
格式符号 | 转换 |
---|---|
%c | 字符 |
%s | 通过str()字符串来格式化 |
%i | 有符号十进制整数 |
%d | 有符号十进制整数 |
%u | 无符号十进制整数 |
%o | 八进制整数 |
%x | 十六进制整数(小写字母) |
%X | 十六进制整数(大写字母) |
%e | 索引符号(小写’e’) |
%E | 索引符号(大写’E’) |
%f | 浮点实数 |
%g | %f和%e的简写 |
%G | %f和%E的简写 |
3.2 输入input语句
接受输入的变量名 = input("提示信息")
4 变量及类型
变量名可以是任意数据类型,在程序中用一个变量名表示
变量名必须有 大小写英文,数字,和下划线(_)组成
赋值(a=“ABC”)时,python解释器执行了两个操作:
- 在内存中创建了一个"ABC"的字符串
- 在内存中创建了一个名为a的变量,并把它指向了"ABC"
5 运算符
5.1 算数运算符
运算符 | 描述 |
---|---|
+ | 加-两个对象相加 |
- | 减-得到复数或是一个数减去另一个数 |
* | 乘-两个数相乘或是返回一个被重复若干次的字符串 |
/ | 除-X除以Y |
% | 取模-返回除法的余数 |
** | 幂-返回x的y次幂 |
// | 取整数- 向下取接近除数的整数 |
5.2 比较运算符
运算符 | 描述 |
---|---|
== | 等于-比较对象是否相等 |
!= | 不等于-比较两个对象是否不相等 |
> | 大于-返回X是否大于Y |
< | 小于-返回X是否小于Y(所有比较运算符返回1为真,返回0表示假) |
>= | 大于等于-返回X是否大于等于Y |
<= | 小于等于-返回X是否小于等于Y |
5.3 赋值运算符
运算符 | 描述 |
---|---|
= | 等于- a=1 |
+= | 加法赋值语句-“a+=b” = “a=a+b” |
-= | 减法赋值语句-“a-=b” = “a=a-b” |
*= | 乘法赋值语句-“a*=b” = “a=a*b” |
/= | 除法赋值语句-“a/=b” = “a=a/b” |
%= | 取模赋值语句-“a%=b” = “a=a%b” |
**= | 幂赋值语句-“a* *=b” = “a=a * *b” |
//= | 加法赋值语句-“a//=b” = “a=a//b” |
5.4 位运算符
运算符 | 描述 |
---|---|
& | 按位与运算符-参与运算的两个值相应位为1则结果为1,否则为0 |
| | 按位或运算符-参与运算的其中一个值为1,结果为1. |
^ | 按位异或运算符-当两相应的二进制位相异时,结果为1. |
~ | 按位取反运算符-对数据的每个二进制位取反,即把1变为0,把0变为1. |
<< | 左移动运算符-运算数的各二进制位全部左移若干位由"<<"指定移动的位数。 |
>> | 右移动运算符-运算数的各二进制位全部右移若干位由"<<"指定移动的位数。 |
5.5 逻辑运算符
运算符 | 描述 |
---|---|
and | 布尔"与"- |
or | 布尔"或"- |
not | 布尔"非"- |
5.6 成员运算符
运算符 | 描述 |
---|---|
in | 如果在指定数列中找到值返回true,否则返回falst |
not in | 如果在指定数列中没有找到值返回true,否则返回falst |
5.7 运算符的优先级
运算符 | 描述 |
---|---|
** | 指数(最高优先级) |
* / % // | 乘,除,取模,取整数 |
± | 加,减 |
>> << | 左移右移 |
& | 位(and) |
^ | | 位运算符 |
<= << >> >= | 比较运算符 |
<> == != | 等于运算符 |
= += -= *= /= %= **= | 赋值运算符 |
is is not | 身份运算符 |
in not in | 成员运算符 |
and or not | 逻辑运算符 |
6 条件判断语句
python 指定任何非0和非空值为true ,0或者None为falst
条件判断语句以缩进控制范围
if 判断语句:#缩进必须同级相同,要不不识别
执行语句1
elif 判断语句2:
执行语句2
else:
执行语句3
7 循环语句
7.1 for循环
for i in range(5):#从0开始五个数的数组
循环语句
for i in range(0,10,3):#从0开始到10为止,步进值为3
循环语句
a = ["1","2","3"]
for i in range(len(a))
print(i,a[i])
for i,x in enumerste(列表)
print(i,x) #枚举函数,i为索引,x为列表值
7.2 while循环
i = 0
while i < 5:
循环语句
i = i++
else:
循环语句
7.3循环控制 break continue pass
#break 退出循环语句
#continue 跳过当前循环
#pass 占位符
8 字符串,列表,元组,字典
8.1 字符串
python 中的字符串可以使用单引号,双引号和三引号括起来,使用反斜杠\转义特殊字符
python3源码文件默认以UTF-8编码,所有字符串都是unicode字符串
支持字符拼接,截取等多种运算
字符串中出现单引号和双引号时需要前加\转义
word = '字符串'
word1 = "字符串"
word2 = """
字符段落
"""
8.1.1 str[x,y,z]
str = "字符串"
print(str[x:y:z]) #@x为起始值,从零开始,y为结束值,不打印结束值,z为步进值。
8.1.2字符串连接
str1 = "字符串"
str2 = "字符串"
print(str1 + str2)
8.1.3字符串的常见操作
方法 | 描述 | 描述 |
---|---|---|
capitalize | 将字符串第一个字符转换为大写 | |
bytes.decode(encoding=“utf-8”,errors=“strict”) | Python3中没有decode方法,但是我们可以使用bytes对象的decode()方法来解码给定的bytes对象,这个bytes对象可以由str.encode()来编码返回。 | |
encode(encoding=“utf-8”,errors=“strict”) | 以encoding指定的编码格式编码字符串,如果出错默认报一个VaError的异常,除非errors指定的是’ignore’或者’replce’ | |
isalnum() | 如果字符串中至少有一个字符并且所有字符都是字母或者数字则返回True,否则返回Falst. | |
isalpha() | 如果字符串中至少有一个字符并且所有字符都是字母则返回True,否则返回Falst. | |
isnumeric() | 如果字符串中只包含数字字符,则返回True,否则返回Falst。 | |
isdigit() | 如果字符串中只包含数字字符,则返回True,否则返回Falst。 | |
join(分隔符) | 以指定字符串为分隔符,将所有元素合并为一个新的字符串。 | |
len(string) | 返回字符串的长度。 | |
lstrip() | 截掉字符串左边的空格或指定字符。 | |
rstrip() | 删除字符串末尾的空格 | |
split(str="",num=string.count(str)num=string.count(str)) | 以str为分隔符截取字符串,如果num有指定值则只截取num+1个字符串。 | |
8.2 列表(list)
列表可以完成大多数集合类的数据结构实现。列表中的元素的类型可以不相同,它支持数字,字符串,甚至可以包含列表(所谓嵌套)。
列表是写在方括号[]之间,用逗号分隔开的元素列表。
列表索引值以0为开始值,-1为末尾的开始位置。
列表可以使用+操作符进行拼接,使用*操作符进行重复。
支持 in count 方法
list = ["字符串",0,[]] #@可以存在混合类型
8.2.1 列表方法
方法 | 描述 | 备注 |
---|---|---|
append() | 在末尾添加元素 | list.append([1,2])-- list = [ 1 , 2 , [1 , 2]] |
extend() | 在末尾添加元素 | list.extend([3,4]) – list = [ 1 , 2 , 3 , 4] |
insert() | 在指定位置插入 | |
del 列表名 | 删除列表 | |
pop() | 弹出列表元素 | |
index() | 查询指定范围内是否存在 | |
count() | 查询某个元素出现几次 | |
reverse() | 反转排序 | |
sort() | 从小到大排序 | |
sort(reverse=True) | 从大到小排序 | |
remove() | 删除指定内容的元素 |
8.2.2 列表方法介绍
-
增:
list = [1,2] #在末尾追加元素 append()方法--列表名.append(要添加的字符) list.append("要增加的字符")
!!! list.append([1,2]) ---------- list = [ 1 , 2 , [1 , 2]]
#在末尾追加元素 extend()方法–列表名.extend(要追加的元素)
list.extend([元组元素,元组元素])
!!! list.extend([3,4]) ---------- list = [ 1 , 2 , 3 , 4]
#在指定位置插入 insert()方法–列表名.insert(要插入位置的下标,插入的元素)
list.insert(插入索引,插入元素)
2.删:
```python
list = [0,1,2,3]
#在指定位置删除元素 del方法--del 列表名[要删除元素的索引]
del list[索引]
#弹出最后一个元素 pop方法--列表名,pop()
list.pop()
#删除指定内容的元素 remove()方法--列表名.remove("要删除元素的具体内容")
list.remove("指定内容") #从前开始遍历,优先删除最前方的。
3.改:
list = [1,2,3]
#指定元素进行修改 无具体方法--列表名[修改元素索引] = "具体内容"
list[索引] = ""
4.查:
list = [1,2]
#查询指定元素是否在列表中 if判断-if 元素 in 列表:
if 1 in list:
反馈语句
#查询指定范围内是否存在 index()方法--列表名.index(指定元素,开始元素,结束元素) !!!左包含右不包含
list.index(指定元素,开始,结束(不包含)) #@存在返回索引,不存在报错
#查询某个元素出现几次 count()方法--列表名.count(元素具体值)
list.count("元素具体值")
5.排:
list = [1,2,3,4]
#反转排序 reverse()方法--列表名.reverse()
list.reverse() #@反转列表顺序
#从小到大排序 sort()方法--列表名.sort()
list.sort() #@从大到小排序
#从大到小排序 sort(reverse=True)方法--列表.sort(reverse=True)
list = sort(reverse=True) #@从大到小排序
8.2.3 列表的嵌套
list = [[1,2],[3,4],[5,6]]
列表名[索引][索引] list[索引][索引]
8.3 元组(tuple)
元组(Tuple)与列表相似,不同之处是元组中的元素不能修改。写在小括号中,元素之间用逗号隔开。
元组的元素不可变,但是可以包含可变对象,如列表
!!!
tuple = (0)
时,type(tuple
) 时int
型的,只有tuple = (0,)
时type(tuple)
时tuple
型的支持 in count 方法
8.3.1 元组方法
方法 | 描述 | 备注 |
---|---|---|
len() | 获取元组长度 | |
max() | 获取元组元素最大值 | |
min() | 获取元组元素最小值 | |
tuple() | 将其他类型对象转换为元组 | |
del 元组名 | 删除元组 | |
8.3.2 元组方法介绍
1.增:
tuple = (1,2,3,4)
#并不是在某一个上增加了,而是新建了。
tup2 = (元素)
tup1 =(元素)
tup = tup1 + tup2
2.删:
tuple = (1,2,3,4)
#删除整个元组 del 元组名
del tuple
3.查:
tuple = (1,2,3,4)
#查找具体元素 元组名[索引]
tuple[索引]
8.4 字典(dict)
字典时无序的对象的集合,使用键值对存储(key-value),具有极快的查找速度。
键(key)必须使用不可变的类型。
同一字典中,键(key)必须唯一。
8.4.1方法
方法 | 描述 | 备注 |
---|---|---|
len() | 获取字典长度 | |
max() | 获取最大key | |
min() | 获取最大value | |
dict() | 将其他类型转换为字典 dict( [ (1,2),(1,2) ] ) | |
get() | 查找指定键的值 | 未查找到不报错,可以设定默认值 |
keys() | 查找所有键 | |
values() | 查找所有值 | |
items() | 查找所有键值 | |
del 字典名 | 删除字典 | |
clear() | 清除字典 |
8.4.2字典的具体操作
1.查:
info = {"key":"value","key1":"value"}
#查找指定键的值 字典名["字典中具体的键"]
info["key"] #如果访问不存在的键会报错
#查找指定键的值 get()方法--字典名.get("字典中具体的键","如果未查询到,返回的值")
info.get("key") #如果不存在返回None
info.get("key","设定默认值") #如果不存在返回设定的值,如果找到默认值不发挥作用。
#查找所有键 keys()方法--字典名.keys()
info.keys() #返回所有键(列表)
#查找所有值 values()方法--字典名.values()
info.values() #返回所有值(列表)
#查找所有键值 items()方法--字典名.items()
info.items() #返回所有键值(列表)---[(键,值),(),()]
for key,value in 字典名,items():
print("key=%s,value=%s",%(key,value))
2.增:
info = {"key":"value","key1":"value"}
#增加新的键值对 字典名["键"] = 值
info["key2"] = "value"
3.删:
info = {"key":"value","key1":"value"}
#删除指定键值对。 del方法 --del 字典名["指定值"]
del info["key"] #删除整个键值对,删除后再访问报错。
del info #删除字典,再访问报错。
#清空字典 clear()方法 --字典名.clear()
info.clear()
4.改:
info = {"key":"value","key1":"value"}
#更改键对应的值 字典名["键"] = ”值“
info["key"] = "值"
8.5集合(set)
集合和字典类似,也是一组key的集合,但是不存在存储value。由于key不能重复,所以,再set中,没有重复的key。
set是无序的,重复元素再set中自动被过滤。
8.5.1方法
方法 | 描述 | 举例 |
---|---|---|
for循环 | 遍历集合 | |
update() | 更新集合 | 集合名.update(集合名) |
add() | 向集合中添加元素 | 集合名.add(元素) |
remove() | 移除集合中的元素 | 集合名.remove(元素) |
pop() | 弹出元素 | 集合名.pop(元素) |
clear() | 清除集合中的元素 | 集合名.clear() |
del | 删除集合 | del 集合名 |
len() | 获取集合长度 | 集合名.len() |
max() | 获取最大值 | 集合名.max() |
min() | 获取最小值 | 集合名.min() |
set() | 将其他类型转换为集合 | set() |
8.6 总结
类型 | 是否有序 | 是否可变 |
---|---|---|
列表[] | 有序 | 可变类型 |
元组() | 有序 | 不可变类型 |
字典{} | 无序 | key不可变,value可变 |
集合{} | 无序 | 可变类型(不可重复) |
9 转义字符
有些字符无法在语句中直接使用,需要转义后才能使用。
转义字符 | 描述 | |
---|---|---|
(在行尾时) | 续行符 | |
\\ | 反斜杠符号 | |
\’ | 单引号 | |
\" | 双引号 | |
\a | 响铃 | |
\b | 退格 | |
\000 | 空格 | |
\n | 换行 | |
\v | 纵向制表符 | |
\t | 横向制表符 | |
\r | 回车 | |
\f | 换页 | |
\oyy | 八进制数,yy代表字符,列如:\o12代表换行,其中o是字母 | 。 |
\xyy | 十六进制数,yy代表的字符,列如:\x0a代表换行。 | |
print("字符串")#@字符串中的\为转义字符,进行转义。
print(r"字符串")#@要打印的字符串前加 r 表示字符串其中转义\不进行转义,直接输出。
10 函数
10.1 概念
1.开发程序时,需要某块代码多次,但是为了提高编写效率以及代码的重用,所以把具有独立功能的代码块组织为一个小模块,这就是函数。
2.函数可以有多个return 但是只要执行一个return就算函数调用完成。
3.函数名不能重复。
4.带参函数,如果在定义时有形参,那么在调用时就应该传递参数
5.调用时,实参的个数和先后顺序应该和定义函数中的要求一致。
#不带参数
del 函数名():
函数体(pass)
#带参数
del 函数名(参数1,参数2):
函数体(pass)
#带返回值-------只有有return才有返回值
del 函数名(参数1,参数2):
函数体(pass)
return 参数
变量名 = 函数名() #接收单返回值
del 函数名(参数1,参数2):
函数体(pass)
return 参数,参数
变量名,变量名 = 函数名() #接收多个返回值
10.2 全局变量和局部变量
全局变量:在整体函数上声明的变量,可以在所有函数上使用。
局部变量:在函数体中声明的变量,只能在本函数上使用。
在函数中,全局变量和局部变量同名时,优先使用的是局部变量,要使用全局变量需要在声明之前加
global
关键字
a = 1 ##全局变量
del 函数名():
a = 2 ##局部变量,会被优先修改
print(a) ##结果为1
a = 1 ##全局变量
del 函数名():
global a = 2 ##声明使用全局变量
print(a) ##结果为2
11 文件
11.1 文件操作
1.打开
##打开指定路径,文件名的文件,使用设定的模式。
变量名1 = open("文件名","打开模式")
2.关闭
变量名1 = open("文件名","打开模式")
#关闭已经打开的文件。
变量名1.close()
3.读
变量名1 = open("文件名","打开模式")
#读取打开文件指定字符的内容 read()方法--打开文件的变量名.read(读取字符个数)
#read()方法开始定位在文件头,每执行一次向后移动指定字符。
变量名1.read(5) #读取五个字符
变量名1.read(5) #会继续往后读取5个字符,与上一句代码读取不相同 !!!!!!
#读取打开文件所有行的内容 readlines()方法--打开文件的变量名.readlines()
变量名1.readlines() #返回每行一个元素的列表
#读取打开文件指定行的内容 readline()方法--打开文件的变量名.readline()
#readline()方法开始定位在文件头,每执行一次向后移动指定行。
变量名1.readline() #返回每行一个元素的列表
4.文件重命名
引入os模块,使用os中的rename()进行文件重命名。
import os
#文件重命名 rename()方法--os.rename("需要修改的文件名","新的文件名")
os.rename("旧文件名","新文件名")
5.删除文件
引入os模块,使用os中的remove()进行文件删除。
import os
#文件删除 remove()方法--os.remove("要删除的文件名")
os.remove("要删除的文件名")
11.2打开模式
访问模式 | 说明 | 备注 |
---|---|---|
r | 以只读的方式打开文件。文件的指针将会放在文件的开头。这是默认的模式。 | 如果不存在文件会报错 |
w | 打开一个文件只用于写入。如果该文件已经存在则将其覆盖。如果该文件不存在,创建新文件。 | |
a | 打开一个文件用于追加,如果该文件已经存在,文件指针将会放在文件的结尾,也就是说,新的内容会被写到已有的内容之后,如果该文件不存在,创建新文件进行写入。 | |
rb | 以二进制格式打开一个文件用于只读,文件指针将会放在文件的开头。这是默认的模式。 | |
wb | 以二进制格式打开一个文件用于写入,文件的指针将会放在文件的开头。这是默认的模式。 | |
ab | 以二进制格式打开一个文件用于追加,文件指针将会放在文件的结尾,也就是说,新的内容会被写到已有的内容之后,如果该文件不存在,创建新文件进行写入。 | |
r+ | 打开一个文件用于读写,文件的指针将会放在文件的开头。 | |
w+ | 打开一个文件用于读写,如果该文件已经存在则将其覆盖。如果该文件不存在,创建新文件。 | |
a+ | 打开一个文件用于读写,如果文件存在,文件指针将会放到文件的结尾,文件打开时会是追加模式。如果文件不存在,创建新文件用于读写。 | |
rb+ | 以二进制格式打开一个文件用读写。文件指针将会放在文件开头。 | |
wb+ | 以二进制格式打开一个文件用于读写。如果该文件已经存在则将其覆盖,如果该文件不存在则创建新的文件。 | |
ab+ | 以二进制格式打开一个文件用于读写。如果文件已存在,文件指针将会放到文件的结尾。如果文件不存在,创建新的文件用于读写。 | |
12 异常
异常指的是在程序运行过程中发生的异常事件,通常是由外部问题(如硬件错误、输入错误)所导致的。在Java等面向对象的编程语言中异常属于对象。
捕获异常:try: #@可能出现异常的代码放在try中
处理异常:except 捕获异常类型: #@处理异常的代码放在except中
try 可以嵌套
异常处理的常用操作:
#捕获单个异常
try:
可能发生异常的代码块
except 可能发生的异常类型 :
若发生异常时执行的语句
#捕获多个异常
try:
可能发生异常的代码块
except (异常1,异常2): #将可能出现的异常填写在小括号中
若发生异常时执行的语句
#捕获多个异常
try:
可能发生异常的代码块
except (异常1,异常2)as result: #result 错误信息
若发生异常时执行的语句
print(result) #打印错误信息,错误信息以字符串形式被打印
#捕获通用异常
try:
可能发生异常的代码块
except Exception as result: # Exception可以承接任何异常,可以打印result错误信息,也可以不打印错误信息。
若发生异常时执行的语句
print(result)
#try------finally finally:后的代码不论异常是否发生,都会执行
try:
可能发生异常的代码块
except 可能发生的异常类型 :
若发生异常时执行的语句
finally:
不论是否异常都执行的代码
常用方法
random.randint(起始值,结束值) 随机生成int型数
二.爬虫基础知识
1爬虫简介
网络爬虫,是按照一定的规则,自动抓取互联网信息的程序或者脚本。由于互联网数据的多样性和资源的有限性,根据用户需求定向抓取相关网页并分析已成为如今主流的爬取政策。
爬虫本质:模拟浏览器打开网页,获取网页中我们想要的那部分数据。
在代码中第一行加入
#coding = utf-8
或者#—*— coding:utf-8 —*—
这样可以在代码中包含中文PYTHON 文件中可以加入main函数用于测试程序
if name == “main”:
2 基本流程
-
准备工作
通过浏览器查看分析目标网页,学习编程技术规范。
-
获取数据
通过HTML库向目标站点发起请求,请求可以包含额外的header等信息,如果服务器能正常响应,会得到一个Response,便是所要获取的页面内容
-
解析内容
得到内容可能是HTML,JSON等格式,可以使用页面解析库,正则表达式等进行解析,
-
保存数据
保存数据形式多样,可以保存为文本,也可以保存为数据库,或者保存为特定格式的文件。
2.1准备工作
2.1.1分析页面
借助charome开发工具来分析页面(F12),在Elements下找到需要的数据位置。
![](https://s3.ax1x.com/2021/02/22/y7ubLQ.png)
通过借助charome开发工具来分析页面(F12),在Network下要发送的数据。
![](https://s3.ax1x.com/2021/02/22/y7KleH.png)
2.1.2 编码规范
在代码中第一行加入
#coding = utf-8
或者#—*— coding:utf-8 —*—
这样可以在代码中包含中文。PYTHON 文件中可以加入main函数用于测试程序。
if __name__ == “__main__”:
#
添加注释进行代码说明。
2.1.3 模块引入
模块(module):用来从逻辑上组织的python 代码(变量,函数,类),本质上就是py文件,提高代码的可维护性。python使用import来导入模块。
# 导入指定模块
from 路径 import 模块名
#使用模块中的函数
模块名.函数名()
常用包:
from bs4 import beaufulSoup #网页解析,获取数据
import re #正则表达式,进行文字匹配
import urllib.request,urllib.error #指定url,获取网页数据
import xlwt #进行excel操作
import sqlite3 #进行SQLite数据库操作
2.2获取数据
python 一般用
urllib
库来获取数据
2.2.1 get请求
#引入urllib库中的request包
import urllib.request
#使用变量接受返回值 变量名 = urllib.request.urlopen("网址",timeout = 设定时间)
response = urllib.request.urlopen("http://www.baidu.com",timeout = 设定时间) #单位秒,超时报urllib.error.URLError错误
#打印网址源码 read()读取内容--decode('utf-8')解码
print(response.read().decode('utf-8'))
2.2.2 post请求
- 简单的请求方式
#引入urllib库中的request,parse包
import urllib.request,urllib.parse
#封装一个二进制数据 二进制变量名 = bytes(urllib.parse.urlencode({存储设定数据的字典}),encoding="utf-8")
data = bytes(urllib.parse.urlencoding({"键":"值"},{"键":"值"}),encoding="utf-8")
#使用变量接受返回值 变量名 = urllib.request.urlopen("网址",data = 二进制变量名)
response = urllib.request.urlopen("http://www.baidu.com",data = data)
#打印网址源码 read()读取内容--decode('utf-8')解码
print(response.read().decode('utf-8'))
- 稍微伪装的请求方式
#引入urllib库中的request,parse包
import urllib.request,urllib.parse
#封装一个二进制数据 二进制变量名 = bytes(urllib.parse.urlencode({存储设定数据的字典}),encoding="utf-8")
data = bytes(urllib.parse.urlencoding({"键":"值"},{"键":"值"}),encoding="utf-8")
#从网页上找到Request Header找到要使用的信息,以字典的方式封装
headers = {"User-Agent":"信息":"":""}
#使用urllib.request.Request()方法封装
封装变量 = urllib.request.Request(url="网址",data=data,headers=headers,mothon="POST")
#使用变量接受返回值 变量名 = urllib.request.urlopen(封装变量)
response = urllib.request.urlopen(req)
#打印网址源码 read()读取内容--decode('utf-8')解码
print(response.read().decode('utf-8'))
例子:
爬取bilibili排行榜源码:
import urllib.request,urllib.parse
try:
url="https://www.bilibili.com/v/popular/rank/all"
header = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36"} #用户代理,告诉指定网址使用机器具体信息(伪装,告诉网站本机器可以接受什么水平的文件内容)
#封装二进制对象
data = bytes(urllib.parse.urlencode({"awsl":"awsl"}),encoding="utf-8") ##此句无实际效果
#封装url对象
re = urllib.request.Request(url=url,headers=header)
#获取网页源码
res = urllib.request.urlopen(re,timeout=1)
#打印源码
print(res.read().decode("utf-8"))
except urllib.error.URLError as e:
print("访问超时")
2.3解析数据
#打开指定文件
file = open("要打开文件的路径","打开模式")
#读取文件内容
html = file.read()
#解析文件 BeautifulSoup(解析内容,"解析类型")
bs = BeautifulSoup(html,"html.parser")
#获取标签内容 解析完变量.标签
print(bs.a)
1.获得需求内容的标签
1.bs4.element.Tag 类型
标签及其内容
默认拿到第一个
file = open("要打开文件的路径","打开模式")
html = file.read()
bs = BeautifulSoup(html,"html.parser")
#获得标签与内容 解析完变量.标签
print(pyte(bs.a) #bs4.element.Tag 类型
2.bs4.element.NavigableString 类型
标签内容(字符串)
file = open("要打开文件的路径","打开模式")
html = file.read()
bs = BeautifulSoup(html,"html.parser")
#获得内容 解析完变量.标签.string
print(pyte(bs.a.string) #bs4.element.NavigableString 类型
3.bs4.NeautifulSoup 类型
整个文档
file = open("要打开文件的路径","打开模式")
html = file.read()
bs = BeautifulSoup(html,"html.parser")
#获得整个文档内容
print(pyte(bs)) #bs4.NeautifulSoup 类型
4.bs4.element.Commeny 类型
注释类型
当解析标签中存在注释时
一个特殊的bs4.element.NavigableString,输出内容不包含注释符号
file = open("要打开文件的路径","打开模式")
html = file.read()
bs = BeautifulSoup(html,"html.parser")
#获得标签内容 !!!第一个a标签中存在注释
print(pyte(bs.a.string)) #bs4.element.Commeny 类型
1.bs4遍历文档树
file = open("要打开文件的路径","打开模式")
html = file.read()
bs = BeautifulSoup(html,"html.parser")
#使用方法获得特定内容
print(bs.a.方法)
方法 | 描述 | 备注 |
---|---|---|
.children | 子节点,子孙节点 | 迭代器 |
.contents | 子节点,子孙节点 | 列表 |
.descendants | 所有子孙结点 | 迭代器 |
.parent | 直接父节点 | 列表 |
.parents | 祖先节点 | 迭代器 |
.next_sibling | 下一个兄弟节点 | 列表 |
.next_siblings | 下面的兄弟节点 | 迭代器 |
.previous_sibling | 上一个兄弟节点 | 列表 |
.previous_siblings | 下面的兄弟节点 | 迭代器 |
.next_element | 不分层次的前元素 | 列表 |
.next_elements | 不分层次的前所有元素 | 迭代器 |
.previous_element | 不分层次的后元素 | 列表 |
.previous_elements | 不分层次的后所有元素 | 迭代器 |
2.文档的搜索
find_all
字符串过滤:会查找与字符串完全匹配标签的内容
file = open("要打开文件的路径","打开模式")
html = file.read()
bs = BeautifulSoup(html,"html.parser")
#使用 find_all("查询字符串")方法获得特定标签的内容
list = bs.find_all("查询字符串")
print(list)
参数过滤:查找含有指定参数的内容
file = open("要打开文件的路径","打开模式")
html = file.read()
bs = BeautifulSoup(html,"html.parser")
#使用 find_all(参数="")
list = bs.find_all(id="指定") #list = bs.find_all(class_="指定")
print(list)
文本过滤
file = open("要打开文件的路径","打开模式")
html = file.read()
bs = BeautifulSoup(html,"html.parser")
#使用 find_all(text="")
list = bs.find_all(text="指定文本") ##可以使用正则表达式 list = bs.find_all( text=re.compile("正则表达式") )
print(list)
limit参数
file = open("要打开文件的路径","打开模式")
html = file.read()
bs = BeautifulSoup(html,"html.parser")
#使用 find_all("查询字符串",limit=次数) 方法获得特定数量标签的内容
list = bs.find_all("查询字符串",limit=3)
print(list)
2.获得标签内的内容
正则表达式
使用正则表达式中,被比较的字符串前加 r ,不用担心转义字符
使用search()方法来匹配内容
#引入正则表达式的库
import re
file = open("要打开文件的路径","打开模式")
html = file.read()
bs = BeautifulSoup(html,"html.parser")
#使用 find_all("查询字符串")方法获得特定内容 re.compile("指定字符串")
list = bs.find_all(re.compile("指定字符"))
pat = re.compile(正则表达式)
m = pat.search(html)
#简写:
m = re.search("正则表达式","检验字符串") #查询是否存在,存在位置
使用findall来匹配内容
#引入正则表达式的库
import re
#re.fandall("正则表达式","检验的字符串")
print( re.fandall("正则表达式","检验的字符串") ) #每匹配成功输出一个列表元素
使用sub来替换内容
import re
#从第三个字符串中找到第一个字符串用第二个字符串替换
re.sub("正则表达式","替换元素","被替换掉字符串")
常用操作符:
操作符 | 说明 | 实列 |
---|---|---|
. | 表示任何一个字符 | |
[] | 字符集,对单个字符给出取值范围 | [abc] 表示a,b,c [a-z] 表示a到z的单个字符 |
[^] | 非字符集,对单个字符给出排除范围 | [^abc] 表示非a非b非c的单个字符 |
* | 前一个字符0次或无限次扩展 | abc* 表示 ab,abc,abcc,abccc |
+ | 前一个字符1次或者无限次扩展 | abc+ 表示abc,abcc,abccc |
? | 前一个字符0次或者1次扩展 | abc? 表示ab,abc |
| | 左右表达式任意一个 | abc|cdf 表示abc或者cdf |
{m} | 扩展前一个字符m次 | ab{2}c 表示abbc |
{m,n} | 扩展前一个字符m至n次(含n) | ab{1,2}c 表示abc,abbc |
^ | 匹配字符串开头 | ^abc 表示abc且在字符串开头 |
$ | 匹配字符串结尾 | $abc 表示abc且在字符串结尾 |
() | 分组标记,内部只能用|操作符 | (abc)表示abc (abc|def)表示abc,def |
\d | 数字,等价[1-9] | |
\w | 单词字符,等价[A-Za-z0-9_] | |
\s |
主要函数:
函数 | 说明 | 备注 |
---|---|---|
re.search() | 在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象 | |
re.match() | 从一个字符串的开始位置起匹配正则表达式,返回match对象 | |
re.findall() | 搜索字符串,以列表类型返回全部能匹配的子串 | |
re.split() | 将一个字符串按照正则表达式匹配结果进行分割,返回列表类型 | |
re.finditer() | 搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素都是match对象 | |
re.sub() | 在一个字符串中替换所有匹配正则表达式的字串,返回替换后的字符串 |
可选的标志修饰符:
修饰符 | 描述 | 备注 |
---|---|---|
re.l | 是匹配大小写不敏感 | |
re.L | 做本地化识别匹配 | |
re.M | 多行匹配,影响^和$ | |
re.S | 使 . 匹配换行在内的所有字符 | |
re.U | 根据Unicode字符集解析字符。这个标志影响\w,\W,\b,\B | |
re.X | 该标志通过给与你更灵活的格式以便你将正则表达式写的更易于理解。 |
css选择器
通过标签查找:
file = open("要打开文件的路径","打开模式")
html = file.read()
bs = BeautifulSoup(html,"html.parser")
#查找固定的标签
list = bs.select("a") #<a class="选定class" id="选定id"></a>
通过类名查找
file = open("要打开文件的路径","打开模式")
html = file.read()
bs = BeautifulSoup(html,"html.parser")
#查找固定类名的标签
list = bs.select(".选定class") #<a class="选定class" id="选定id"></a>
通过id来查找
file = open("要打开文件的路径","打开模式")
html = file.read()
bs = BeautifulSoup(html,"html.parser")
#查找固定id的标签
list = bs.select("#选定id") #<a class="选定class" id="选定id"></a>
通过属性来查找
file = open("要打开文件的路径","打开模式")
html = file.read()
bs = BeautifulSoup(html,"html.parser")
#查找固定属性的标签
list = bs.select("a[class='选定class']") #<a class="选定class" id="选定id"></a>
通过子标签查找
file = open("要打开文件的路径","打开模式")
html = file.read()
bs = BeautifulSoup(html,"html.parser")
#查找标签d的子父关系查找 # <head>
list = bs.select("head > title") # <title>查找内容</title> # </head>
通过兄弟标签查找
file = open("要打开文件的路径","打开模式")
html = file.read()
bs = BeautifulSoup(html,"html.parser")
#查找固定属性的标签 # <muav></muav>
list = bs.select(".muav ~ .bri") # <bri>要查找内容<bri>
2.4保存数据
1.Excel 表存储数据
l利用python库将抽取的数据写入Excel表格
以utf-8编码创建一个excel表格 -> 创建一个sheet表 -> 往单元格写入内容 -> 保存表格
#引入模块
import xlwt
#以utf-8编码创建一个excel表格 表格变量 = xlwt.Workbook(decoding="utf-8")
workbook = xlwt.Workbook(decoding="utf-8")
#创建一个sheet表 工作表变量 = workbook.add_sheet('工作表名')
worksheet = workbook.add_sheet('sheet1',cell_overwrite_ok=True) ##是否可以覆盖内容
#往单元格写入内容 工作表变量.write(横坐标, 纵坐标, "要写入字符")
worksheet.write(0, 0, "存储字符")
#保存表格
workbook.save("xxxx.xls") 表格变量.save("表格名.xls")
2.数据库存储数据
利用python库将抽取的数据写入sqliee数据库
打开或者创建数据库 -> 获取游标 -> 执行sql语句 -> 提交数据库操作 -> 关闭数据库
# 引入模块
import sqlite3
#1.打开或者创建数据库,默认在当前目录下 数据库变量 = sqlite.connect("文件名")
conn = sqlite.connect("文件名")
#2.获取游标 游标变量 = 数据库变量.cursor()
c = conn.cursor()
#编写sql语句
sql = "sql语句"
#3.执行sql语句 游标变量.execute("sql语句")
c.execute(sql) #如果有返回值: cursor = c.execute(sql)
#4.提交数据库操作 数据库变量.commit()
conn.commit()
#5.关闭数据库 数据库变量.close
conn.close()
例子:
# -*- codeing = utf-8 -*-
#@Time: 2021/2/22 19:33
#@Name: 凡诚
#@File:bilibili
#@Software PyCharm
import urllib.request,urllib.parse
import re
from bs4 import BeautifulSoup
import xlwt
#爬取网页地址
url = "https://www.bilibili.com/v/popular/rank/all"
#获得排名
findpm = re.compile(r'data-rank="(\d*)"><div')
#获得名字
findName = re.compile(r'href=".*" target="_blank">(.*)</a> <!-- --> ')
#获得番号
findfh = re.compile(r'li class="rank-item" data-id="(.*)" data-rank')
#获得播放地址
finddz = re.compile(r'a href="//(.*)" target="_blank"><img')
#获得播放量
findbfl = re.compile(r'<i class="b-icon play"></i>\n(.*)</span> <span class="data-box">',re.S)
#获得弹幕数
finddms = re.compile(r'</span> <span class="data-box"><i class="b-icon view"></i>(.*)</span> <a',re.S)
#获得制作方
findzzf = re.compile(r'<span class="data-box up-name"><i class="b-icon author"></i>(.*)</span></a></div> <div class="pts">',re.S)
#获得综合分数
findfs = re.compile(r'<div>(\d*)</div>综合得分')
#获得指定标签内的内容
def getText(html):
#返回内容的列表
list_s = []
# 使用BeautifulSoup解析源码
bs = BeautifulSoup(html, "html.parser")
#依次解析获得内容
for item in bs.find_all('li',class_='rank-item'):
data = []
item = str(item)
#获得排名
pm = re.findall(findpm, item)[0]
data.append(pm)
# 获得名字
name = re.findall(findName,item)[0]
data.append(name)
# 获得番号
fh = re.findall(findfh, item)[0]
data.append(fh)
#获得播放地址
dz = re.findall(finddz, item)[0]
data.append(dz)
# 获得播放量
bfl = re.findall(findbfl, item)[0]
bfl = re.sub(r"\n","",bfl)
bfl = re.sub(" ", "", bfl)
data.append(bfl)
# 获得弹幕数
dms = re.findall(finddms, item)[0]
dms = re.sub(" ","",dms)
dms = re.sub(r"\n", "",dms)
data.append(dms)
# 获得制作方
zzf = re.findall(findzzf, item)[0]
zzf = re.sub(" ", "", zzf)
zzf = re.sub(r"\n", "", zzf)
data.append(zzf)
# 获得综合分数
fs = re.findall(findfs, item)[0]
data.append(fs)
list_s.append(data)
return list_s
#获取指定网页源码
def getHtml(url):
try:
header = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36"}
# 封装二进制对象
data = bytes(urllib.parse.urlencode({"awsl": "awsl"}), encoding="utf-8")
# 封装url对象
re = urllib.request.Request(url=url, headers=header)
# 获取网页源码
res = urllib.request.urlopen(re, timeout=1)
# 打印源码
# print(res.read().decode("utf-8"))
except urllib.error.URLError as e:
print("访问超时")
return res.read().decode("utf-8")
#将爬取内容保存到excel表格中
def getExcel(list):
list_b = ['排名','视频名称','视频番号','播放地址','观看次数','弹幕数量','制作者','综合分数']
list_n = list
#创建一个表格
workbook = xlwt.Workbook(encoding="utf-8")
#创建一个工作表
worksheet = workbook.add_sheet("哔哩哔哩排行榜")
#写入数据
for i in range(0,8):
#写入表头
worksheet.write(0,i,list_b[i])
for i in range(0, 100):
for j in range(0, 8):
#写入内容
worksheet.write(i+1,j, list_n[i][j])
#关闭并保存
workbook.save("bilibili每日排行.xls")
if __name__ == "__main__":
list = []
#获取网页源码
html = getHtml(url)
#获取标签内容
list = getText(html)
#将获取数据写入excel表格
getExcel(list)