Python从网页文件获取纯文本并拆分文本文件

从HTML文件获取纯文本

通过BeautifulSoup获取纯文本

之前是通过BeautifulSoup (bs4)获取纯文本的,简单演示如下:

from bs4 import BeautifulSoup

htmfile = 'myweb.htm'
html = open(htmfile, 'r', encoding='utf-8')
htmlpage = html.read()
soup = BeautifulSoup(htmlpage.strip(), 'html.parser')
print(soup.text)

但是这样做的问题在于,其控制文本的格式或许与浏览器端显示的不一样
浏览器端显示的格式:


2018-06-01 14_36_17-Document.png

bs4抓取的文本格式如下:


2018-06-01 15_06_04-.png

为什么会这样呢?
因为在html源码中,存在这样的换行:
2018-06-01 15_09_30-Document.png

可以理解为bs4仅仅将html中的tag什么的去除了,但是并没有考虑格式与浏览器显示一致。

经过一番搜索,终于找到相应的方案

通过HTMLParser获取纯文本

HTMLParser是可以无视tag中的换行符的,如同浏览器一样,只要在tag中的文本,如<p>等,无论是否换行,在浏览器都是显示为一行。
安装:

pip install HTMLParser

但是安装之后运行,或许会提示找不到markupbase module的错误。
可以去如下地址下载:markupbase
然后将_markupbase.py更名为markupbase.py,并拷贝到python安装路径的:Lib\site-packages目录下,如: D:\python36\Lib\site-packages
具体的代码如下,我是将其单独写在一个python代码文件中,方便重用:

from re import sub
from sys import stderr
#need download https://pypi.org/project/micropython-_markupbase/3.3.3-1/#files,
#  and copy _markupbase.py to \Lib\site-packages, then rename it to markupbase.py
# this library make html content to be right format
# 不能直接使用HTMLParser,而是用html.parser,
# 否则如果环境是python3.x,会遇到兼容问题
# from HTMLParser import HTMLParser
from html.parser import HTMLParser
from traceback import print_exc
from bs4 import BeautifulSoup

class _DeHTMLParser(HTMLParser):
    def __init__(self):
        HTMLParser.__init__(self)
        self.__text = []

    def handle_data(self, data):
        text = data.strip()
        if len(text) > 0:
            text = sub('[ \t\r\n]+', ' ', text)
            self.__text.append(text + ' ')

    def handle_starttag(self, tag, attrs):
        if tag == 'p':
            self.__text.append('\n\n')
        elif tag == 'br':
            self.__text.append('\n')
        elif tag == 'div':
            self.__text.append('\n')

    def handle_startendtag(self, tag, attrs):
        if tag == 'br':
            self.__text.append('\n\n')

    def text(self):
        return ''.join(self.__text).strip()

def dehtml(text):
    try:
        parser = _DeHTMLParser()
        parser.feed(text)
        parser.close()
        return parser.text()
    except:
        print_exc(file=stderr)
        #If invoke exception, then return text by beautifulsoup
        soup = BeautifulSoup(text, 'html.parser')
        return soup.text

之后提取的文本就是符合我们格式要求的:


2018-06-01 15_19_08-htmltotext [D__Blade_MorningStar.Demo_github_htmltotext] - ..._txt_159343589_0cd.png

主程序代码

包括:解压htm压缩包,提取纯文本,拆分文本文件
拆分文本文件,我是每500行就拆为一个小的文本文件
但是,考虑到避免将一个完整的段落文字拆到几个文本文件中,加入了最后一行必须以句号:.为结尾(相对英文文件文本)如果是汉语,可以加入结尾是否是汉字句号:。的判断。
压缩文件相对于程序代码路径:./htmzip
解压的htm文件相对于程序代码路径:./htm
txt文件相对于程序代码路径:./txt
完整主程序代码:

import os
import parsehtmltext
import zipfile

def startjob():
    zipfilelist = getfilelist('./htmzip', '.zip')
    count = 1
    for filepath in zipfilelist:
        (filefolder, zipfilename) = os.path.split(filepath)
        print('handle the %d file: %s start' % (count, zipfilename))
        unzipfolder = './htm/%s' % (zipfilename)
        unzip(filepath, unzipfolder)
        htmlfilelist = getfilelist(unzipfolder, '.htm')
        if len(htmlfilelist) > 0:
            txtfilelist = splithtmltotxt(htmlfilelist[0],
                                         './txt/%s' % (zipfilename))
            print(txtfilelist)
        count += 1

def getfilelist(folderpath, extension):
    filelist = []
    for (root, dirs, files) in os.walk(folderpath):
        for filename in files:
            if filename.lower().endswith(extension.lower()):
                filepath = os.path.join(root, filename).replace('\\','/')
                filelist.append(filepath)
    return filelist

def splithtmltotxt(htmfile, txtfolder):
    html = open(htmfile, 'r', encoding='utf-8')
    htmlpage = html.read()
    wholetextlines = parsehtmltext.dehtml(htmlpage).split('\n')
    if len(wholetextlines) == 1 and len(wholetextlines[0].strip()) > 100:
        wholetextlines = wholetextlines[0].split('.')
    testblock = []

    if os.path.isdir(txtfolder):
        pass
    else:
        os.mkdir(txtfolder)
    txtfilelist = []
    #整体计数器
    count = 1
    #用于单文本文件行数的计数器
    eachcount = 0
    #文本文件数量的计数器
    txtfilecount = 1
    totalcount = len(wholetextlines)
    # print(wholetextlines)
    # print(totalcount)
    for line in wholetextlines:
        if line.split():
            testblock.append(line.strip() + '\n')
            eachcount += 1
        # print('each count is %d, count is %d, total count is %d' % (eachcount, count, totalcount))
        if (eachcount >= 500
            and (line.endswith('\n') or line.strip().endswith('.')))\
                or count == totalcount:
            txtfilename = '%s/%d.txt' % (txtfolder, txtfilecount)
            with open(txtfilename, 'w', encoding='utf-8') as f:
                f.writelines(testblock)
            # print('save txt file: %s'% txtfilename)
            txtfilelist.append(txtfilename)
            #reset single counter
            testblock = []
            eachcount = 0
            txtfilecount += 1
        count += 1
    return txtfilelist

def unzip(sourcefile, unzipfolder):
    with zipfile.ZipFile(sourcefile) as zip_file:
        if os.path.isdir(unzipfolder):
            pass
        else:
            os.mkdir(unzipfolder)
        for names in zip_file.namelist():
            zip_file.extract(names, unzipfolder)

if __name__ == '__main__':
    startjob()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容