一、Python基础回顾
(一)变量类型
可变类型
:可以进行添加、修改、删除
(列表、字典…)
不可变类型
:不可以进行上述操作
(数字、字符串、元组…)
知识点 | 阐释 | 举例 |
---|---|---|
数字 不可变类型 | 标准数据类型之一 | int 整数、float 浮点数 |
字符串 不可变类型 | 标准数据类型之一 | str = “Hello World!” |
len(str) | 求长度,包含空格 | print(len(str)) 结果为12 |
str[1] | 字符串索引,从0开始 | print(str[1]) = e |
str[2:7] | 返回字符串中第三个至第六个之间的字符串 | print(str[2:5]) = llo Wo |
str[2:] | 返回从第三个字符开始的字符串 | print(str[2:]) = llo World! |
列表 可变类型 方括号[ ] | 标准数据类型之一 | list = [123,‘orange’,66.6,‘apple’,100] |
len(list) | 列表中元素的个数 | print(len(list)) 结果为5 |
list[1] | 返回列表中第二个元素 | print(list[0]) = orange |
list[1:4] | 返回列表中第二个元素到第四个元素 | print(list[1:4]) = [‘orange’,66.6,‘apple’] |
list[2:] | 返回从第三个元素开始至列表末尾所有元素 | print(list[2:]) = [66.6,‘apple’,100] |
list.append(‘banana’) | 添加元素 | print(list) = [123,‘orange’,66.6,‘apple’,100,‘banana’] |
list.remove(’apple‘) | 删除元素 | print(list) = [123,‘orange’,66.6,100,‘banana’] |
max( )、min( )、sorted( ) | 全是数字的列表找最大值、最小值、递增排序函数 | 函数括号中放列表名称即可,返回结果分别是数字、数字、列表 |
元组 不可变类型 圆括号( ) | 标准数据类型之一 | 元组是不可变类型 故不能进行添加、删除操作 |
字典 “键” 是不可变类型 "字典”是可变类型 | 标准数据类型之一 键key值value对,用键查找值 | dict={“a”:“001”, “b”:“002”, “c”:“003”} “键与值”之间用冒号隔开,“键值对”之间用逗号隔开 |
len(dict) | 键值对个数 | print(len(dict)) 结果为3 |
dict[“a”] | 查找键对应的值 | print(dict[“a”]) = 001 |
dict.keys() | 返回所有键 | print(dict.keys()) = dict_keys([‘a’, ‘b’, ‘c’]) |
dict.values() | 返回所有值 | print(dict.values()) = dict_values([‘001’, ‘002’, ‘003’]) |
dict.items() | 返回所有键值对 | |
添加键值对 | dict[“d”] = “004” | print(dic) = {‘a’: ‘001’, ‘b’: ‘002’, ‘c’: ‘003’, ‘d’: ‘004’} |
删除键值对 | del dict[“a”] | print(dict) = |
检查键是否存在 | print(“a” in dict) 返回布尔值 | True则为存在 |
元组作为键 | dict = {(“张伟”,21):“001”, (“张伟”,34):“002”, (“张伟”,44):“003”} | 其中(张伟,xx)是不可变的元组类型 由于年龄不同,则可区分不同的张伟,并根据需要输出对应的值 |
字典作循环 | 将键值对看作元组,按照顺序取元组中的元素作为for后的变量 | 例如:temp_dict={“a”:36.4,“b”:36.6,“c”:36.2} for id,temp in temp_dict.items(): if temp >= 38:print(id) |
(二)其他操作
知识点 | 阐释 | 举例 |
---|---|---|
type( ) | 返回对象类型的函数 | type(None) 结果为<class ‘None Type’> |
input( ) | 从控制台获取输入,一律返回字符串 需要将结果赋值给一个变量 print中 “+” 只能用于字符串的连接 | age = input(“请输入年龄:”) print(“年龄为” + age) |
强制类型转换 | int( )、float( )、str( ) 将input的返回值改成需要的类型 | age = int(input(“请输入年龄:”)) xu_age = age + 1 print(“虚岁为” + str(xu_age)) |
range(5,10) | range(起始,终止-1) | for i in range(5,10) i 被依次赋值为5,6,7,8,9不包含10 |
range(1,10,2) | range(起始,终止-1,步长) | i 依次被赋值为1 3 5 7 9 |
range(5) | 默认起始值为0,终止值为5,步长为1 | |
format | 格式化输出 | gpa_dict = {“a”:3.251,“b”:3.869,“c”:4.256} for name,gpa in gpa_dict.items(): print(“{0}的绩点为{1}”.format(name,gpa)) |
f “你的年龄为{age}” | 格式化输出 | f加花括号加变量 |
def 函数名(参数): 不要忘记冒号 | return将运行结果返回以便其他地方使用 | 定义函数中的代码在调用时才会被执行 |
按住ctrl+函数名 | 查看具体函数实现 |
(三)面向对象编程
OOP:Object Oriented Programming
类 是创造 对象 的
模板
,对象 是 类 的实例
对象 可以绑定
“属性” 与 “方法”
# 创建一个CuteCat类
class CuteCat:
# __init__构造函数(初始化方法)
# self用来表示对象自身,用来把属性的值绑定在实例对象上
# 创建了该类的实例时,就会调用该方法
def __init__(self, cat_name, cat_age, cat_color):
self.name = cat_name
self.age = cat_age
self.color = cat_color
# 定义方法
# 方法中的self可以用来获取或修改和对象绑定的属性
# 此处cat的叫声次数为年龄值
def speak(self):
print("喵" * self.age)
# 创建Cutecat的一个实例,将实参传入
cat1 = CuteCat("Hua",3,"brow")
# cat1.age 访问该实例的属性
print(cat1.age)
# 实例调用类的方法
cat1.speak()
# 定义一个学生类
# 要求:
# 1. 属性包括学生姓名、学号,以及语数英三科的成绩
# 2. 能够设置学生某科目的成绩
# 3. 能够打印出该学生的所有科目成绩
class Student:
def __init__(self, name, id):
self.name = name
self.id = id
self.grades = {"语文":0, "数学":0, "英语":0}
def set_grades(self, course, grade):
# 判断科目是否存在于字典
if course in self.grades:
self.grades[course] = grade
def print_grades(self):
print(f"学生:{self.name} 学号:{self.id}")
for course in self.grades:
print(f"{course}:{self.grades[course]}分")
stu1 = Student("Alice", "001")
stu1.set_grades("语文", 95)
stu1.set_grades("数学", 100)
stu1.set_grades("英语", 85)
stu1.print_grades()
封装:写类的人将内部实现细节隐藏起来,使用类的人只通过外部接口(方法)访问和使用
继承:子类可以继承父类的属性和方法
多态:同样的接口(方法)因为具体所属类的不同而有不同的表现(在调用时,由于对象所属类的不同而使得,即使名称相同的方法,在对象调用方法执行后,会有不同的结果)
# 继承与多态练习:人力系统
# - 员工分为两类:全职员工共FullTimeEmployee、兼职员工PartTimeEmployee
# - 全职和简直都有“姓名 name”、“工号 id”属性
# 都具备“打印信息 print_info”(打印姓名、工号)方法
# - 全职有“月薪 monthly_salary”属性
# 兼职有”日新 daily_salary“属性、”每月工作天数 work_days“的属性
# - 全职和简直都有”计算月薪 salary“的方法,但各自计算过成不同
class Employee():
# 构造函数,父类中的name与if是子类所共有的
def __init__(self, name, id):
self.name = name
self.id = id
def print_info(self):
print(f"姓名:{self.name} 工号:{self.id}")
class FullTimeEmployee(Employee):
# 子类的括号中写父类
# 子类用super()继承父类中的构造函数,不带self
def __init__(self, name, id, monthly_salary):
super().__init__(name, id)
self.monthly_salary = monthly_salary
def salary(self):
return self.monthly_salary
class PartTimeEmployee(Employee):
# 子类的括号中写父类
# 子类用super()继承父类中的构造函数,不带self
def __init__(self, name, id, daily_salary, work_days):
super().__init__(name, id)
self.daily_salary = daily_salary
self.work_days = work_days
def salary(self):
return self.daily_salary * self.work_days
Employee1 = FullTimeEmployee("Alice", "001", 8000)
Employee2 = PartTimeEmployee("Freya", "008", 300, 15)
Employee1.print_info()
Employee2.print_info()
print(Employee1.salary())
print(Employee2.salary())
(四)文件读写
知识点 | 阐释 | 举例 |
---|---|---|
打开文件 | f = open(“文件路径”, “r或w”, encoding=“utf-8”) | 不写r或w时默认为r open返回的是一个文件对象 赋值给 f 可以进行后续操作 |
关闭文件 | f.close( ) | 关闭文件,释放资源 |
with关键字 | with open(“文件路径”) as f: print(f.read()) | f是文件对象的命名,缩进的代码块是对文件的操作 |
“r” 读取模式 | 只读 | 下面为读取的各种方法 |
返回全部文件内容的字符串 | f.read( ) f.read(x) | x为设定的从当前往后读x个字节的内容 x不写数时,一次性读取文件中的所有内容,返回为字符串 读完一次再读后返回空字符串(程序会记录最终读取的位置) 文件很大不建议用 |
返回一行文件内容的字符串 | f.readline( ) | 读取没一行文件内容,用while输出 读完全部文件后返回空字符串 “ ” |
返回全部文件内容组成的列表 | f.readlines( ) | 读取每一行文字并存储为列表,用for输出 |
“w”写入模式 | 只写 | 下面为写入的各种方法 |
覆盖文件,重新写入 | f.write( ) | 写入一行,若换行用换行符\n |
“a”添加模式 | 在原文件后添加 |
with open("D:\PyCharm\Spider\data.txt", "r", encoding="utf-8") as f:
# 方法一
print(f.read())
# 方法二
line = f.readline() # 读第一行
while line != "": # 判断当前行是否为空
print(line) # 不为空则打印当前行
line = f.readline() # 读取下一行
# 方法三
lines = f.readlines() # 把每行内容储存到列表里
for line in lines: # 遍历每行内容
print(line) # 打印当前行
二、爬虫流程
- 确定 URL
- 发起请求获取页面的 HTML
- 获取响应数据
- 将获取到的数据保存
(一)HTTP协议
知识点 | 阐释 | 举例 |
---|---|---|
URLUniversal Resource Loactor | 统一资源定位符 | 在浏览器的地址栏中输入的内容 |
HTTPHyper Text Transfer Protocol | 超文本传输的协议 用来明确谁是客户端,谁是服务器 | 客户端请求资源; 服务端提供资源 |
HTTPSHyper Text Transfer Protocol over Secure Socket Layer | 以安全为目标的http通道,http的安全版,即在http下加入ssl层 | |
GET方法 | 获得数据 | 得到服务器返回的网页内容 请求体一般为空 |
POST方法 | 创建数据 | 将数据发送给服务器 |
- HTTP请求
- HTTP响应
- 常见的状态码和状态消息
- 用 python 中的 Requests 库 构建 和 发送 HTTP请求
- 一个专门练习爬虫的网站:
http://books.toscrape.com/
- 查看各种状态码解释的网站:
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status
知识点 | 阐释 | 举例 |
---|---|---|
headers | {head = “User-Agent”:“Mozilla/5.0 (Windows NT 10.0;Win64; x64)”} head变量是一个字典类型 | 将爬虫伪装成一个正常的浏览器 |
requests | response = requests.get(“URL ”, headers = head) | requests.get( )构建和发送http请求 |
ok | response.ok | requests中的一个方法,用于判断请求是否成功 |
test | response.test | requests中的一个方法,用于返回请求后响应的字符串 |
- 伪装成浏览器的User-Agent获取位置
- 用 headers 成功伪装成浏览器获得响应(响应即该网站的 HTML 源码)
- 请求失败
(二)HTML网页结构
知识点 | 阐释 |
---|---|
HTML | 定义网页的结构和信息 |
CSS | 定义网页的样式 |
JavaScript | 定义用户和网页的交互逻辑 |
常用的标签 | 实例 | 含义 |
---|---|---|
< !DOCTYPE html > | 告诉浏览器是html格式进行渲染 | 声明文件类型 |
< html >…< /html > | 整个文档的根,其他标签作为其子元素 | |
< title >…< /title > | 展示在浏览器显示卡上的标题,而非网页文本标题 | |
< h1 >…< /h1 > | < h1 >这是一个一级标题< /h1 > | 标题标签,最多定义为 h6 |
< p >…< /p > | < p >这是一个文本< /p > | 文本标签 一个< br >强制换行 一对< i >…< /i >文本斜体 一对< u >…< /u >加下划线 一对< b >…< /b >文本加粗 |
< img …> | < img src = “图片的URL ”> | 图片标签 |
< a >…< /a > | < a href = “目标跳转的URL ”>这里是链接对应的文字< /a > | 添加链接 |
< a >…< /a > | < a href = “目标跳转的URL "target=”_self">这里是链接对应的文字< /a > | target默认为_self表示直接在当前的窗口跳转链接; target改为_blank表示在新窗口里打开 |
< div >…< /div > | 表示容器,块级元素,一行最多只有一个div元素 | |
< span >…< /span > | 表示容器,一行可以有多个span元素 | |
< ol >…< /ol > | 有序列表ordered list、list item | |
< ul >…< /ul > | 无序列表unordered list | |
< table >…< /table > | table | 表示表格 |
< thead >…< /thead > | head | 表示表格头部 |
< tbody >…< /tbody > | body | 表示表格主题 |
< tr >…< /tr > | row | 表格行 |
< td >…< /td > | data | 单元格 |
class属性 | 用来分组,例如可以通过class区分哪些是评论哪些是文章 |
(三)bs4 解析网页内容
- BeautifulSoup将HTML解析为下面的树状结构
- 解析HTML获得该网站中的书籍价格
# 为解析网页内容引入BeautifulSoup库
from bs4 import BeautifulSoup
# 为发送Get请求引入requests库
import requests
# 发送Get请求,返回网页的HTML
# 并且作为字符串储存在content的变量里
content = requests.get("http://books.toscrape.com").text
# 将content传入BeautifulSoup中,
# 因为BeautifulSoup还能解析其他东西
# 故需要指定HTML的解析器为 html.parser
soup = BeautifulSoup(content, "html.parser")
# BeautifulSoup中的findAll方法
# 可以根据标签、属性等找出符合要求的元素
# findAll(“表示找的标签”,attrs={字典键值对对应需要的属性和值})
# 返回的是一个可迭代对象,可以通过for循环依次操作返回的各个对象
all_prices = soup.findAll("p", attrs={"class":"price_color"})
for price in all_prices:
# 打印对象的string属性,只返回标签包围的文字
print(price.string[2:])
- 解析HTML获得该网站中的书籍名称
from bs4 import BeautifulSoup
import requests
content = requests.get("http://books.toscrape.com").text
soup = BeautifulSoup(content, "html.parser")
# findAll方法是找出所有指定的元素
all_names = soup.findAll("h3")
for title in all_names:
# find方法是直接找指定元素中的第一个元素
# 此处指只需要找出第一个a元素
# find方法返回的并不是可迭代对象,而直接是第一个对象
# 故不需要用for循环打印
names = title.find("a")
print(names.string)
(四)爬虫小试
- 爬取豆瓣电影TOP250的电影一句话介绍