注明:本博客为学习博客,其中代码以及讲解参考爬虫入门的视频
本文目录
- 阅读前提示
- 安装python环境
- 快速入门python语法
- python爬虫的流程
- HTTP请求和相应
- python的request库
- HTML网页结构
- python的Beautiful Soup库
- 爬虫的终极演练——爬取豆瓣TOP250网页
- 致谢
阅读前提示
本文中的所有代码大部分以交互模式下的python语法,也就是在代码块中,每行代码前面没有 >>>的就是我输入的代码,有>>>的就是计算机给我的反馈
安装python环境
安装Python集成开发环境
在windows系统环境下,下载python环境,可以直接点击下面网址python官网进行下载
怎么证明电脑已经安装好了Python环境
打开电脑下方的搜索
输入cmd,弹出一个黑色的框框
在黑色的框框中输入python后,如果和下面图片显示的效果差不多,那么就说明python环境已经安装就绪
安装pycharm
可以点击下面的链接pycharm官网
由于我们的python仅供普通的使用,所以我们只需要下载社区版即可
由于是外网访问,所以下载速度较慢是正常现象
打开pycharm
如果已经安装了这样的窗口,那么就说明已经成功的安装了pycharm
快速入门python语法
打印函数print()
print的意思是打印,将指定文字展现在屏幕上,打印的东西为括号内的内容
ps:编程语言只认得英文的符号
要用双引号引住
print("hello world")
被引号所引用的叫做字符串,即这里的hello world就是字符串,无论引号中是什么,只要在引号内,那么他就是字符串
python中的数学运算
加减乘除
python使用的是+ - * / 来表示加减乘除四个符号
** 表示乘方
math函数库
专门提供数学运算的函数库,需要用这个函数库中的函数的话,需要在代码的开头写上import math,类似于标准C语言的# include “头文件”
import math
math.sin(1) #计算sin1的大小
该库还可以返回log的底数,具体math函数库中的函数
math.log2(8) #该式子返回的就是浮点数3.0
如果我们需要知道这个表达式的计算结果,并且打印在屏幕上,可以利用print函数
print(math.log2(8))
>>> 3
或者是用某个变量进行记录
import math
result = math.log2(8)
print(result)
>>> 3
python的注释
注释在代码中是非常重要的,它是会被解释器和编译器忽略的文字,是给人类来阅读的,帮助他人和未来的自己理解未来的意图
python的注释为#开头 ,类似于C语言的//
# 我是一行注释
pycharm快捷键一键注释代码
选中代码后CTRL+/ 即可快速注释选中代码
撤销注释:
在摁一次CTRL+/ 即可
其他的注释方式
可以利用"“” “”"来注释代码 类似于C语言中的/* */
"""
我被注释了
"""
python的数据类型
python的数据类型和其他编程语言相似,有字符串、整数、浮点数、布尔类型、空值类型等等
也有python独有的列表和字典,后面会讲解
字符串
x = "hello"
字符串的长度
len(x) #5
字符串的索引
x[1] #e
注意,python的索引是从0开始的
整数int 浮点数float
数字 | 类型 |
---|---|
6 | int |
-2 | int |
-1.2 | float |
布尔类型(bool)
只包含两种值:真(True) 假(False)
空置类型(None)
None类型不是0 也不是" " 也不是False 它所表示的是完全不存在一个值
类似于C语言中的NULL(空指针)
类型函数
当我们需要知道一个数据的类型的时候,我们可以使用type函数,它会返回这个数据的类型
type(x)
>>> <class 'str'>
python的执行模式
python有两种执行模式:命令行模型和交互模式
命令行模式
写好代码后,保存并且运行整个文件,例如pycharm的工程文件
运行的时候python解释器会对每一行进行执行
交互模式
输入一行后,马上执行并且输出运行结果,例如IDLE就是最典型的交互模式工程文件
不需要print语句就可以直接得到我们输入的数据
python输入和输出
input函数
例如下面代码询问用户的年龄:
input("请输入你的年龄: ")
>>> 请输入你的年龄:
python会根据input中的字符串给出相应的提示
为了知道input的返回值,可以用变量来接受input的返回值
age = input("请输入你的年龄:")
print("你的年龄是" + age + "岁")
input一律返回字符串,无论我们是输入什么,它都会当作字符串进行返回
那如果我们需要将输入的进行计算怎么办,此时类型转换登场
python的类型转换
int()函数
将输入的转换为int类型
int("666")# 这里返回的就是数字666
#将字符串"666"转换为了数字整形666
float()、str()函数
将输入的类型转换为浮点型和字符串类型
float(6) ## return 6.0
str(6) ## return "6"
str函数在print函数中用的很多,例如整数不可以在字符串的模式下进行打印,但是我们只需要进行str函数的改变即可完成打印
print("你今年" + str(2) + "岁了")
python的条件判断语句
条件语句的核心:
如果条件1满足:
执行A行动
否则:
执行B行动
python的条件语句是用 if 来书写
条件语句的返回布尔类型
例如
3 == 3 # return True
3 > 2 # return True
5 < 2 # return False
条件语句举例
代码的格式:
if [条件]:
[执行语句]
else:
[执行语句]
要注意if和else的缩进,缩进是python的命脉
mood_index = input("对象今天的心情指数是: ")
if int(mood_index) >= 60: # 注意这里要将mood_index强制类型转化为int类型
print("You can play games")
else:
print("You can't play games")
多条件判断语句
嵌套if语句
语句的基本格式:
if [condition1]:
if [condition2]:
next codeA
else:
next codeB
else:
next codeC
这里需要condition1 和 condition2 全部为真(True),才会执行next codeA的语句
这里更需要利用缩进,一般python的一个缩进就是一个Tab键
elif语句
if condition1 :
codeA
elif codition2:
codeB
elif condition3:
codeC
else:
codeD
elif的数量没有上限也没用下限
但是如果condition2 和condition3同时满足,python只会执行condition2的条件,其他的else和elif的语句将不再进行解析翻译
逻辑运算符
逻辑运算符的分类
python的逻辑运算符有三个 and or not 对应中文里的与或非三种逻辑关系
数学语言理解 python逻辑运算符
x > 5 and x < 10 翻译为数学语言为x ∈(5,10)
x > 5 or x < 10 翻译为数学语言为x ∈(5,∞)∪(-∞,10)
not x > 5 翻译为数学语言为x ∈ (-∞,5] 这里要注意5这里取等号
布尔类型理解逻辑运算符
and 所连接的所有条件判断只有全部为True的时候,整体才为True;有一个为False的时候整体就是False
or所链接的条件判断的时候只要有一个为True,整体就为True;除非全部为False,否则整体即为True
逻辑运算符的优先级
优先级顺序为 not > and > or
python的列表
python的列表是用[]来表示的,并且列表是python中可变的一种数据结构,前面讲的字符串、整形、浮点数、布尔类型都是不可以变化的
list = ["Keyboard","Mouse","Paper"]
可变以及不可变
以不可变的字符串作为例子:
ps:upper方法可以将字符串的每个字母都变成大写返回出来
s = "hello"
print(s.upper())
>>> HELLO
print(s)
>>> hello
从上面的例子可以看出,字符串是一种不可变的数据结构,即使用upper将每个字母转化为了大写,但是依旧不改变原字符串
那么如果我们要将s中的每个字母都变成大写怎么办呢?
可以利用赋值操作
s = s.upper()
即可
列表是可以变化的,就不需要像字符串这样还要赋值操作
向列表中添加元素
可以利用添加元素的方法,方法是什么?我们后面会提到。
这里需要用append方法给列表添加元素
list.append("Pen")
list
>>> ["Keyboard","Mouse","Paper","Pen"]
方法也是用来实现某种特定功能的
初识方法
方法和函数是非常相似的,但是也有一定的区别
他们的调用方法也是不一样的
方法 | 函数 |
---|---|
对象.方法名(…) | 函数名(对象) |
向列表中删除元素
删除列表中的任意元素,是利用列表的remove方法
list
>>> ["Keyboard","Mouse","Paper","Pen"]
list.remove("keyboard")
list
>>> ["Mouse","Paper","Pen"]
列表的长度
可以通过len函数求长度,len函数会返回列表中的元素个数
list
>>> ["Keyboard","Mouse","Paper","Pen"]
len(list)
>>> 4
列表的索引
也是通过[]的方式来索引链表
list
>>> ["Keyboard","Mouse","Paper","Pen"]
list[1]
>>> "Mouse"
列表的可包容性
python 的列表不同于C语言的数组,可以放很多不同类型的数据
list = ["hello"]
list.append(6)
list.append(True)
list
>>> ["hello",6,True]
Python的列表还有很多的其他方法,这里由于空间的原因就不为赘述,具体可以查看python的列表官方文档,这里搜索网上的链接python的列表方法大全
得到的图片(图片来自上方链接)为:
python的字典
字典用来存储键值对 键:值
key : value
字典用{}来表示,同时字典也是一种可变的数据结构
contacts = {"A":"110","B":"119"}
要注意的是,字典键的类型必须是不可变类型,例如列表等可变类型就不可以作为字典的键
但是如果有时候键有多个,但是我们也不可以使用列表作为键,那么该怎么办呢?
不需要担心python贴心的准备了另一个数据结构,和列表相似,唯一的不同就是它是不可变的
python的元组
python的元组是用一对括号包括起来的数据结构,是一种不可变的数据结构
tuple = ("Key","Paper")
获取每个键的值
字典可以通过键来获得键所对应的值
contacts["A"]
>>> "110"
修改键值对
contacts = {"A":"110","B":"119"}
contacts["A"] = "120"
contacts
>>> {"A":"120","B":"119"}
由此可见,直接利用键来修改键值对会覆盖以前的键值对
键值对的存在性
如果向知道某个键是否存在
"something" in dict
如果字典中存在该键,返回布尔类型True,否则返回False
删除键
删除字典的键用的是del函数
contacts = {"A":"110","B":"119"}
del contacts["A"]
contacts
>>> {"B":"119"}
字典中键值对的数目
还是可以使用len函数来获得字典中键值对的数目
contacts = {"A":"110","B":"119"}
x = len(contacts)
x
>>> 2
字典的一些方法
dict.keys() # return each key
dict.values() # return each value
dict.items() # return each key and value 并且打包为元组的形式
python的for循环语句
python中可以用for循环进行迭代,迭代的对象可以是列表,字典,字符串等等数据结构
基本结构
for 变量名 in 可迭代对象:
#对每个变量做一些事情
所有前面带缩进的,都会被认为for循环其中的语句
下面以循环遍历字典中的键值对举例:
for a,b in list.items():
if condition1:
code
这个代码中的循环变量有两个,分别是a和b,他们按照顺序存储字典中的键和值,也就是a存储键,b存储这个键对应的值
range
range用来表示整数序列,括号中第一个数字表示起始值,最后一个数字表示结束值
range(5,10),需要注意的是,结束值并不在序列的范围中
这个可以用来结合for语句打印序列:
for i in range(5,10):
print(i)
>>> 5 6 7 8 9
range还可以包含第三个参数表示步长,也就是每一次跨越几个数字
for i in range(1,10,2)
print(i)
>>> 1 3 5 7 9
如果不指定步长,那么range的步长会默认为1
python的while循环语句
while conditionA:
action
只要conditionA的布尔值为True,那么while循环就会一直执行下去
python的格式化字符串
前面使用的格式化字符串都是用 + 的方式进行链接,但是这样的字符串过于丑陋,所以python还额外提供了几种格式化字符串的方法
format方法
位置格式化
str = "今年是{0}年,我今年{1}岁了".format(2023,20)
str
>>> "今年是2023年,我今年20岁了"
由此可以看出python的format格式化字符串方法也是一种索引的方式,{}中的数字就是format括号中的索引
关键词格式化
str = "今年是{year}年,我今年{age}岁了".format(year=2023,age=20)
str
>>> "今年是2023年,我今年20岁了"
这里用的是关键词的形式来替换字符串中的位置
f字符串
f字符串实际上是format方法的一种语法糖,具体什么是语法糖后面会进行解释
year = 2023
age = 20
str = f"今年是{year}年,我今年{age}岁了"
str
>>> "今年是2023年,我今年20岁了"
python的函数
python函数的基本格式:
def 函数名():
#定义的一些代码
还是要用缩进来划分函数的定义范围
在定义函数的时候,函数里面的代码都不会被执行,只有在调用函数的时候,函数中的代码才会被执行
函数的传参
# 定义函数
def callback(year,age):
print(f"This is {year} , and I am {age} year old")
callback(2023,20) # 调用函数
>>> This is 2023 , and I am 20 year old
可以在调用函数的时候传递参数
函数的作用域
我们在函数内部定义的变量都被称为局部变量,在函数的外面就访问不了了
我们可以具体举个例子来试试
# 定义函数
def myfunc():
x = 520
x
>>>Traceback (most recent call last):
>>> File "<pyshell#3>", line 1, in <module>
>>> x
>>>NameError: name 'x' is not defined
可以见到这里的函数报错了,从最后一句话可以看出编译器认为x没有被定义,所以说在函数内定义的变量在函数的外部是不可以访问的
函数的返回
函数的返回是用return语句的,return后面跟的是我们需要函数返回的东西,当遇到return语句的时候,函数就结束了
当没有写return语句的时候,函数会默认为 return None
需要注意的是,当我们利用可以返回的函数的时候,我们需要创建变量来接收这个函数的返回值
下面举个例子:
def plus():
x = 50 + 20
return x
x
>>> 70
python的内置函数
我们可以在python的官方网站上,查看所有常用的内置函数
网站如下:python的内置函数大全
这里的访问速度比较慢是正常的,耐心等待即可
python导入模块函数
import 语句
import math
from…import… 语句
from math import sin
这样的话只把math库中的sin函数导入过来,其他的函数并没有被导入
这样的好处是,下次再使用这个函数的时候,就不需要带上模块的名字
from…import * 语句
from tkinter import *
这样的话就把tkinter中所有的函数全部导入过来了,运用的时候也不需要带上模块的名字
但是缺点是这样的运行速度会比较慢
python面向对象编程概念
面向过程编程
完成某个具体任务的编程,把要实现的事情拆分成一个个的过程进行编程
例如我们学习的C语言,就是典型的面向过程编程语言
但是随着程序长度和逻辑复杂度的增加,面向过程编程会稍微复杂
主打函数编程
面向对象编程
考虑每个对象有什么性质,能做什么事情
能让参数最小,程序逻辑更加清晰,避免了反复造轮子的行为
在面向对象的编程中,我们往往需要用class语句创建一个类
主打方法编程
类和对象的关系
类是对象的模板
对象是类的实例化
面向对象的三个特性
封装 继承 多态
封装
封装表示类的书写的时候把类中的代码隐藏起来,只通过外部的接口访问和使用,我们只需要知道这个类有哪些作用,不需要知道里面的原理
接口就是我们所使用的方法
继承
面向对象的编程允许创建有层次的类,类也可以有子类和父类,其中就包含了继承
例如我们创建了学生这个类,再来创建的小学生、中学生、大学生就是它的子类,就会继承有关于学生的一部分特性,不需要反复的定义
多态
同样的接口可以有不同的作用,在继承中,除了继承学生一部分特性,还有他们所不一样的地方,这个就叫做多态
python的面向对象的属性详解
创建一个类的基本格式为:
class myclass:
#定义类的一些代码
#...
一个类需要思考这个类的对象拥有的属性和方法
类的属性
例如我们想创建一个猫类,猫的属性就有它的毛发颜色、四肢数量等等
类的方法
特殊的类的方法——构造函数
主要作用是定义实例对象的属性,并且这个函数必须被命名为__init__()
class myclass:
def __init__(self):
#构造函数的代码
#..
在构造函数的括号里面可以放任意数量的参数,第一个参数永远都是self参数,用于表示这个对象自身,把属性的值绑定在实例对象上面
创建一个对象
例如我们先定义一个狗类
class mydog:
def __init__(self):
self.name = "旺财"
再来实例化一个对象,在python中,实例化对象用的是
对象名 = 类名()
dog1 = mydog()
dog1.name
>>> "旺财"
但是不是所有的狗狗都叫 “旺财” 我们可以手动传入狗狗的名字
class mydog:
def __init__(self,its_name):
self.name = its_name
dog2 = mydog("四喜")
dog2.name
>>> "四喜"
python的面向对象的方法详解
方法表示对象能完成什么事情
定义的方法和我们创建函数相类似,在class的定义内部定义def函数即可,但是需要注意缩进
基本的格式如下:
class myclass:
def __init__(self):
# 定义对象的一些属性
def mothed(self):
# 定义对象这个方法的代码
如何调用类的方法
先定义一个类,再实例化一个对象
调用方法只需要用方法名加上括号即可
class mydog:
def __init__(self,age,its_name):
self.name = its_name
self.age = age
def walk(self)
print("嘿咻"*self.age)
dog3 = mydog("旺财",3)
dog3.name
>>> "旺财"
dog3.age
>>> 3
dog3.walk()
>>> "嘿咻嘿咻嘿咻"
python的继承详解
父类的创建
在慢慢学习的过程中,小学的时候我们需要学习语文、数学、英语这三门课程,上课不可以迟到,但是在大学(理工类)的时候我们需要学习数学、英语、程序设计这三门课同时上课也不可以迟到
那么在小学和大学中,我们都需要学习英语和数学这两门科目,所以我们可以创建一个大的父类来包括学习英语和数学以及不可以迟到
class Student:
def __init__():
is_late = False
people = "1"
def math():
print("you need learn math")
def English():
print("you need learn English")
子类的创建
在类目的后面的括号写上父类的名字即可
class college(Student):
def python():
print("you need learn python")
class primary(Student):
def Chinese():
print("you need learn Chinese")
这里可以看出,子类是没有构造函数的,所以它会在它的父类里面寻找构造函数,来定义 math 和 English 和是否可以迟到的信息
子类修改父类的属性
如果说我们的学业已经完成的非常完美了,我们想在大学生这一类里面把is_late这一个属性变成True应该怎么完成呢?
这个时候我们就需要用到super()这个方法
super方法
super方法会返回到当前类的父类
class Student():
def __init__(self):
people = "1"
class college(Student):
def __init__():
super().__init__()
self.is_late = True
python的文件位置
计算机操作系统的目录结构
计算机的目录结构如上图所示
绝对路径
从根目录开始的路径,以最后需要寻找文件结尾
相对路径
从一个参考位置出发,从那个位置来看,其他位置的相对位置
用 . 来表示当前文件所在的那个目录
用 … 来表示更上一层的目录
python读取文件信息
打开目标文件
我们使用open函数
open函数有几个参数:第一个参数是路径;第二个参数是模式;第三个参数是encoding(我们一般使用utf-8)
常见的打开文件模式
“r” : 只读
“w” : 只写
f = open("相对路径 or 绝对路径","method",encoding = "utf-8")
如果上面代码执行成功,会返回一个文件对象
读取文件
read方法
读取文件可以用文件对象的read方法
f.read()
用了这个方法后,它会一次性读取文件中的所有内容,并且以字符串的形式返回
如果不想把整个文章读取完毕,可以给read方法传递参数,参数里面是数字表示读取几个字节
f.read(10) # 读取文件中的十个字节
readline方法
也可以用readline方法,每次读取一行
f.readline()
那么readline方法怎么可以看出文章已经读取完毕了呢?
由于当读到最后一行的时候,会返回空字符串,所以可以用循环的方式来进行判断
line = f.readline()
while line != "":
print(line)
line = f.readline()
readlines方法
返回全部文件内容组成的列表
read方法的注意事项
需要注意的是,当我们用完一次read方法后,再紧接着用一次read方法,会发现文件什么东西都打印不出来
这是因为文件会记录文件被读到哪个位置了,这里和C语言的文件指针的概念比较相似
关闭文件
利用close方法关闭文件
f.close()
但是很多时候我们会忘记关闭文件,所以我们可以使用另一种with open的语法来打开文件
with open("路径") as f:
#操作
用这样的语法打开文件后,当文件里面的代码执行完毕后,文件会被自动的关闭,这样的写法可以让代码更加的简洁
python写入文件信息
由于写文件和读文件非常的类似,我们都需要打开文件和关闭文件,但是不同的是不可以用 r 的方式打开文件,而是要用 w 的方式来打开文件
注意事项
用w的方式写入文件的话,如果文件本身存在,那么就会把原先的文件所有内容清空
写入操作
利用文件对象的write方法
f.write("hello\n")
f.write("csdn\n")
需要注意的是,write方法并不会自动帮我们换行,所以我们需要做的是手动换行,也就是手动添加 \n 的方法
追加操作
如果需要用追加的操作的话,就不可以用 w 的方式打开文件,应该用 a 的方式打开文件
读写操作
在传入的模式变成 r+ 的之后,就可以变成读写模式,既可以读也可以写
并且write方法执行的时候,并不会覆盖之前的文件,而是在原来的文件后面进行追加
python的异常捕捉
异常类型
IndexError 索引错误
ZeroDivisionError 除零错误
FileNotFoundError 找不到文件错误
TypeError 类型错误
…
捕捉异常
捕捉异常用的是try…except语句
基本的代码格式为:
try:
# 有可能产生错误的代码
except 异常类型1:
# 处理异常的方式
except 异常类型2:
# 处理异常的方式
except: # 无论是什么异常都进行拦截
# 处理异常的方法
else:
# 如果没有任何异常,执行的语句
finally:
# 无论错误是否存在,都会执行这句话
需要注意的是,try…except语句是从上向下执行的,当捕捉到我们写到的第一个异常的时候,后面的异常将都不会进行捕捉
python爬虫的流程
第一步:获取网页内容
通过代码,向网页服务器发送请求,它会返回给我们网页上的内容
第二步:解析网页内容
为了找到我们想要的内容,我们需要解析网页里面的代码进行解析,提取我们想要的代码
第三步:存储和分析数据
取决于具体的需求,后面还会讲到
爬虫需要注意的事情
第一:不要爬取公民的隐私数据
第二:不要爬取受著作权保护的内容
第三:不可以爬取国家保护的事务
第四:请求频率不能过高
第五:网站做出了反爬虫的操作,不要想着突破
HTTP请求和相应
http : 中文叫超文本传输协议
当我们在浏览器上输入我们想进入的网址的时候,浏览器就会向该网站的服务器发送一个请求
Get方法(爬虫程序主要使用的方法)
Get方法主要用于获得数据
比如当我们进入一个网页的时候,浏览器会发送Get请求
Post方法
Post方法主要用于创建数据
比如当我们进入一个网页并且填写信息的时候,浏览器会发送Post请求
http请求的组成部分
请求行
请求行会包括方法类型、资源路径、查询参数、协议版本
资源路径
资源路径表明了我们要访问服务器的哪个资源
下面举个例子
www.baidu.com/photo
这个例子的/photo就是所谓的资源路径
查询参数
查询参数表明我们传递给浏览器额外的信息
下面举个例子
https://blog.csdn.net/m0_60593173/article/details/131663?spm=......&utm_medium=distribute.pc_feed_v2.none-task-blog-personrec_tag-1-1-null-null.pc_personrec&depth_1-utm_source=distribute.pc_feed_v2.none-task-blog-personrec_tag-1-10963-null-null.pc_personrec
像在这一串的路径中 ? 前后的就是所谓的查询参数,查询参数之间用 & 进行分割
请求头
请求头会给予一些服务器需要的信息,比如右键网页打开network所能看到的 Host参数、User-Agent参数、Accept参数、Connection参数等等
请求体
请求体中可以包含客户端所传输的数据,请求体中也可以包含客户提交的查询字符串信息
http相应的组成部分
状态行
状态行包含了协议版本、状态码、状态消息
HTTP/2.0 404 Not Found
常见的状态码和状态消息
200 OK————客户端请求成功
301 Moved Permanently ————资源被永久移动到新的网站
404 Not Found ———— 请求资源不存在
503 Server Unavailable ———— 服务器不能处理客户端的请求
总结而言 2开头的状态码表示请求成功
3开头的状态码表示重定向
4开头的状态码表示客户端错误
5开头的状态码表示服务器错误
响应头
响应头会包含一些响应的信息,例如响应的日期、文本格式、文本编码等等
响应体
服务器给客户端的响应内容
python的request库
下载python的requests库
我们先打开pycharm编辑器,找到终端
在终端输入pip install requests
如果会卡住的话,就输入
pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple
当出现了这样的界面的时候,就说明我们已经安装成功了
requests库的常见函数/方法
requests.get()
requests.get()是用来发送get请求,并且返回一个服务器返回给我们的响应对象
这个函数的参数传入我们需要访问的URL网址
import requests
response = requests.get("http://books.toscrape.com/")
response
>>> <Resopnse [200]>
resopnse.status_code # 请求状态码
>>> 200
当response对象的请求状态码为2开头的数字的时候,就说明我们成功向网页发送了get请求
或者我们可以使用response的ok属性来检测是否成功发送请求
if response.ok:
当这个属性为True的时候,说明成功发送请求,为False的时候说明发送请求失败
response.text
这个属性可以用存储我们响应出来的文件,我们可以直接用它来获取响应的内容
下面写一串爬取网页响应内容的代码示例
import requests
response = requests.get("http://books.toscrape.com/")
if response.ok:
print(response.text)
else:
print("something error")
请求成功的时候,控制台会打印很多标签符号,其实这都是网页的源码,类似于下面这张图片
header参数
这个参数可以用来帮助我们额外传给服务器一些信息,多用于隐藏自己的爬虫代码为浏览器的正常访问,这个参数的数据类型是一个字典
import requests
head = {"User-Agent":"....(浏览器)"}
response = requests.get("http://books.toscrape.com/",header = head)
这样在括号里定义上浏览器后,服务器就会将我们的爬虫代码看作是浏览器访问
获得本地电脑的User-Agent
我们可以随便点开一个网页,右键网页后找到检查,点击检查
找到右边新出现的一堆东西,点击network
后找到这一堆东西,随便点击一个进去
找到headers,并向下翻找到User-Agent,将内容复制下来即可
HTML网页结构
网页一般是由三个部分组成的,分别是html、css、JavaScript组成,这里我们主要爬取html,也就是定义了网页的结构和信息
html标签的基本结构,也可以叫做一个html元素:
<!DOCTYPE HTML> <这里表示该网页为html格式>
<html> <没有/的html是表示开始的标签,有/的表示结束的标签>
</html>
body标签
body表示文档的主体内容
h标签
h标签表示标题
h1表示一级标题,也就是最大的那个标题,h2,h3以此类推
数字越小,标题的层级越大
p标签
p标签表示文本段落
不同的p标签之间会默认换行
下面可以举个例子
<p>第一行</p>
<p>第二行</p>
第一行
第二行
举个例子
<!DOCTYPE HTML>
<html>
<body>
<h1>这是一个标题</h1>
<p>这是一个文本段落</p>
</body>
</html>
由于这个h1和p位于一个body下面,所以他们是一个级别的,他们最后组成的样子就是一个标题加一段文字
html还有很多的其他有趣的标签,在这里步过多的探索,后期还会发有关于前端的一些文章,其中会对html进行一些详解
html常见的其他重要标签
除了上面讲到的标题标签、body标签、内容标签等等,还有很多对我们学习爬虫比较重要的网络标签,在这里我们一起学习一下他们。
br标签
br标签可以在文本段落中强制换行,被称为换行标签,并且是以单标签的形式出现
下面可以举个例子:
<p>第一行<br>第二行</p>
<p>第三行</p>
第一行
第二行
第三行
b标签&i标签
我们可以用b标签包围文本,实现文本的加粗
<p>我马上要被<b>加粗</b>了</p>
我马上要被加粗了
我们可以用i标签包围文本,实现文本的斜体
<p>我马上要变成<i>斜体</i>了</p>
我马上要变成斜体了
img标签
img标签可以在网页中添加一张图片,并且也是一个单标签
这个标签需要添加属性src,表示图片的路径(可以是一个网页链接,也可以是一个路径)
还可以添加一些其他的属性来控制这个图片
例如width属性,设置图片宽度,height设置图片高度
<img src="路径",width = "宽度",height = "高度">
a标签
a标签可以看作是一个超链接,用户通过链接进入其他网页
a标签一定要指定属性href,href的值就是目标跳到的网页
还有一个可有可无的target属性,当target属性指定为_self的时候,就会覆盖当前网页打开下一个网页,当target属性指定为_blank的时候,就会重新打开一个网页
<a herf = "网页">跳转网页</a>
div标签和span标签
这两个标签是两个容器,本身是没有意义的。
他们的作用在于,当我们使用css去渲染整个网页的时候,我们不需要对于每个标签都进行渲染,我们只需要找到div包裹住的标签,可以进行整体的渲染
区别
div标签独占一行,一行只能有一个div标签
span标签一行可以有多个
ol标签&ul标签
ol标签是一个表示有序列表的标签
下面举个例子
<ol>
<li>语文</li>
<li>数学</li>
<li>英语</li>
<li>线性代数</li>
</ol>
1.语文
2.数学
3.英语
4.线性代数
从上面可以看出,ol标签会自动给我们输入的进行有序的标号
与ol对于的是无序列表ul,这里就不多赘述
网页的表格组成
table标签
table是用来定义表格的标签,里面常常会嵌入一些定义表格的元素
可以加上一些属性
border:可以为表格加上边框<table border="1">
thead标签
表示表格的头部,表格的第一行
tbody标签
表示表格的主体
tr标签
tr标签一般定义在thead和tbody之间,用来表示表格的每一行
td标签
在tr标签之间,会放一些td标签,表示一项一项的数据,单元格
整体举例
<table>
<thead>
<tr>
<td>列1</td>
<td>列2</td>
</tr>
</thead>
<tbody>
<tr>
<td>坐标11</td>
<td>坐标12</td>
</tr>
<tr>
<td>坐标21</td>
<td>坐标22</td>
</tr>
</tbody>
</table>
列1 | 列2 |
---|---|
坐标11 | 坐标12 |
坐标21 | 坐标22 |
python的Beautiful Soup库
安装beautiful soup库
和python的requests库一样,属于python的第三方库,所以要用相同的方法进行安装,这里就不过多赘述
pip install bs4 -i https://pypi.tuna.tsinghua.edu.cn/simple
构造函数BeautifulSoup
这个函数可以解析我们的html的文本
这个函数的第一个参数是response.text对象,第二个参数是需要用html格式的解析器进行解析,也就是"html.parser"
这个函数会返回一个被解析的对象
content = requests.gets("网页").text
soup = BeautifulSoup(content,"html.parser")
解析后,得到的将会是类似于下面图片的对象(图片来自网络):
beautifulsoup对象的findAll方法
能根据标签的属性等,找出所有符合要求的元素,并且返回一个可迭代的对象
第一个参数为需要寻找的标签
第二参数为attrs,其为一个字典格式,里面存放的是属性:名字的键值对
下面举个例子
all_price = soup.findAll("p",attrs={"class":"price_color"})
for price in all_price:
print(price.string)
#price的string属性可以直接把标签包围的文字返回给我们
爬虫的终极演练——爬取豆瓣TOP250网页
第一步:以get方式进入网站
import requests
head = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36 SLBrowser/7.0.0.6251 SLBChan/105"
}
response = requests.get("http://movie.douban.com/top250",headers = head)
第二步:利用BeautifulSoup提取html
from bs4 import BeautifulSoup
html = response.text
soup = BeautifulSoup(html,"html.parser")
第三步:分析提取信息的特点
先进入豆瓣Top250的网页,右键点击检查,可以看到网页的源代码
我们来寻找几个标题来寻找一下共同的特征
我们可以总结出来,所有的标题都是一个span标签,并且他们的class的值都是title
于是我们可以写下代码:
all_titles = soup.findAll("span",attrs={"class":"title"})
for title in all_titles:
print(title.string)
发现错误
我们在做完上面的操作后,发现打印的东西确实含有我们想要的标题,但是还打印了一些我们不想要的东西,比如这个电影的原版标题
此时我们再次回到豆瓣Top250的网页检查源码,发现电影的原名也确实符合span下的class为title的特征
再次分析问题,解决问题
我们可以再来看看打印的结果
仔细观察不难发现到,我们打印的原来的名字前面都有一个 / ,这个或许可以成为我们筛选掉他们的一个基础
所以我们只需要找到不带 / 的标题即可,只需要使用条件判断即可
于是我们修改代码:
for title in all_titles:
title_string = title.string
if "/" not in title.string:
print(title.string)
第四步:学会翻页继续查找
通过上面的操作,我们可以得到第一页的所有电影名字,但是我们想获得的是整个Top250
这个时候我们就需要学会如何使用代码进行翻页
爬虫讲究的就是求同存异,我们寻找第一页和第二页的不同之处
我们可以发现,在第一页的时候,网页的start参数是0
但是在第二页的时候
网页的查询参数变成了25.也即是电影的索引是从25开始的
我们可以修改代码:
for start in range(0,250,25):
response = requests.get(f"http://movie.douban.com/top250?start={start}",headers = head)
html = response.text
soup = BeautifulSoup(html,"html.parser")
all_titles = soup.findAll("span",attrs={"class":"title"})
for title in all_titles:
title_string = title.string
if "/" not in title.string:
print(title.string)
整体代码
import requests
from bs4 import BeautifulSoup
head = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36 SLBrowser/7.0.0.6251 SLBChan/105"
}
for start in range(0,250,25):
response = requests.get(f"http://movie.douban.com/top250?start={start}",headers = head)
html = response.text
soup = BeautifulSoup(html,"html.parser")
all_titles = soup.findAll("span",attrs={"class":"title"})
for title in all_titles:
title_string = title.string
if "/" not in title.string:
print(title.string)
致谢
本文用于0基础入门学习python、0基础入门学习html语言、0基础入门学习爬虫,本文代码、思路、图片均有参考网上,参考的地方均用超链接做了标记