01--python基础回顾

发布时间 2023-12-22 14:08:35作者: Edmond辉仔

一 关于爬虫的特殊性

1.网站的多变性:
这个是爬虫的魅力. 要全方位的去思考. 就像找漏洞一样. 思维逻辑不可能是固定的
达到目的即可,不要死磕牛角尖


2.访问频率调低
爬虫程序如果编写的不够完善. 访问频率过高. 很有可能会对服务器造成毁灭性打击
所以不要死盯着一个网站干. 请放慢爬取的速度. 为你好, 也为网站好


3.大厂和政府网站
新手不要去挑战这种大厂. 等有实力了. 慢慢研究(哪个都要研究很久)
gov的网站, 非必要不爬取. 非要爬取. 请一定降低访问频率   # !!!
   # 中央的很多重要网站都有非常强力的防护措施(瑞数等...)

二 必须要掌握的py基础

2.1 基础语法相关

  1. if条件判断

    举例:在写爬虫的时候. 我们会遇到这样的两种情况

    情况一 数据里有一些我们并不需要的内容

    data = "10,英雄本色,1500万"   # 正常你需要的数据
    data = "11,-,-"  # 你不需要的数据
    
    # 伪代码  理解含义(思路)
    if data里有你需要的数据:
        处理数据
    else:
         再见
    

    情况二 页面结构不统一, 会有两种页面结构

    完全没必要用一个提取器获取所有的数据. 完全没必要!!!
    
    # 伪代码  理解含义(思路)
    提取器1 = xxxx  #  用来提取页面中内容的
    提取器2 = xxxxxx
    
    # 页面有可能是不规则的
    结果1 = 提取器1.提取(页面)
    if 结果1:
        有结果. 存起来
    else: 
        没有结果. 
        结果2 = 提取器2.提取(页面)
    
  2. while循环
    关于循环, 我们必须要知道一个事情.

    # 反复的执行一段代码
    如果条件为真, 就执行循环体, 然后再次判断条件.....直到条件为假. 结束循环
    
    
    while 条件:
        循环体
    
  3. 关于True和False

    True, 是真的意思. 翻译成人话: 对的, OK, 没毛病. 确定

    False, 是假的意思. 翻译成人话: 不对劲, 错误, No. 有瑕疵. 不对劲

    下面这个, 需要各位去记住

    # 几乎所有能表示为空的东西. 都可以认为是False
    print(bool(0))
    print(bool(""))    
    print(bool([]))
    print(bool({}))
    print(bool(set()))
    print(bool(tuple()))
    print(bool(None))
    # 上面这一坨全是False, 相反的,都是真
    print(bool(" "))  # True
    
    # 利用这个特性. 我们可以有以下的一些写法
    
    # 伪代码  理解逻辑
    结果 = 提取器.提取(页面)
    if 结果:
        有结果. 我要保存结果
    else:
        没结果.......
    

2.2 字符串

