文章目录

  • 项目简介:英文文献词频搞定三大步骤
  • One: 英文文献PDF转成纯文本TXT格式
  • Two: 纯文本TXT格式的清洗与英文词频统计
  • Three: 对英文词频进行精准翻译


项目简介:英文文献词频搞定三大步骤

一直以来,读透一篇英文文献并掌握其传递的核心思想一直是一件棘手的事情。相信饱受英文文献折磨的同学,也对于文献中出现的生僻词汇和专业词汇也十分困扰。本文从英文文献的词频的角度提供技术解决方案,主要包括三个主要的部分:

  1. 第一步,将英文文献由PDF格式转化成纯文本的格式;
  2. 第二步,对纯文本的英文文献进行清洗,并进行词频统计;
  3. 第三步,对统计的词频借助网络爬虫进行精准的翻译。

One: 英文文献PDF转成纯文本TXT格式

前期准备

运行程序版本:Python 3.7
集成开发环境:Pycharm 2019.3 Pro
安装pdfminer模块:

  • 注意,在Pycharm提供的第三方库中,有很多pdfminer库,本文使用的是pdfminer3k补充pdfminersix也可以进行PDF的转化,但是它与pdfminer3k中的某个文件发生冲突,请不要两个包放在一个环境中进行调用。

另外,可以通过pip直接安装pdfminer3k

pip install pdfminer3k

模块导入

1.导入sys模块,为了读取本地硬盘中,英文文献文件夹中的多个文件名称

import sys
import importlib
importlib.reload(sys)

2.导入pdfminer3k核心模块

from pdfminer.pdfparser import  PDFParser,PDFDocument
from pdfminer.pdfinterp import PDFResourceManager,PDFPageInterpreter
from pdfminer.converter import PDFPageAggregator
from pdfminer.layout import LTTextBoxHorizontal,LAParams
from pdfminer.pdfinterp import PDFTextExtractionNotAllowed

3.构建解析函数parse()

def parse(text_path):
    """解析PDF文本,并保存到TXT文件中"""
    fp = open(text_path,'rb') #'rb'表示解读为二进制数据
    #用文件对象创建一个PDF文档分析器
    parer = PDFParser(fp)
    #创建一个PDF文档
    doc = PDFDocument()
    #连接分析器,与文档对象--也就说内容与载体连接
    parer.set_document(doc)
    doc.set_parser(parer)

    #提供初始化密码,如果没有密码,就创建一个空的字符串
    doc.initialize()

    #检测文档是否提供txt格式转化,不提供就忽略
    if not doc.is_extractable:
        raise PDFTextExtractionNotAllowed
    else:
        #创建PDF,资源管理器,来共享资源
        rsrcmgr = PDFResourceManager()
        #创建一个PDF设备对象
        laparams = LAParams()
        device = PDFPageAggregator(rsrcmgr,laparams=laparams)
        #创建一个PDF解释其对象
        interpreter = PDFPageInterpreter(rsrcmgr,device)

        #循环遍历列表,每次处理一个page内容
        #doc.get_pages() 获取pages列表
        for page in doc.get_pages():
            interpreter.process_page(page)
            #接受该页面的LTPage对象
            layout = device.get_result()
            #这里layout是一个LTpage对象,里面存放着这个page解析出的各种对象
            #一般包括LTTextBox,LTFigure,LTImage,LTTextHorizontal等等
            #想要获得文本就获得对象的text属性
            for x in layout:
                if(isinstance(x,LTTextBoxHorizontal)):
                    with open(r"prediction_text.txt",'a',encoding= 'utf-8') as f:
                        results = x.get_text()
                       # return results
                        f.write(results+'\n')

4.读取本地文件的所有英文文献的名称,并放在pdfs列表中

import glob
pdf_path = r'G:\pythonPjc\PDFminer3k_Project\document_translation'
pdfs = glob.glob("{}/*.pdf".format(pdf_path))

python程序设计文献阅读 python处理文献_python程序设计文献阅读


5.设置for循环,对列表中的PDF进行解析,并将解析失败的文件名称储存

list= []
for pdf in pdfs:
   # parse(pdf_path)
   print(pdf)
   try:
      parse(pdf)
   except:
      list.append(pdf)
