Python日常-難啃的論文

劇情

這兩天在看論文,密密麻麻的英文,各種專有名詞,看得很頭痛。借助谷歌翻譯可以輔助理解(其實(shí)谷歌翻譯得挺不錯(cuò)的),就是用谷歌翻譯的時(shí)候遇到了一點(diǎn)麻煩,見下圖。

PDF格式的論文里文字選中的時(shí)候是這樣的:

論文選中

復(fù)制到記事本上是這樣的:

可以看到:

  • 很多單詞被截?cái)?,中間用‘-’進(jìn)行連接。
  • 完整的文本中間全是斷行。也就是說,在ASCII碼里有很多 ‘\n’ ,直接復(fù)制到Google的話,每一個(gè)'\n'之前的文本都會(huì)當(dāng)做一個(gè)句子去處理。

這樣翻譯效果就很差。需要手動(dòng)一個(gè)個(gè)把斷行給接起來。理想效果是這樣:

理想效果

論文里估計(jì)有幾百行近千行,這樣一行行地按Backspace鍵既乏味又蠢,對(duì)于一個(gè)程序員是不可忍受的。然后我就想搞一個(gè)Python腳本去處理。

開始動(dòng)手

思路很簡(jiǎn)單:

  • 先找一個(gè)pdf處理庫,把文字提取出來
  • 然后進(jìn)行字符串增刪操作,把斷句連起來
  • 把生成的文本調(diào)用Google API翻譯出來,或者模擬瀏覽器訪問 http://translate.google.cn ,把翻譯結(jié)果拿回來

先去Github搜索: python pdf process,結(jié)果如下:


第一個(gè)結(jié)果里依賴項(xiàng)太多了。而且列表里也沒啥好的庫,我懷疑關(guān)鍵詞是不是錯(cuò)了,就換成: python pdf extract。后來就找到了slate這個(gè)庫。后來又發(fā)現(xiàn)slate這個(gè)庫完全是基于pdfminer這個(gè)庫做的,我干脆就直接用pdfminer了。

去豆瓣的pypi國(guó)內(nèi)鏡像里看了一下,確實(shí)有pdfminer這玩意,就用pip把pdfminer給裝上了。因?yàn)樽C書的問題,我最后用的清華的源。安裝命令如下:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pdfminer

在pdfminer的repo里發(fā)現(xiàn)了一個(gè)腳本pdf2txt.py(地址),就是用來從pdf里提取文字的,很開心,直接用上了。第一步搞定。

文字再處理

從pdf2text.py中提取中夾雜大量斷行的文字到一個(gè)txt文件中,呈現(xiàn)如下效果:

思考一會(huì)后,我打算做如下的處理邏輯:

  • 只提取摘要后面的文字
  • 對(duì)于一行,如果只有數(shù)字和空格,則刪掉(因?yàn)檫@樣的行是葉號(hào)、頁腳)
  • 每一行都去掉末尾的‘\n’
  • 對(duì)于只有'\n'的一行,則多加一個(gè)'\n'換行符到新文本中
  • 去掉換行符后,如果行尾是'-',則刪掉

邊寫邊試,第二步也基本搞定了,最后在調(diào)用Google翻譯的時(shí)候遇到了一點(diǎn)麻煩,解析html時(shí)發(fā)現(xiàn)文字沒有翻譯出來,不知何故。但是最后一步已經(jīng)不重要了,時(shí)間寶貴,到此為止。

源代碼與處理效果

用腳本處理后的效果:

新文本
命令行
Google翻譯效果

最后附上源代碼:

import sys
from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdfparser import PDFParser
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfdevice import PDFDevice, TagExtractor
from pdfminer.pdfpage import PDFPage
from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter
from pdfminer.cmapdb import CMapDB
from pdfminer.layout import LAParams
from pdfminer.image import ImageWriter