​ 字符串在爬虫里. 必须要知道的几个操作:

  1. 索引和切片
    索引 就是第几个字符. 它从0开始
    切片 从字符串中提取n个字符

    s = "我爱黎明,黎明爱我"
    print(s[1])
    print(s[0])
    
    print(s[2:4])  从第2个到第4个(取不到4)
    
  2. strip()

    我们从网页上提取的数据. 很多都是带有一些杂质的(换行, 空格) 怎么去掉?

    strip 可以去掉字符串左右两端的空白 (空格, 换行\n, 回车\r, 制表符\t)

    s = "    \t\t\t我的天哪\r\r      \n\n  "  # 够乱的字符串
    s1 = s.strip()
    print(s1)  # 好了 `我的天哪`
    
  3. split()

    split 做切割的

    s = "10,男人本色,100000万"  # 你在网页上提取到这样的一段数据. 现在我需要电影名称
    tmps = s.split(",")
    name = tmps[1]
    print(name)  # 男人本色
    
    id, name, money = s.split(",")  # 切割后. 把三个结果直接怼给三个变量
    print(id)
    print(name)
    print(money)
    
  4. replace()

    replace 字符串替换

    s = "我      \t\t\n\n爱   黎       明    "   # 这是你从网页上拿到的东西
    s1 = replace(" ", "").replace("\t", "").replace("\n", "")   # 干掉空格, \t, \n
    print(s1)  # 我爱黎明
    
  5. join()

    join 将列表拼接为一个完整的字符串

    lst = ["我妈", "不喜欢", "黎明"]  # 有时由于网页结构的不规则, 导致获取的数据是这样的. 
    s1 = "".join(lst)   # 用空字符串把lst中的每一项拼接起来
    print(s1)  # 我妈不喜欢黎明
    
    lst2 = ["\n\r","\n\r","周杰伦\n\r", "\n不认识我\r"] 
    s2 = "".join(lst2).replace("\n", "").replace("\r", "")
    print(s2)   # 周杰伦不认识我
    
  6. f-string

    格式化字符串的一种方案

    s = "周杰伦"
    s1 = f"我喜欢{s}"  #  它会把一个变量塞入一个字符串
    print(s1)  # 我喜欢周杰伦
    
    k = 10085
    s2 = f"我的电话号是{k+1}" # 它会把计算结果赛入一个字符串
    print(s2)  # 我的电话号是10086
    
    # 综上:f-string的大括号里, 其实是一段表达式,能计算出结果即可
    

2.3 列表

列表,仅次于字符串的一种数据类型. 它主要是能承载大量的数据. 理论上. 内存不炸. 就能一直存

  1. 索引, 切片

    列表的索引和切片逻辑与字符串完全一致

    lst = ["赵本山", "王大陆", "大嘴猴", "马后炮"]
    item1 = lst[2]  # 大嘴猴
    item2 = lst[1]  # 王大陆
    
    lst2 = lst[2:]
    print(lst2)  # ["大嘴猴", "马后炮"]
    
    # 注意, 如果列表中没有数据. 取0会报错
    lst = []
    print(lst[0])  # 报错, Index out of bounds
    
    # 注意, 如果给出的索引下标超过了列表的最大索引. 依然会报错
    lst = ["123", "456"]
    print(lst[9999])   # 报错, Index out of bounds
    
  2. 增加

    给列表添加数据. append

    lst = [11,22]
    
    lst.append(33)
    lst.append(44)
    print(lst)  # [11,22,33,44]
    
  3. 删除

    删除数据(不常用, 好不容易爬到的数据. 为什么要删)

    lst.remove("周润发")  #  把周润发删掉
    
  4. 修改

    lst = ["赵本山", "王大陆", "大嘴猴", "马后炮"]
    
    lst[1] = "周杰伦"
    print(lst)   # ["赵本山", "周杰伦", "大嘴猴", "马后炮"]
    
  5. range

    用for循环数数的一个东西

    for i in range(10):
        print(i)   # 从0数到9
       
    for i in range(5, 10):
        print(i)  # 从5 数到 9
    
  6. 查询(必会!!!!)

    lst = ["赵本山", "周杰伦", "大嘴猴", "马后炮"]
    print(lst[0])
    print(lst[1])
    print(lst[2])
    print(lst[3])
    
    # 循环列表的索引
    for i in range(len(lst)):
        print(lst[i])
        
    # 循环列表的内容
    for item in lst:
        print(item)
    

2.4 字典

字典可以成对的保存数据

  1. 增加

    dic = {}
    dic['name'] = '樵夫'
    dic['age'] = 18
    
    print(dic)  # {"name": "樵夫", "age": 18}
    
    
  2. 修改

    dic = {"name": "樵夫", "age": 18}
    
    dic['age'] = 19
    print(dic)  # {"name": "樵夫", "age": 19}
    
  3. 删除(不常用)

    dic = {"name": "樵夫", "age": 18}
    
    dic.pop("age")
    print(dic)  # {'name': '樵夫'}
    
  4. 查询(重点)

    dic = {"name": "樵夫", "age": 18}
    
    a = dic['name']  # 查询'name'的值
    print(a)  # 樵夫
    
    b = dic['age']   # 拿到dic中age对应的值
    print(b)  # 18
    
    c = dic['哈拉少']   # 没有哈拉少. 报错
    d = dic.get("哈拉少")  # 没有哈拉少, 不报错. 返回None  # get好,不报错
    