with open(r"list_url.txt", 'a', encoding='utf-8') as f:
   # return results
   sep = ';'
   f.write(sep.join(list))

至此,英文文献PDF已经全部转成TXT纯文本格式

Two: 纯文本TXT格式的清洗与英文词频统计

模块导入

import sys, re,collections,nltk
from nltk.stem.wordnet import WordNetLemmatizer
from nltk.tokenize import word_tokenize
import xlwt

文本清洗

由于直接生成的英文纯文本文档格式比较杂乱,比如需要做一些缩写拆解,大小写还原,格式还原等一系列工作,比如

can’t 应该还原成 can not
I’ve 应该还原成 i have

故借助正则表达进行清洗,此部分参照公众号“数据Chocolate”(2019-06-23)的文章编写的正则规则。

# patterns that used to find or/and replace particular chars or words
# to find chars that are not a letter, a blank or a quotation
pat_letter = re.compile(r'[^a-zA-Z \']+')
# to find the 's following the pronouns. re.I is refers to ignore case
pat_is = re.compile("(it|he|she|that|this|there|here)(\'s)", re.I)
# to find the 's following the letters
pat_s = re.compile("(?<=[a-zA-Z])\'s")
# to find the ' following the words ending by s
pat_s2 = re.compile("(?<=s)\'s?")
# to find the abbreviation of not
pat_not = re.compile("(?<=[a-zA-Z])n\'t")
# to find the abbreviation of would
pat_would = re.compile("(?<=[a-zA-Z])\'d")
# to find the abbreviation of will
pat_will = re.compile("(?<=[a-zA-Z])\'ll")
# to find the abbreviation of am
pat_am = re.compile("(?<=[I|i])\'m")
# to find the abbreviation of are
pat_are = re.compile("(?<=[a-zA-Z])\'re")
# to find the abbreviation of have
pat_ve = re.compile("(?<=[a-zA-Z])\'ve")

词频统计

1.对词汇换行情况进行处理

由于在英文论文中常常出现一个单词换行的情况,导致有些词汇分裂,因此,在处理文本之前,对这种情况进行处理。处理的思路是:逐行读取纯文本文件,然后横向合并。借助正则表达式对词汇换行的情况进行处理。

def open_file(file_path):
    with open(file_path, encoding='utf-8') as f:
        # txt= f.read()
        txt0 = f.readlines()
        txt =[x.strip() for x in txt0]
        txt1 = " ".join(txt)
        txt2 = re.sub('(-\s)', '', txt1)
        return txt2

2.借助正则表达式,对缩写词汇进行替换

def replace_abbreviations(text):
    new_text = text
    new_text = pat_letter.sub(' ', text).strip().lower()
    new_text = pat_is.sub(r"\1 is", new_text)
    new_text = pat_s.sub("", new_text)
    new_text = pat_s2.sub("", new_text)
    new_text = pat_not.sub(" not", new_text)
    new_text = pat_would.sub(" would", new_text)
    new_text = pat_will.sub(" will", new_text)
    new_text = pat_am.sub(" am", new_text)
    new_text = pat_are.sub(" are", new_text)
    new_text = pat_ve.sub(" have", new_text)
    new_text = new_text.replace('\'', ' ')
    return new_text

3.对标点符号,以及文章中出现的大量的数字以及单个英文字符进行处理

def text_washing(text):
    new_text = re.sub('[,\.()":;!?@#$%^&*\d]|\'s|\'', '', text)  # txet wash
    new_text = re.sub("\W|[0-9]", " ", new_text)
    #deleting the solo character
    # 删掉单个字母
    txt4 = new_text.split(" ")
    list = []
    for i in txt4:
        i = i.strip()
        if len(i) > 2:
            list.append(i)
    wash_text = " ".join(list)
    return wash_text

4.对单词的词性进行还原,并借助停用词词典,对停用词进行剔除

def merge(text):
    words = text.split()
    new_words = []
    for word in words:
        if word:
            tag = nltk.pos_tag(word_tokenize(word)) # tag is like [('bigger', 'JJR')]
            pos = get_wordnet_pos(tag[0][1])
            if pos:
                lemmatized_word = lmtzr.lemmatize(word, pos)
                new_words.append(lemmatized_word)
            else:
                new_words.append(word)
    stopwords = [word.strip().lower() for word in open("stopwords.txt")]
    clean_tokens = [tok for tok in new_words if len(tok) > 1 and (tok not in stopwords)]
    return clean_tokens