"""
        print ('usage: %s [-d] [-p pagenos] [-m maxpages] [-P password] [-o output]'
               ' [-C] [-n] [-A] [-V] [-M char_margin] [-L line_margin] [-W word_margin]'
               ' [-F boxes_flow] [-Y layout_mode] [-O output_dir] [-R rotation] [-S]'
               ' [-t text|html|xml|tag] [-c codec] [-s scale]'
               ' file ...' % argv[0])
"""
# main
def extract_text(filename, password_param, output_file):

    # debug option
    debug = 0
    # input option
    password = ''
    pagenos = set()
    maxpages = 0
    # output option
    outfile = None
    outtype = None
    imagewriter = None
    rotation = 0
    stripcontrol = False
    layoutmode = 'normal'
    codec = 'utf-8'
    pageno = 1
    scale = 1
    caching = True
    showpageno = True
    laparams = LAParams()

    if filename.strip()[-4:] != '.pdf':
        print 'file type is not pdf!'
        return
    elif output_file is not None:
        outfile = output_file
    else:
        outfile = filename.strip()[:-4] + '.txt'
        print 'output file path: %s' % outfile
    if password_param is not None:
        password = password_param

    PDFDocument.debug = debug
    PDFParser.debug = debug
    CMapDB.debug = debug
    PDFPageInterpreter.debug = debug
    #
    rsrcmgr = PDFResourceManager(caching=caching)
    if not outtype:
        outtype = 'text'
        if outfile:
            if outfile.endswith('.htm') or outfile.endswith('.html'):
                outtype = 'html'
            elif outfile.endswith('.xml'):
                outtype = 'xml'
            elif outfile.endswith('.tag'):
                outtype = 'tag'
    if outfile:
        outfp = file(outfile, 'w')
    else:
        outfp = sys.stdout
    if outtype == 'text':
        device = TextConverter(rsrcmgr, outfp, codec=codec, laparams=laparams,
                               imagewriter=imagewriter)
    elif outtype == 'xml':
        device = XMLConverter(rsrcmgr, outfp, codec=codec, laparams=laparams,
                              imagewriter=imagewriter,
                              stripcontrol=stripcontrol)
    elif outtype == 'html':
        device = HTMLConverter(rsrcmgr, outfp, codec=codec, scale=scale,
                               layoutmode=layoutmode, laparams=laparams,
                               imagewriter=imagewriter, debug=debug)
    elif outtype == 'tag':
        device = TagExtractor(rsrcmgr, outfp, codec=codec)
    else:
        return
    fname = filename
    fp = file(fname, 'rb')
    interpreter = PDFPageInterpreter(rsrcmgr, device)
    print 'extracting text in pdf ... ...'
    page_cnt = 1
    for page in PDFPage.get_pages(fp, pagenos,
                                maxpages=maxpages, password=password,
                                caching=caching, check_extractable=True):
        page.rotate = (page.rotate+rotation) % 360
        print 'processing page %d ...' % page_cnt
        interpreter.process_page(page)
        page_cnt += 1
    fp.close()
    device.close()
    outfp.close()
    print 'text has been written into %s ' % outfile
    return outfile


def check_line_valid(line):# only line like '1 ' will be invalid
    line = line[:-1]
    if line == '':
        return True
    digits = '0123456789'
    for c in line:
        if c != ' ' and c not in digits:
            return True
    return False


def process_line(line):
    if line != '\n':  # single line with '\n' will be ignored
        line = line[:-1]
        if line[-1:] == '-':
            line = line[:-1]
        else:
            line += ' '
    else:
        line += '\n'
    return line

"""
"""
def reformat_output_file(outfile):
    text_reformated = ''
    file_handler = open(outfile)
    line = file_handler.readline()
    recording = False
    while line:
        if line == 'Abstract\n':
            recording = True
        if recording is True:
            if check_line_valid(line):
                line = process_line(line)
                text_reformated += line
        line = file_handler.readline()
    file_handler.close()
    print '%s has been reformated.' % outfile
    file_reformated_name = outfile[:-4] + '.reformated.txt'
    file_handler = open(file_reformated_name, 'w')
    file_handler.write(text_reformated)
    return text_reformated

of = extract_text('H://Hendricks_Deep_Compositional_Captioning_CVPR_2016_paper.pdf', '', None)
tr = reformat_output_file(of)

代碼說明:

  • 依賴項(xiàng):pdfminer
  • 環(huán)境:Windows 10,Python 2.7
  • reformated后的文件會(huì)寫入源pdf所在目錄下的一個(gè)txt文件內(nèi)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,725評(píng)論 25 709
  • # Python 資源大全中文版 我想很多程序員應(yīng)該記得 GitHub 上有一個(gè) Awesome - XXX 系列...
    aimaile閱讀 26,822評(píng)論 6 427
  • 以往都是痛恨錯(cuò)誤的居多,比如說,你剛洗好的蔬菜,小孩子跑過來掀翻,正在炒菜的你,會(huì)是一種怎樣的心情。 相信大部分父...
    三十七度半1號(hào)閱讀 341評(píng)論 0 2
  • 這是一個(gè)很奇怪的命題,我實(shí)在不知道我的父母之間是否有愛情的存在。 在我的印象里,他們是一對(duì)怨偶,一直吵...
    課間操閱讀 402評(píng)論 2 1
  • 平時(shí)我是很少讀心靈雞湯類文字的,然而近來,不知是因?yàn)楹俚姆趴v擾亂了心緒,還是因?yàn)榇猴L(fēng)來了,吹亂了一池春水。心總難...
    一把紙傘碎江南閱讀 468評(píng)論 2 13

友情鏈接更多精彩內(nèi)容