Python NLTK 處理原始文本
作者:白寧超
2016年11月8日22:45:44
摘要:NLTK是由賓夕法尼亞大學計算機和信息科學使用python語言實現的一種自然語言工具包,其收集的大量公開數據集、模型上提供了全面、易用的接口,涵蓋了分詞、詞性標注(Part-Of-Speech tag, POS-tag)、命名實體識別(Named Entity Recognition, NER)、句法分析(Syntactic Parse)等各項 NLP 領域的功能。本文主要介紹:1)怎樣編寫程序訪問本地和網絡上的文件,從而獲得無限的語言材料?2)如何把文檔分割成單獨的單詞和標點符號,並進行文本語料上的分析?3)怎樣編寫程序產生格式化輸出,並把結果保存在文件中?關於Python基礎知識可以參看本人的【Python五篇慢慢彈】系列文章(本文原創編著,轉載注明出處:Python NLTK處理原始文本)
目錄
【Python NLP】干貨!詳述Python NLTK下如何使用stanford NLP工具包(1)
【Python NLP】Python 自然語言處理工具小結(2)
【Python NLP】Python NLTK 走進大秦帝國(3)
【Python NLP】Python NLTK獲取文本語料和詞匯資源(4)
【Python NLP】Python NLTK處理原始文本(5)
關於處理原始文本部分導入語句:
>>> from __future__ import division >>> import nltk,re,pprint
1 從網絡和硬盤訪問文本(在線獲取傷寒雜病論)
python網絡訪問程序:
>>> from __future__ import division >>> import nltk,re,pprint >>> from urllib.request import urlopen >>> url=r'http://www.gutenberg.org/files/24272/24272-0.txt' >>> raw=urlopen(url).read() >>> raw = raw.decode('utf-8') >>> len(raw) 70306 >>> raw[2000:2500]
運行結果:
對其中文分詞:
>>> from nltk.tokenize import StanfordSegmenter >>> segmenter = StanfordSegmenter( path_to_jar=r"E:\tools\stanfordNLTK\jar\stanford-segmenter.jar", path_to_slf4j=r"E:\tools\stanfordNLTK\jar\slf4j-api.jar", path_to_sihan_corpora_dict=r"E:\tools\stanfordNLTK\jar\data/", path_to_model=r"E:\tools\stanfordNLTK\jar\data\pku.gz", path_to_dict=r"E:\tools\stanfordNLTK\jar\data\dict-chris6.ser.gz" ) >>> result = segmenter.segment(raw) >>> result[1000:2500]
分詞結果:
2 在線獲取處理HTML文本(紅樓夢)
在線獲取html文本資料:
>>> import re,nltk >>> from urllib.request import urlopen >>> url='http://www.gutenberg.org/cache/epub/24264/pg24264-images.html' >>> html=urlopen(url).read() >>> html=html.decode('utf-8') >>> html[5000:5500]
運行結果:
相關正則知識:
- \d 匹配一個數字
- \w 匹配一個字母或者數字
- * 任意個字符(包括0個),
- + 至少一個字符
- ? 0個或1個字符
- {n} n個字符
- {n,m} n-m個字符
- \s 匹配一個空格
- \s+ 至少有一個空格
- \d{3,8} 表示3-8個數字,例如'1234567'
- \d{3}\s+\d{3,8}
- [0-9a-zA-Z\_] 匹配一個數字、字母或者下划線
- [0-9a-zA-Z\_]+ 匹配至少由一個數字、字母或者下划線組成的字符串,
- 比如'a100','0_Z','Py3000'等等;
- [a-zA-Z\_][0-9a-zA-Z\_]*可以匹配由字母或下划線開頭,后接任意個由一個數字、字母或者下划線組成的字符串,也就是Python合法的變量
- [a-zA-Z\_][0-9a-zA-Z\_]{0, 19}更精確地限制了變量的長度是1-20個字符(前面1個字符+后面最多19個字符)
- A|B可以匹配A或B,所以(P|p)ython可以匹配'Python'或者'python'
- ^表示行的開頭,^\d表示必須以數字開頭
- $表示行的結束,\d$表示必須以數字結束
正則表達式進行數據清洗:
>>> len(html) 962651 >>> strhtml=re.sub("[\s+\.\!\/_,$%^*(+\"\']+|[+——!,。??、~@#¥%……&*()]+|[A-Za-z0-9]+","",html)#去掉中英文符號 >>> len(strhtml) 781150 >>> strhtml[5000:5500]
清洗后結果:
紅樓夢進行中文分詞
>>> # 紅樓夢進行中文分詞 >>> from nltk.tokenize import StanfordSegmenter >>> segmenter = StanfordSegmenter( path_to_jar=r"E:\tools\stanfordNLTK\jar\stanford-segmenter.jar", path_to_slf4j=r"E:\tools\stanfordNLTK\jar\slf4j-api.jar", path_to_sihan_corpora_dict=r"E:\tools\stanfordNLTK\jar\data/", path_to_model=r"E:\tools\stanfordNLTK\jar\data\pku.gz", path_to_dict=r"E:\tools\stanfordNLTK\jar\data\dict-chris6.ser.gz" ) >>> result = segmenter.segment(raw)
查找分析:查找“曰”后面的內容
re.findall(r'(曰.{,3})',strhtml)
備注:處理搜索引擎的結果:基於自己配置的搜索引擎處理
3 處理RSS訂閱
>>> import feedparser #feedparser需要在python庫中下載 >>> llog=feedparser.parse(url)
4 讀取本地文件:strip()方法刪除輸入行結尾的換行符
方法一:
>>> f=open(r"E:\dict\q0.txt","r") >>> for line in f: print(line.strip())
方法二:
>>> with open(r"C:\Users\cuitbnc\Desktop\dqdg.txt","r+") as f: str=f.read()
方法三:
>>> import nltk >>> path=nltk.data.find(r'C:\Users\cuitbnc\Desktop\dqdg.txt') >>> raw=open(path,'rU').read() >>> len(raw) 673167 >>>
PDF或者MSWord以及其他二進制提取文本,利用第三方函數庫pypdf和pywin32
>>> raw=open(r"E:\dict\q0.txt","r").read() >>> tokens=nltk.word_tokenize(raw) >>> words=[w for w in tokens] >>> vocab=sorted(set(words)) >>> vocab
5 字符串:最底層的文本處理
有用的字符串方法:
- s.find(t) 字符串s中包含t的第一個索引s.rfind(t) 字符串s中包含t的最后一個索引
- s.index(t) 與s.find(t)類似
- s.rindex(t) 與s.rfind(t)類似
- s.join(text)
- s.split(t) 字符串分割
- s.splitlines()
- s.lower()
- s.upper()
- s.titlecase() s首字母大寫
- s.strip() 返回一個沒有首尾空白字符的s的復制
- s.replace(t,u) 用u替換s中的t
鏈表和字符串的差異:字符串和鏈表都是一種序列,可以通過索引抽取他們一部分,可以切片,可以合並。但是,鏈表和字符串不能連接
6 使用Unicode進行文字處理
解碼:文件中的文本都有特定的編碼,需要一些機制將文本翻譯成Unicode的過程就是解碼。 編碼:將Uniocde寫入一個文件或者終端,首先需要將Unicode轉化為合適的編碼,這個過程就是編碼
中文解碼問題
>>> raw=open(r"E:\dict\text.txt","r").read() Traceback (most recent call last): File "<pyshell#18>", line 1, in <module> raw=open(r"E:\dict\text.txt","r").read() UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 16: illegal multibyte sequence >>> import codecs >>> f=codecs.open(r"E:\dict\text.txt",'r',encoding="utf-8").read()
ord()查找字符的整數序列
>>> ord('a') 97 >>> ord('f') 102
7 使用正則表達式檢測詞組搭配
import re 導入re函數庫
re.search('ed$',w)查詢w字符串中是都ed結尾匹配 [w for w in wordlist if re,search('ed$',w)]
通配符“.”可以用來匹配任何單個字符。例如:有一個8個字母組成的字謎,j是第三個字母,t的第六個字母,每個空白單元格用句點隔開.(^字符串開始,$字符串結束)
[w for w in wordlist if re.search('^..j..t..$',w)]
計算文本中詞出現次數 sum(w for w in text if re.search('^e-?mail$',w))
搜索數字
[w for w in wordlist if re.search('^[0-9]+\.[0-9]+$',w)]
[w for w in wordlist if re.search('^[0-9]{4}$',w)]
python正則表達式基本元字符
- . 通配符,匹配所有字符
- ^abc 匹配以abc開始的字符串
- abc$ 匹配以abc結尾的字符串
- [abc] 匹配字符集合
- [A-Z0-9] 匹配字符范圍
- ed|ing|s 匹配指定的字符串,諸如ed或者ing或者s
- * 前面項目0個或者多個,如a*/[a-z]* (也叫Kleene閉包)
- + 前面項目1個或者多個,如a+、[a-z]+
- ? 前面項目0個或者1個,如a?、[a-z]?
- {n} 重復n次
- {n,} 至少重復n次
- {,n} 重復不多於n次
- {m,n} 至少重復m次不多於n次
- a(b|c)+ 括號表示操作符的范圍
- 正則表達式符號:
- \b 詞邊界
- \d 任何數字等於[0-9]
- \D 任何非數字等於[^0-9]
- \s 任何空白字符[\t\n\r\f\v]
- \S 任何非空白字符[^\t\n\r\f\v]
- \w 任何字母[A-Za-z0-9]
- \W 任何非字母[^A-Za-z0-9]
- \t 制表符
- \n 換行符
指定條件查詢分析:
>>> f=codecs.open(r"E:\dict\q0.txt",'r').read() >>> import re >>> re.findall(r"大秦",f) ['大秦'] >>> re.findall(r"龐涓",f) ['龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓', '龐涓'] >>> len(re.findall(r"龐涓",f)) 33 >>>
【推薦】