def get_wordnet_pos(treebank_tag):
    if treebank_tag.startswith('J'):
        return nltk.corpus.wordnet.ADJ
    elif treebank_tag.startswith('V'):
        return nltk.corpus.wordnet.VERB
    elif treebank_tag.startswith('N'):
        return nltk.corpus.wordnet.NOUN
    elif treebank_tag.startswith('R'):
        return nltk.corpus.wordnet.ADV
    else:
        return ''

5.构建词频的统计函数

def append_ext(words_list):
    count = collections.Counter(words_list)
    words =count.most_common()
    new_words = []
    for item in words:
        word, count = item
        tag = nltk.pos_tag(word_tokenize(word))[0][1] # tag is like [('bigger', 'JJR')]
        new_words.append((word, count, tag))
    return new_words

6.将数据写入文件

def data_write(file_path, datas):
    f = xlwt.Workbook()
    sheet1 = f.add_sheet(u'sheet1', cell_overwrite_ok=True)  # 创建sheet
    # 将数据写入第 i 行,第 j 列
    j = 2
    for data in datas:
        for i in range(len(data)):
            sheet1.write(i, j, data[j])
        i = i + 1
    f.save(file_path)  # 保存文件

至此,我们将纯文本中的词汇进行了清洗和词频统计,效果图如下

python程序设计文献阅读 python处理文献_正则表达式_02

Three: 对英文词频进行精准翻译

模块导入

本部分主要借助urllib模块编写爬虫程序

from openpyxl import load_workbook
from openpyxl import Workbook
import json
import sys
from urllib.parse import urlparse, quote, urlencode, unquote
from urllib.request import urlopen
import re
import time

词汇翻译解析函数构建

调用有道翻译url,对词汇进行翻译。注意,经测试,有道翻译页面设置反爬虫机制,当抓取速度过快或者单位时间内抓取数量过多时,网页便拒绝访问。一个好的解决方案是,访问延迟,经验表明以3秒为时间间隔 比较合适。

def fetch(query_str):
    query = {"q": "".join(query_str)}  # list --> str: "".join(list)
    # print(query)
    url = 'https://fanyi.youdao.com/openapi.do?keyfrom=11pegasus11&key=273646050&type=data&doctype=json&version=1.1&' + urlencode(
        query)
    time.sleep(3)
    response = urlopen(url, timeout=3)
    html = response.read().decode('utf-8')
    return html

HTML解析函数的构建

def parse(html, num):
    d = json.loads(html)
    try:
        if d.get('errorCode') == 0:
            explains = d.get('basic').get('explains')
            result = str(explains).replace('\'', "").replace('[', "").replace(']', "")  # .replace真好用~
            sheet.cell(row=num, column=2).value = result
            num = num + 1
            for i in explains:
                print(i)
        else:
            print('无法翻译!****')
            sheet.cell(row=num, column=2).value = ' '  # 若无法翻译,则空出来
            num = num + 1
    except:
        print('****翻译出错!')  # 若无法翻译,则空出来
        sheet.cell(row=num, column=2).value = ' '
        num = num + 1

词汇翻译主函数

def main():
    Sheet1 = ExcelFile['Sheet1'];
    num = 1
    while (1):
        word = Sheet1.cell(row=num + 2, column=1).value
        if (word != None):
            print('正在翻译第', end='');
            print(num, end='');
            print('个单词')
            print(word)
            try:
                parse(fetch(str(word)), num)
            except:
                continue
            num += 1
            print()
            out.save('out.xlsx')
        else:
            print('翻译结束!')
            break
    ExcelFile.close()
    # out.save('word.xlsx')

至此,我们的全部工作已经完成,让我们看一下效果图吧!

python程序设计文献阅读 python处理文献_python_03


参考资料

[1] 自然语言处理 | NLTK英文分词尝试 [2] Python使用pdfminer解析PDF

[3] Python 3.6 中使用pdfminer解析pdf文件