美文网首页信息安全专业知识
Python爬虫学习(更新中)

Python爬虫学习(更新中)

作者: 简言之_ | 来源:发表于2020-03-28 17:18 被阅读0次

    因为本篇文章很长,建议去我的个人博客看这篇文章(带有目录更方便):https://jwt1399.top/posts/34992.html

    一、基础知识准备

    Python基础语法还是很简单的,我通过一个个简单的小段代码来进行学习,所需掌握的知识点都包含在这段段代码中,每段代码都有相应详细注释,如果你有其他语言的基础那么Python基础就是轻轻松松的事。

    1 条件判断语句

    score = 60
    if score >=90 and score <=100:
        print("本次考试等级为A")
    elif score >=70 and score <90:  #elif == else if
        print("本次考试等级为B")      
    else:
        print("本次考试等级为C")      #output: 本次考试等级为B
    

    2 循环语句

    2.1 for循环

    for i in range(5): #输出5个数 [0 1 2 3 4]
        print(i)
    
    for i in range(0,10,3):#从[0,10),以3为间距输出                #output: [0 3 6 9]
        print(i)
    
    
    for i in range(-10,-100,-30):#从[-10,-100),以-30为间距     #output: [-10 -40 -70]
        print(i)
    
    
    
    name="chengdu" 
    for x in name:
        print(x)            #output: [c h e n g d u]
    
        
    a = ["a", "b", "c"] 
    for i in range(len(a)):
         print(i, a[i])    #output: [0 a 1 b 2 c]
    

    2.2 while循环

    i=0
    while i<3:
        print("这是第%d次循环:"%(i+1))
        print("i=%d"%i)
        i+=1
    
    '''#output: 
    这是第1次循环:
    i=0
    这是第2次循环:
    i=1
    这是第3次循环:
    i=2
    '''
    
    count = 0
    while count<3:
        print(count,"小于3")
        count +=1
    else:
        print(count,"大于或等于3")
        
    '''#output: 
    0 小于3
    1 小于3
    2 小于3
    3 大于或等于3
    '''
    

    3 字符串

    str="chengdu"             
    print(str)                #chengdu
    print(str[0])             #c
    print(str[0:5])           #[0,5) cheng
    print(str[1:7:2])         #[起始位置:结束位置:步进值] hnd
    print(str[5:])            #显示5以后的 du
    print(str[:5])            #显示5以前的 cheng
    print(str+",hello")       #字符串连接 chengdu,hello
    print(str*3)              #打印3次 chengduchengduchengdu
    print("hello\nchengdu")   #\n换行 hello  chengdu
    print(r"hello\nchengdu")  #前面加"r",表示显示原始字符串,不进行转义hello\nchengdu
    print("-"*30)             #打印30个“-”
    

    4 列表-List

    列表中的每个元素都分配一个数字 - 它的位置或索引,第一个索引是0,第二个索引是1,依此类推。

    4.1 列表定义

    namelist = ["小张","小王","小李"]
    testlist = [1,"测试","str"]  #列表中可以存储混合类型
    testlist = [["a","b"],["c","d"],["e","f","g"]] #列表嵌套
    

    4.2 列表元素输出

    namelist = ["小张","小王","小李"]
    #输出指定元素
    print(namelist[1])     #output: 小王
    
    #遍历输出
    for name in namelist: 
        print(name)
       
    '''output
    小张
    小王
    小李
    '''    
    
    #使用枚举函数enenumerate(),同时拿到列表下标和元素类容
    for i,name in enumerate(namelist): 
        print(i,name)
        
    '''output
    0 小张
    1 小王
    2 小李
    '''
    

    4.3 列表元素切片

    如下所示:L=['Google', 'Python', 'Taobao']

    Python 表达式 结果 描述
    L[2] 'Taobao' 读取第三个元素
    L[-1] 'Taobao' 读取最后一个元素
    L[1:] ['Python', 'Taobao'] 输出从第二个元素开始后的所有元素
    L[:-1] ['Google', 'Python'] 输出从第一个到倒数第一个的所有元素
    L[-2:] ['Python', 'Taobao'] 输出从倒数第二个到末尾的所有元素

    4.4 列表元素追加

    #append
    a = [1,2]
    b = [3,4]
    a.append(b)  #将b列表当做一个元素加入到a中
    print(a)     #output: [1, 2, [3, 4]]
    
    #extend
    a = [1,2]
    b = [3,4]
    a.extend(b) #将b列表中的诶个元素,逐一追加到a中
    print(a)    #output: [1, 2, 3, 4]
    
    #insert
    a=[1,2,4]
    a.insert(2,3) ##在下标为2的位置插入3   #指定下标位置插入元素(第一个表示下标,第二个表示元素)
    print(a)  #output: [1, 2, 3, 4] 
    

    4.5 列表元素删除

    #del
    a = ["小张","小王","小李"]
    del a[2]                      #删除指定下标元素
    print(a)                      #output: ['小张', '小王']
    
    #pop
    a = ["小张","小王","小李"]
    a.pop()                      #弹出末尾元素
    print(a)                     #output: ['小张', '小王']
    
    #remove
    a = ["小张","小王","小李"]
    a.remove("小李")             #直接删除指定内容的元素
    print(a)                    #output: ['小张', '小李']
    

    4.6 列表元素修改

    a = ["小张","小王","小李"]
    a[2] = "小红"              #修改指定下标元素内容
    print(a)                  #output: ['小张', '小王', '小红']
    

    4.7 列表元素查找

    #in / not in
    a = ["小张","小王","小李"]
    findName = input("请输入你要查找的学生姓名:")
    if findName in a:
        print("找到")
    else:
        print("未找到")
        
    #index
    a = ["小张","小王","小李"]
    print(a.index("小王",0,2))    #可以查找指定下标范围的元素,并返回找到对应数据的下标  #output: 1
    print(a.index("小李",0,2))   #范围区间:左开右闭[0,2) # ValueError: '小李' is not in list
    
    #count
    print(a.count("小王"))      #查找某个元素出现的次数  #output: 1
    

    4.8 列表元素反转和排序

    a = [1,4,2,3]
    a.reverse()             #将列表所有元素反转
    print(a)                #output: [3, 2, 4, 1]
     
    a.sort()                #升序
    print(a)                #output: [1, 2, 3, 4]
    
    a.sort(reverse=True)    #降序
    print(a)                #output: [1, 2, 3, 4]
    

    5 前段知识综合练习

    Topic: 将8个老师随机分配到3个办公室

    import random
    offices = [[],[],[]]                            #3个教室
    teachers = ["A","B","C","D","E","F","G","H"]    #8个老师
    for teacher in teachers:                        #遍历teachers放入office中
        index = random.randint(0,2)                 #产生随机数0,1,2
        offices[index].append(teacher)              #将teachers追加到office中
    i=1 #office1
    for office in offices:                           #输出每个office人数和对应的老师
        print("office%d的人数为:%d"%(i,len(office)))
        i += 1  #遍历offices
        for name in office:
            print("%s"%name,end="\t")                #打印每个office老师的名字
        print("\n")                                  #打印完一个office换行
        print("-"*20)                                #打印完一个office输出20个-
    

    6 元组-Tuple

    元组与列表类似,不同之处在于元组的元素不能修改。
    元组使用小括号,列表使用方括号。

    6.1 元组定义

    tup1=()     #空元组
    tup2=(5)    #<class 'int'>  不是元组
    tup2=(5,)   #<class 'tuple'>
    tup3 = ('Google', 'Python', 1997, 2000)
    

    6.2 元组元素切片

    tup=(1,2,3)
    print(tup[0])    #第一个元素     #output:  1
    print(tup[-1])   #最后一个元素   #output:  3
    print(tup[0:2])  #左闭右开[0,2) #output:  (1, 2)
    

    6.3 元组元素增加(连接)

    tup1 = (12,34,56)
    tup2 = ("ab","cd","ef")
    tup3 = tup1+tup2
    print(tup3)          #(12, 34, 56, 'ab', 'cd', 'ef')
    

    6.4 元组元素删除

    tup1 = (12,34,56)
    #del tup1[0]    #不允许删除单个元素
    del tup1        #删除了整个元组变量
    

    6.5 元组元素不能修改

    tup1 = (12,34,56)
    tup1[0] = 72  #报错 不能修改
    

    7 字典-dict

    字典使用键值对(key=>value)存储;键必须是唯一的,但值则不必。

    7.1 字典定义

    dict = {key1 : value1, key2 : value2 }
    info = {"name":"简简","age":18}
    

    7.2 字典访问

    info = {"name":"简简","age":18}
    print(info["name"])
    print(info["age"])
    
    #访问不存在键
    print(info["sex"])               #直接访问不存在的键,会报错
    print(info.get("sex"))           #使用get()方法,访问不存在的键,默认返回:none
    print(info.get("sex","没有"))     #没有找到的时候,返回自定义值  #output: 没有
    

    7.3 字典键值增加

    info = {"name":"简简","age":18}
    info["sex"]="man"               #新增sex
    print(info)                     #output: {'name': '简简', 'age': 18, 'sex': 'man'}
    

    7.4 字典键值删除

    #del
    info = {"name":"简简","age":18}
    del info["name"]                #删除name键值对
    print(info)                     #output: {'age': 18}
    
    del info                        #删除整个字典
    print(info)                     #output: NameError: name 'info' is not defined
    
    #clear
    info = {"name":"简简","age":18}
    info.clear()                     #清空字典内键值对
    print(info)                      #output: {}
    

    7.5 字典键值修改

    info = {"name":"简简","age":18}
    info["age"]=20
    print(info)
    

    7.6 字典键值查找

    info = {"name":"简简","age":18}
    print(info.keys())               #得到所有的键     #output: dict_keys(['name', 'age'])
    print(info.values())             #得到所有的值     #output: dict_values(['简简', 18])
    print(info.items())              #得到所有的键值对 #output: dict_items([('name', '简简'), ('age', 18)])
    
    
    #遍历所有的键
    for key in info.keys():
        print(key)     #output: name age
        
    #遍历所有的值
    for value in info.values():
        print(value)     #output: 简简 18
        
    #遍历所有的键值对
    for key,value in info.items():
            print("(key=%s,value=%s)"%(key,value)) 
    #output: (key=name,value=简简) (key=age,value=18)
    

    8 函数

    8.1 函数定义和使用

    def printinfo(a,b): #函数定义
        c =a + b
        print(c)
    
    printinfo(1,2)      #函数的使用
    

    8.2 带返回值的函数

    def info(a,b):
        c =a + b
        return c        #返回值
    
    print(info(1,2)) 
    

    8.3 返回多个值的函数

    def divid(a,b):
        shang = a//b
        yushu = a%b
        return shang,yushu #多个返回值用逗号隔开
    
    sh,yu = divid(5,2)     #需要用多个值来保存返回内容
    print("商:%d 余数:%d"%(sh,yu))
    

    9 文件操作

    9.1 打开文件(open)

    用法:对象=open(文件名,访问模式)

    f = open('test.txt', 'w')
    
    模式 说明
    r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
    w 打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
    a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
    rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
    wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
    ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
    r+ 打开一个文件用于读写。文件指针将会放在文件的开头。
    w+ 打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
    a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
    rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
    wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
    ab+ 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

    9.2 关闭文件(close)

    用法:对象.close()

    f.close()
    

    9.3 写数据(write)

    用法:对象.write()

    f=open("test.txt","w")  # 打开文件,w(写模式)-文件不存在就在当前路径给你新建一个
    f.write("hello,world")  # write将字符写入文件
    f.close()
    

    9.4 读数据(read)

    用法:对象.read()

    f=open("test.txt","r")   #打开文件,r(读模式)
    content=f.read(5)        #read读取5个字符
    print(content)
    f.close()
    

    9.5 读一行数据(readline)

    用法:对象.readline()

    f = open('test.txt', 'r')
    content = f.readline()
    print("1:%s"%content)#读取一行
    content = f.readline()
    print("2:%s"%content)#再读下一行
    f.close()
    

    9.6 读多行数据(readlines)

    用法:对象.readlines()

    f=open("test.txt","r")   #打开文件,r(读模式)
    content=f.readlines()    #readlines读取整个文件,以列表形式输出
    print(content)           #输出形式为列表 #output: ['hello,world\n', 'hello,world']
    
    #对列表进行处理,按序号一行一行输出
    i=1
    for temp in content:
        print("%d:%s" % (i, temp))
        i += 1  #output: 1:hello,world 2:hello,world
    f.close() 
    

    9.7 OS模块

    • 使用该模块必须先导入模块:
        import os
    
    os模块中的函数:
    序号 函数名称 描述 格式
    1 getcwd() 获取当前的工作目录 格式:os.getcwd() 返回值:路径字符串
    2 chdir() 修改当前工作目录 格式:os.chdir() 返回值:None
    3 listdir() 获取指定文件夹中的 所有文件和文件夹组成的列表 格式:os.listdir(目录路径) 返回值:目录中内容名称的列表
    4 mkdir() 创建一个目录/文件夹 格式:os.mkdir(目录路径) 返回值:None
    5 makedirs() 递归创建文件夹 格式:os.makedirs(路径)
    6 rmdir() 移除一个目录(必须是空目录) 格式:os.rmdir(目录路径) 返回值:None
    7 removedirs() 递归删除文件夹 格式:os.removedirs(目录路径) 返回值:None 注意最底层目录必须为空
    8 rename() 修改文件和文件夹的名称 格式:os.rename(源文件或文件夹,目标文件或文件夹) 返回值:None
    9 stat() 获取文件的相关 信息 格式:os.stat(文件路径) 返回值:包含文件信息的元组
    10 system() 执行系统命令 格式:os.system() 返回值:整型 慎用! 玩意来个rm -rf 你就爽了!
    11 getenv() 获取系统环境变量 格式:os.getenv(获取的环境变量名称) 返回值:字符串
    12 putenv() 设置系统环境变量 格式:os.putenv('环境变量名称',值) 返回值:无 注意:无法正常的getenv检测到。
    13 exit() 推出当前执行命令,直接关闭当前操作 格式:exit() 返回值:无

    10 异常处理

    10.1 异常简介

     print '-----test--1---'  
        open('123.txt','r')  
     print '-----test--2---'
    
    image-20200323100011079

    打开一个不存在的文件123.txt,当找不到123.txt 文件时,就会抛出给我们一个IOError类型的错误,No such file or directory:123.txt (没有123.txt这样的文件或目录)

    10.2 捕获异常

    try:
        print('-----test--1---')  
        open('123.txt','r')          
        print('-----test--2---')
    except IOError:
        pass
    

    此程序看不到任何错误,因为用except 捕获到了IOError异常,并添加了处理的方法
    pass 表示实现了相应的实现,但什么也不做;如果把pass改为print语句,那么就会输出其他信息

    总结:

    image-20200323100335376

    把可能出现问题的代码,放在try中
    把处理异常的代码,放在except中

    try:
      print num 
    except IOError:
      print('产生错误了')
    

    上例程序,已经使用except来捕获异常,但是还会看到错误的信息提示

    except捕获的错误类型是IOError,而此时程序产生的异常为 NameError ,所以except没有生效

    try:
      print num
    except NameError:
      print('产生错误了')
    

    Python的一些內建异常:

    异常 描述
    Exception 常规错误的基类
    AttributeError 对象没有这个属性
    IOError 输入/输出操作失败
    IndexError 序列中没有此索引(index)
    KeyError 映射中没有这个键
    NameError 未声明/初始化对象 (没有属性)
    SyntaxError Python 语法错误
    TypeError 对类型无效的操作
    ValueError 传入无效的参数
    ZeroDivisionError 除(或取模)零 (所有数据类型)

    更多可以参考:http://blog.csdn.net/gavin_john/article/details/50738323

    10.3 捕获多个异常

    #coding=utf-8 
    try:
     print('-----test--1---')
     open('123.txt','r') # 如果123.txt文件不存在,那么会产生 IOError 异常  
     print('-----test--2---')
     print(num)# 如果num变量没有定义,那么会产生 NameError 异常
     except (IOError,NameError):
     #如果想通过一次except捕获到多个异常可以用一个元组的形式
    

    10.4 获取异常的信息描述

    image-20200323102016442 image-20200323102023020.png

    10.5 try...finally...

    在程序中,如果一个段代码必须要执行,即无论异常是否产生都要执行,那么此时就需要使用finally。 比如文件关闭,释放锁,把数据库连接返还给连接池等

    import time
    try:
        f = open('test.txt')
        try:
            while True:
                content = f.readline()
                if len(content) == 0:
                    break
                time.sleep(2)
                print(content)
        except:
             #如果在读取文件的过程中,产生了异常,那么就会捕获到  
             #比如 按下了 ctrl+c
            pass
        finally:
            f.close()
            print('关闭文件')
    except:
        print("没有这个文件")
    

    test.txt文件中每一行数据打印,但是我有意在每打印一行之前用time.sleep方法暂停2秒钟。这样做的原因是让程序运行得慢一些。在程序运行的时候,按Ctrl+c中断(取消)程序。
    我们可以观察到KeyboardInterrupt异常被触发,程序退出。但是在程序退出之前,finally从句仍然被执行,把文件关闭。

    二、Python爬虫

    下面的学习方式是以爬取豆瓣top250 网页进行开展的

    基本流程: 爬取网页--->解析数据--->保存数据

    爬取网页

    首先要学习requests库或者urllib库的使用,不然你无法看懂下面代码

    学习requests库,请看我另外一篇文章,里面对requests库进行了详细的讲解Python模块-Requests学习

    爬取豆瓣top250第一页数据

    #-*- coding =utf-8 -*-
    import requests
    
    def askUrl(url):
        head = { #模拟浏览器头部信息,向豆瓣服务器发送消息
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.69 Safari/537.36 Edg/81.0.416.34"
        # 用户代理:告诉豆瓣服务器,我们是什么类型的浏览器(本质上是告诉浏览器我们可以接收什么水平的文件内容)
        }
        html=""  #用来接收数据
        r = requests.get(url, headers = head) #get方式发送请求
        html = r.text #接收数据
        print(html)  
        return html
    
    if __name__ == "__main__": # main函数用于测试程序
        askUrl("https://movie.douban.com/top250?start=") #调用函数
    

    可以看到成功的爬取到豆瓣top250第一页的数据

    image-20200327113957848

    爬取豆瓣top250所有的10页数据数据

    #-*- coding =utf-8 -*-
    import requests
    
    #爬取一个页面
    def askUrl(url):
        head = { #模拟浏览器头部信息,向豆瓣服务器发送消息
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.69 Safari/537.36 Edg/81.0.416.34"
        # 用户代理:告诉豆瓣服务器,我们是什么类型的浏览器(本质上是告诉浏览器我们可以接收什么水平的文件内容)
        }
        #html=""
        r = requests.get(url, headers = head)
        html = r.text
        print(html)
    
    # 爬取所有页面
    def getData(baseurl):
        for i in range(0, 10):
            url = baseurl + str(i * 25)
            html = askUrl(url)
    
    if __name__ == "__main__": # main函数用于测试程序
        baseurl = "https://movie.douban.com/top250?start="
        getData(baseurl)
    

    可以看到排名250的梦之安魂曲也被成功爬取到

    image-20200327115150029

    相关文章

      网友评论

        本文标题:Python爬虫学习(更新中)

        本文链接:https://www.haomeiwen.com/subject/vorsuhtx.html