5.循环

dic = {"name": "樵夫", "age": 18}

for k in dic:  # 循环出所有的key
    print(k)  
    print(dic[k])  # 获取到所有的value并打印

6.嵌套

dic = {
   "name": "王峰",
   "age": 18,
   "wife": {
       "name": "章子怡",
       "age": 19,
   },
   "children": [
       {'name':"胡一菲", "age": 19},
       {'name':"胡二菲", "age": 18},
       {'name':"胡三菲", "age": 17},
   ]
}

   # 王峰的第二个孩子的名字
   print(dic['children'][1]['name'])

   # 王峰所有孩子的名称和年龄
   for item in dic['children']:
       print(item['name'])
       print(item['age'])

2.5 字符集和bytes

字符集, 记住两个字符集就够了. 一个是utf-8, 一个是gbk. 都是支持中文的. 平时使用的最多的是utf-8

记住, bytes不是给人看的. 是给机器看的. 所有文字, 图片, 音频, 视频的东西到了计算机里都是字节

# 把字符串转化成字节    编码
bs = "我的天哪abcdef".encode("utf-8")
print(bs)  #  b'\xe6\x88\x91\xe7\x9a\x84\xe5\xa4\xa9\xe5\x93\xaaabcdef'
# 一个中文在utf-8里是3个字节. 一个英文是一个字节. 所以英文字母是正常显示的


# 把字节还原回字符串   解码
bs = b'\xe6\x88\x91\xe7\x9a\x84\xe5\xa4\xa9\xe5\x93\xaaabcdef'
s = bs.decode("utf-8")
print(s)

2.6 文件操作

python中. 想要处理一个文件. 必须用open()先打开一个文件

语法规则

f = open(文件名, mode="模式", encoding='文件编码')

f.read()  |  f.write()

f.close()


文件名:就不解释了

模式: 
  需要知道的主要有4个. 分别是: r, w, a, b
    r 只读模式
    w 只写模式
    a 追加模式
    b 字节模式. 可以和上面三种模式进行混合搭配. 目的是写入的内容或读取的内容是字节.


encoding: 
  文件编码. 只有处理的文件是文本的时候才能使用   99%的时候我们用的是`utf-8`
  并且mode不可以是`b`
    
    
# 问: 
1. 想保存一张图片. 用哪种模式?    mode='wb'
2. 想读取txt文件, 用哪种模式?    mode='r', encoding='utf-8'  
3. 想复制一个文件. 用哪种模式?    mode='rb'

另一种写法:

好处是, 不需要手动去关闭f

with open(文件名, mode=模式, encoding=编码) as f:
    pass


# 读取一个文本文件:
with open("躺尸一摆手.txt", mode="r", encoding="utf-8") as f:
    for line in f:   # for循环可以逐行的,进行循环文件中的内容
        print(line)

2.7 关于函数

在代码量很少的时候, 并不需要函数
一旦代码量大了. 一次写个几百行代码. 调试起来就很困难 
此时, 建议把程序改写成一个一个具有特定功能的函数. 方便调试,也方便代码的重用


# 定义函数
def 函数名(形式参数):
    # 函数体
    return 返回值

# 函数调用
函数名(实际参数)

试试:

def get_page_source(url):
    print("我要发送请求了. 我要获取到页面源代码啊")
    return "页面源代码"

pg_one = get_page_source("baidu.com")
pg_two = get_page_source("koukou.com")


def download_image(url, save_path):
    print(f"我要下载图片{url}了", f"保存在{save_path}")

donwload_image("http://www.baidu.com/abc/huyifei.jpg", "胡二飞.jpg")
donwload_image("http://www.baidu.com/aaa/dagedagefeifeifei.jpg", "大哥大哥飞飞飞.jpg")

