美文网首页
简单利用python处理文件

简单利用python处理文件

作者: TK丰 | 来源:发表于2019-12-27 16:21 被阅读0次

    之前我在真·从零开始使用Requests制作简单爬虫中爬取了小说下来,本来想搭建个服务器,做一个个人的小说平台,发现爬下来的文件中,有大量的javascript以及对原地址请求的动作等,导致加载速度很慢。为了解决这个问题,需要把上述的内容处理掉,所以在此也写写,如何简单地利用python批量处理文件

    一、打开文件操作

    常用python打开文件有2种方式:

    # 方式1
    f = open('a.txt','r')
    # 方式2
    with open('a.txt', 'r') as f:
    

    我推荐用的是with open。当直接使用open是打开一个文件流后,是需要后续手工写f.close()关闭文件流的。对于读的操作来说,关闭文件流与否影响不会特别大,但是对于写入的操作来说,如果不及时关闭,会导致写入丢失。而with open的方法,他是不需要后续再调用close()的方法,至于为什么?属于python 迭代器的范畴,大家可以自行百度一下,这里只要知道即可。

    with open 以及 open除了一个是迭代器实现,一个不是之外,在参数使用上、取文件内容的方式上,没有什么不同。因为懒,所以下文统一用with open来讲解。

    1.with open的参数讲解
    # filename代表文件名,建议字符串前面带个u,例如:u'a.txt'
    with open (filename, mode) as f:
    

    mode的方法,需要带'',例如:'w'

    参数 解释
    r \color{blue}{只读}方式打开文件,从头开始读取文件内容
    rb \color{blue}{二进制}格式打开一个文件用于\color{blue}{只读},从头开始读取文件内容
    r+ 打开一个文件用于\color{blue}{读写}。若文件不存在,报错,若文件存在,从头开始\color{red}{覆盖}原文件内容。另外,先读后写,读取内容后再写入。
    rb+ 以二进制格式打开一个文件用于\color{blue}{读写}。若文件不存在,报错,若文件存在,从头开始\color{red}{覆盖}原文件内容。另外,先读后写,读取内容后再写入。
    w 打开一个文件只用于\color{blue}{写入}。如果该文件不存在,创建新文件。如果该文件已存在则将其\color{red}{覆盖}。与r+不同的地方在于,r+是从内容的开头开始覆盖,w相当于把整个文件删掉,重新创建的方式覆盖。
    wb 以二进制格式打开一个文件只用于\color{blue}{写入}。如果该文件不存在,创建新文件。如果该文件已存在则将其\color{red}{覆盖}。与rb+不同的地方在于,rb+是从内容的开头开始覆盖,wb相当于把整个文件删掉,重新创建的方式覆盖。
    w+ 打开一个文件用于\color{blue}{读写}。如果该文件不存在,创建新文件。如果该文件已存在则将其\color{red}{覆盖}。与r+不同的地方在于,r+是从内容的开头开始覆盖,w+相当于把整个文件删掉,重新创建的方式覆盖。
    wb+ 以二进制格式打开一个文件用于\color{blue}{读写}。如果该文件已存在则将其\color{red}{覆盖}。如果该文件不存在,创建新文件。与rb+不同的地方在于,rb+是从内容的开头开始覆盖,wb+相当于把整个文件删掉,重新创建的方式覆盖。
    a 打开一个文件用于\color{blue}{追加}。如果没有该文件,则创建该文件,在文件末尾(空文件的开头与末尾在同一个位置)插入新的内容。
    ab 以二进制格式打开一个文件用于\color{blue}{追加}。如果没有该文件,则创建该文件,在文件末尾(空文件的开头与末尾在同一个位置)插入新的内容。
    a+ 打开一个文件用于\color{blue}{读写}。如果没有该文件,则创建该文件,在文件末尾(空文件的开头与末尾在同一个位置)插入新的内容。
    ab+ 以二进制格式打开一个文件用于\color{blue}{追加}。如果没有该文件,则创建该文件,在文件末尾(空文件的开头与末尾在同一个位置)插入新的内容

    读写的意思是,既可以读也可以写。当我们想修改原文件的内容然后覆盖的话,就会选用读写模式,可读可写,都需要用seek(0)后才可读。例如:f.seek(0)。

    快速记忆法:三个模式,r,w,a。两个数据,带b和不带b。以及分别带不带+号(能不能读写)。其实我一般就直接用r,w,a~hahahah

    2.文件的内容读取

    文件读取有几种方式,如下

    with open ('a.txt', r) as f:
        # 一次性读取整个文件的内容放到s中
        s = f.read()
    print (s)#输出整个文本 
    
    s = ''
    with open ('a.txt', r) as f:
        # 一次只从文件中读一行数据,所以需要用迭代的方式取
        for line in f:
            #把每一行都拼接到定义好的字符串上
            s += f.readline()
    print (s)#输出整个文本 
    
    with open ('a.txt', r) as f:
        #一次性读取整个文件,但是通过换行符,把文章分割成列表,通过操作列表来进行操作文本的数据
        s2 = f.readlines()
    print (type(s))#输出的是列表
    

    根据自己的需求,或者说根据机子的性能来选择不同的方式。一般来说,不是特别大的文件,都可以直接用read或者readlines。这两者的选择是,你之后是否需要针对每一行,或者某些行处理,如果是的话,直接用readlines会比较方便。

    3.提取所需的文件内容
    提取步骤
    a.分析原文件

    打开爬虫获得的原文件,看到


    txt文件

    一般爬虫获得的网页文件,都是由前端各种标签,以及真正的内容组成。所以我们需要找到真正内容所在的标签并提取即可

    b.寻找所需的内容以及规律
    找到标题的标签 找到正文的标签
    c.编写对应关于规则

    先去除其余一切无用的标签,两种方法,第一种方法使用split的方法

    split获得的是列表,所以采用[0]、[1].....的方式提取。
    简单理解:若要切割的元素在字符串中只出现一次,那么0代表的改元素的左边,1代表的是该元素的右边。
    若切割的元素会在字符串中出现多次,那么split会获得多个列表元素,根据需要选择。附上split的用法

    # 方法1使用split
    with open ('第123章.txt', 'r') as f:
      #因为单篇小说的大小其实很小,所以直接用read读到内存中
        s = f.read()
    # 用split的方法把title标签里的title直接切割出来
    title = s.split('<title>')[1].split('</title>')[0]
    # 用split的方法把content里的内容切割出来
    #后面的为什么选择<br />?首先这个是一个换行的标签,在小说网站中,一般用于正文的换行。
    #对此通过观察原文件可发现,<br />的确出现在正文中。
    #最后的[:-1],是选取除了最后一项的所有项,为什么去掉最后一项?
    #大家可以试试contentList = s.split('<div id="content">')[1].split('<br />')观察一下
    contentList = s.split('<div id="content">')[1].split('<br />')[:-1]
    # 因为split切出来的是一个列表,选取其中一项则为字符串。
    #而我们这里选取的是除了最后一项的其他所有项,所以得到的是一个列表,可通过我设置的变量名知道
    #所以我们需要用join的方法,把列表串联成字符串,并且把“&nbsp”的空格html标签替换成空格字符“ ”。
    #串联成字符串后发现,多了一个<p>,所以也去掉
    content = ''.join(contentList).replace('&nbsp;',' ').split('<p>')[0]
    #打印看看结果
    print (title)
    print (content)
    
    

    join的作用,用来把可迭代的对象,例如列表,元组(严格意义上来说跟数组不同)等里面的元素串联成一个字符串。用法:str.join(sequence)

    #!/usr/bin/python
    # -*- coding: UTF-8 -*-
    
    str = "-";
    seq = ("a", "b", "c"); # 字符串序列,元组、列表,反正是可迭代的对象都可以
    result = str.join( seq )
    print (result)
    

    输出“a-b-c”

    结果

    第二种方法,使用re的方法

    # 加载正则库
    import re
    with open ('第123章.txt', 'r') as f:
    #因为单篇小说的大小其实很小,所以直接用read读到内存中
        s = f.read()
    # 把title标签之间的内容全部匹配
    titleRe = re.compile('(?<=<title>).*?(?=</title>)')
    #匹配<div id="content">以及最后一次出现的<br /><p>标签之间的全部内容
    contentRe = re.compile('(?<=<div id="content">)[\s\S]*(?=<br /><p>)')
    # 用findall的方式返回列表形式
    title = titleRe.findall(s)
    #输出title的值
    print (title[0])
    # 用findall的方式返回列表形式
    contentList = contentRe.findall(s)
    # 获取列表的元素,随后把&nbsp;以及<br />换成字符串的形式
    content = contentList[0].replace('&nbsp;',' ').replace('<br />','\n')
    #输出content的值
    print (content)
    
    结果展示

    会发现正则匹配出来的换行好像比split出来的多。是因为spilt的时候我们是以<br />也就是换行符切割,也就是会丢失一个换行符,而正则是匹配的方式会保留下来。可以通过对.replace('<br />','\n',2).replace('<br />', '')来处理。其中2的意思代表每遇到2个<br />才替换第二个<br />为换行符

    一般我们会两种方法混合着用,这样的效率还有效果是最好的。其实,也就是怎么方便怎么来XD。附上正则语法表


    最后写入到文件中

    一般我会将处理过的文本保存成新的文件,源数据不会去覆盖,这样有助于之后的多次利用

    #为可与读的区分,所以 as 后面用了其他变量名,随意取
    with open ('newfilename.txt', 'w' ) as f_write:
      #用write直接写入即可
        f_write.write(s)
    

    参考代码

    import re,os
    
    BaseFilename = u"第%d章.txt"
    #输入你想从哪一章开始处理
    n = 121
    
    #当仍有文章时,while里的条件用于寻找文件,文件存在时返回True
    while os.path.isfile(BaseFilename%n):
        with open (BaseFilename%n, 'r') as f:
            s = f.read()
        titleRe = re.compile('(?<=<title>).*?(?=</title>)')
        contentRe = re.compile('(?<=<div id="content">)[\s\S]*(?=<br /><p>)')
        title = titleRe.findall(s)
        content = contentRe.findall(s)
        content = content[0].replace('&nbsp;',' ').replace('<br />','\n',2).replace('<br />','')
        #在子文件夹new中放新的文本
        newFileName = 'new/第%d章.txt'
        with open (newFileName%n, 'w') as FWrite:
            #写入标题和正文
            FWrite.write(title[0] + '\n' + content)
        #文章数加1,继续进行循环
        n += 1
    

    That's all.Thank's for your attention

    相关文章

      网友评论

          本文标题:简单利用python处理文件

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