2.8 关于模块

# 模块
就是已经有人帮我们写好了的一些代码, 这些代码被保存在一个py文件 或者一个文件夹里
可以拿来直接用


# 在python中有三种模块
第一种 python内置模块
  不用安装   直接导入就能用

第二种 第三方模块
  需要安装  安装后. 导入就可以用了

第三种 自定义模块  (新手先别自己定义模块)
  直接导入就能用

导入模块的语法

import 模块
from 模块 import 功能
from 模块.子模块 import 功能


# 举例子
import os
import sys
from urllib.parse import urljoin
from bs4 import BeautifulSoup

必须要了解的一些python内置模块

  1. time模块

    import time
    
    time.time()    # 获取时间戳  python的时间戳是秒,其他语言时间戳是毫秒
                   # 1s = 1000ms
    
    
    time.sleep(999)  # 让程序暂停999秒
    
  2. os模块

    import os
    
    os.path.exists()  # 判断文件或者文件夹是否存在
    os.path.join()    # 路径拼接
    os.makedirs()     # 创建文件夹
    
  3. json模块(重中之重)

    现在网站,习惯性用json来传递数据
    所以必须要知道json是啥, 以及python如何处理json
    
    json是一种类似字典一样的东西
    对于python而言, json是字符串 
    
    例如
    s = '{"name": "jay", "age": 18}'
    

    如何转化

    ### json字符串 ===> python字典
    import json
    
    s = '{"name": "jay", "age": 18}'
    
    dic = json.loads(s)     # loads json字符串  装载  成python格式
    print(type(dic))
    
    
    ### python字典 ===> json字符串
    dic = {"name": "jay", "age": 18}
    
    s = json.dumps(dic)    # dumps  python格式  倾倒  为json字符串
    print(type(s))
    
  4. random模块

    随机. 没别的用处.生成随机数

    import random
    
    i = random.randint(1, 10)  # 包含1~10的随机数
    print(i)   # 多跑两次.效果更加
    
    l = [11, 22, 33]   # 从列表中,随机抽取一个内容
    print(random.choice(l))
    
  5. 异常处理

    这个是重点. 我们在写爬虫的时候. 非常容易遇到问题. 但这些问题本身并不是我们程序的问题 
    
    比如, 你在抓取某网站的时候. 由于网络波动或者他服务器本身压力太大,导致本次请求失败 
    这种现象太常见了. 此时序这边就会崩溃. 打印一堆红色的文字. 让你难受的一P.  怎么办?
    
    要清楚一个事情  平时在打开一个网址的时候. 如果长时间没有反应, 或者加载很慢的时候
    我们习惯性的会刷新网页. 这个逻辑就像: `程序如果本次请求失败了. 能不能重新来一次`
    OK, 我们接下来聊的这个异常处理. 就是干这个事儿的
    
    
    try:   # 尝试...
        print("假如, 我是一段爬虫代码, 请求到对方服务器")
        print("我得出事儿啊")
        print(1/0)  # 出事儿了
    except Exception as e:  # 出错了. 我给你兜着
        print(e)  # 怎么兜?  打印一下. 就过去了
        
    print("不论上面是否出错. 我这里, 依然可以执行")
    
    
    程序执行的时候. 如果`try`中的代码出现错误
    则自动跳到`except`中. 并执行`except`中的代码 
    然后程序正常的, 继续执行
    
    有了这玩意. 我们就可以写出一段很漂亮的代码逻辑:
    import time
    for i in range(10):
        try:
            我要发送请求了. 我要干美国CIA的总部. 我要上天
            print("我成功了!!")
            break  # 成功了.就跳出循环
        except Exception as e:
            print("失败了")
            print("我不怕失败")
            print("再来")
            time.sleep(i * 10)
            
            
    # 注:
    在写代码测试阶段. 不要加try...except
    要不然,出错了. 你都不知道. 啥错了  错哪儿了