Python读取文档

互联网并不是一个 HTML 页面的集合。它是一个信息集合,而 HTML 文件只是展示信息的一个框架而已。 如果我们的爬虫不能读取其他类型的文件,包括纯文本、PDF、图像、视频、邮件等,我们将会失去很大一部分数据。


1.文档编码

文档编码是一种告诉程序——无论是计算机的操作系统还是 Python 代码——读取文档的规则.通常可以根据文件的扩展名进行判断.


2.纯文本

from urllib.request import urlopen
textPage = urlopen("http://www.pythonscraping.com/pages/warandpeace/chapter1.txt")
print(textPage.read())

通常,当用 urlopen 获取了网页之后,我们会把它转变成 BeautifulSoup 对象,方便后面对 HTML 进行分析。在这段代码中,我们直接读取页面内容。你可能觉得,如果把它转变成 BeautifulSoup 对象应该也不错,但那样做其实适得其反——这个页面不是 HTML,所以BeautifulSoup 库就没用了。一旦纯文本文件被读成字符串,你就只能用普通 Python 字符串
的方法分析它了。 当然,这么做有个缺点,就是你不能对字符串使用 HTML 标签,去定位那些你真正需要的文字, 避开那些你不需要的文字。如果现在你想从纯文本文件中抽取某些信息,还是有些难度的.

文本编码和全球互联网

互联网上的文本文件会比较复杂。包括 ASCII、 Unicode 和 ISO 编码。

编码类型简介

Unicode 联盟( The Unicode Consortium)的非营利组织尝试将地球上所有用于书写的符号进行统一编码。 其目标包括拉丁字母、斯拉夫字母(кириллица)、中国象形文字( 象形)、数学和逻辑符号( , ≥),甚至表情和“杂项”( miscellaneous)符号。

编码进行时

用默认设置的 urlopen 读取了网上的 .txt 文档。这么做对英文文档没有任何问题。但是,如果你遇到的是俄语、阿拉伯语文档,或者文档里有一个像“ résumé”这样的单词,就可能出问题。

from urllib.request import urlopen
textPage = urlopen("http://www.pythonscraping.com/pages/warandpeace/chapter1-ru.txt")
print(textPage.read())

部分打印结果:

b"\xd0\xa7\xd0\x90\xd0\xa1\xd0\xa2\xd0\xac \xd0\x9f\xd0\x95\xd0\xa0\xd0\x92\xd0\x90\xd0\xaf\n\nI\n\n\xe2\x80\x94 Eh bien, mon prince. G\xc3\xaanes et Lucques ne sont plus que des apanages, des \xd0\xbf\xd0\xbe\xd0\xbc\xd0\xb5\xd1\x81\xd1\x82\xd1\x8c\xd1\x8f, de la famille Buonaparte. Non, je vous pr\xc3\xa9viens que si vous ne me dites pas que nous avons la guerre, si vous vous permettez encore de pallier toutes les infamies, toutes les atrocit\xc3\xa9s de cet Antichrist (ma parole, j'y crois) \xe2\x80\x94 je ne vous connais plus, vous n'\xc3\xaates plus mon ami, vous n'\xc3\xaates plus \xd0\xbc\xd0\xbe\xd0\xb9 \xd0\xb2\xd0\xb5\xd1\x80\xd0\xbd\xd1\x8b\xd0\xb9 \xd1\x80\xd0\xb0\xd0\xb1, comme vous dites.
(省略)

这个问题是因为 Python 默认把文本读成ASCII 编码格式, 而浏览器把文本读成 ISO-8859-1 编码格式。其实都不对,应该用 UTF-8编码格式

from urllib.request import urlopen
textPage = urlopen("http://www.pythonscraping.com/pages/warandpeace/chapter1-ru.txt")
print(str(textPage.read(), 'utf-8'))

如果你要做很多网络数据采集工作,尤其是面对国际网站时,建议你先看看 meta 标签的内容,用网站推荐的编码方式读取页面内容


3.CSV

Python 有一个超赞的标准库( https://docs.python.org/3.4/library/csv.html)可以读写CSV 文件。

读取CSV文件

Python 的 csv 库主要是面向本地文件,就是说你的 CSV 文件得存储在你的电脑上。而进行网络数据采集的时候,很多文件都是在线的。不过有一些方法可以解决这个问题:

  • 手动把 CSV 文件下载到本机,然后用 Python 定位文件位置;
  • 写 Python 程序下载文件,读取之后再把源文件删除;
  • 从网上直接把文件读成一个字符串, 然后转换成一个 StringIO 对象,使它具有文件的属性。

下面的程序就是从网上获取一个CSV 文件( 这里用的是 http://pythonscraping.com/files/MontyPythonAlbums.csv 里的 MontyPython 乐团的专辑列表),然后把每一行都打印到命令行里:

csv
from urllib.request import urlopen
from io import StringIO
import csv
data = urlopen("http://pythonscraping.com/files/MontyPythonAlbums.csv").read().decode('ascii', 'ignore')
dataFile = StringIO(data)
csvReader = csv.reader(dataFile)
for row in csvReader:
    print("The album \""+row[0]+"\" was released in "+str(row[1]))

输出结果:

The album "Name" was released in Year
The album "Monty Python's Flying Circus" was released in 1970
The album "Another Monty Python Record" was released in 1971
The album "Monty Python's Previous Record" was released in 1972
The album "The Monty Python Matching Tie and Handkerchief" was released in 1973
The album "Monty Python Live at Drury Lane" was released in 1974
The album "An Album of the Soundtrack of the Trailer of the Film of Monty Python and the Holy Grail" was released in 1975
The album "Monty Python Live at City Center" was released in 1977
The album "The Monty Python Instant Record Collection" was released in 1977
The album "Monty Python's Life of Brian" was released in 1979
The album "Monty Python's Cotractual Obligation Album" was released in 1980
The album "Monty Python's The Meaning of Life" was released in 1983
The album "The Final Rip Off" was released in 1987
The album "Monty Python Sings" was released in 1989
The album "The Ultimate Monty Python Rip Off" was released in 1994
The album "Monty Python Sings Again" was released in 2014

看第一行的内容, The album "Name" was released in Year为无用内容。有些程序员可能会简单地跳过 csvReader 对象的第一行,或者写一个简单的条件把第一行处理掉。不过,还有一个函数可以很好地处理这个问题,那就是 csv.DictReader:

from urllib.request import urlopen
from io import StringIO
import csv

data = urlopen("http://pythonscraping.com/files/MontyPythonAlbums.csv").read().decode('ascii', 'ignore')
dataFile = StringIO(data)
dictReader = csv.DictReader(dataFile)

print(dictReader.fieldnames)

for row in dictReader:
    print(row)

运行结果:

['Name', 'Year']                                                                                                     
{'Name': "Monty Python's Flying Circus", 'Year': '1970'}                                                             
{'Name': 'Another Monty Python Record', 'Year': '1971'}                                                              
{'Name': "Monty Python's Previous Record", 'Year': '1972'}                                                           
{'Name': 'The Monty Python Matching Tie and Handkerchief', 'Year': '1973'}                                           
{'Name': 'Monty Python Live at Drury Lane', 'Year': '1974'}                                                          
{'Name': 'An Album of the Soundtrack of the Trailer of the Film of Monty Python and the Holy Grail', 'Year': '1975'} 
{'Name': 'Monty Python Live at City Center', 'Year': '1977'}                                                         
{'Name': 'The Monty Python Instant Record Collection', 'Year': '1977'}                                               
{'Name': "Monty Python's Life of Brian", 'Year': '1979'}                                                             
{'Name': "Monty Python's Cotractual Obligation Album", 'Year': '1980'}                                               
{'Name': "Monty Python's The Meaning of Life", 'Year': '1983'}                                                       
{'Name': 'The Final Rip Off', 'Year': '1987'}                                                                        
{'Name': 'Monty Python Sings', 'Year': '1989'}                                                                       
{'Name': 'The Ultimate Monty Python Rip Off', 'Year': '1994'}                                                        
{'Name': 'Monty Python Sings Again', 'Year': '2014'}                                                                 

csv.DictReader 会返回把 CSV 文件每一行转换成 Python 的字典对象返回,而不是列表对象,并把字段列表保存在变量 dictReader.fieldnames 里,字段列表同时作为字典对象的键


4.PDF

PDFMiner3K 就是一个非常好用的库( 是 PDFMiner 的 Python 3.x 移植版)。它非常灵活,可以通过命令行使用, 也可以整合到代码中。它还可以处理不同的语言编码,而且对网络文件的处理也非常方便。
你可以下载这个模块的源文件( https://pypi.python.org/pypi/pdfminer3k), 解压并用下面命令安装:
$python setup.py install
文档位于源文件解压文件夹的 /pdfminer3k-1.3.0/docs/index.html 里
下面的例子可以把任意 PDF 读成字符串,然后用 StringIO转换成文件对象:

from pdfminer.pdfinterp import PDFResourceManager, process_pdf
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from io import StringIO
from io import open
from urllib.request import urlopen

def readPDF(pdfFile):
    rsrcmgr = PDFResourceManager()
    retstr = StringIO()
    laparams = LAParams()
    device = TextConverter(rsrcmgr, retstr, laparams=laparams)

    process_pdf(rsrcmgr, device, pdfFile)
    device.close()

    content = retstr.getvalue()
    retstr.close()
    return content

pdfFile = urlopen("http://pythonscraping.com/pages/warandpeace/chapter1.pdf")
outputString = readPDF(pdfFile)
print(outputString)
pdfFile.close()


5.微软Word和.docx

Python 对这种 Google Docs、 Open Office 和 Microsoft Office都在使用的 .docx 格式 的 支 持 还 不 够 好。 虽 然 有 一 个 python-docx 库(http://python-docx.readthedocs.org/en/latest/),但是只支持创建新文档和读取一些基本的文件数据,如文件大小和文件标题,不支持正文读取。如果想读取 Microsoft Office文件的正文内容,我们需要自己动手找方法。

从文件读取 XML

from zipfile import ZipFile
from urllib.request import urlopen
from io import BytesIO
from bs4 import BeautifulSoup

wordFile = urlopen("http://pythonscraping.com/pages/AWordDocument.docx").read()
wordFile = BytesIO(wordFile)
document = ZipFile(wordFile)
xml_content = document.read('word/document.xml')

wordObj = BeautifulSoup(xml_content.decode('utf-8'))
textStrings = wordObj.findAll("w:t")
for textElem in textStrings:
    print(textElem.text)

这段代码把一个远程 Word 文档读成一个二进制文件对象( BytesIO 与StringIO 类似),再用 Python 的标准库 zipfile 解压(所有的 .docx 文件为了节省空间都进行过压缩),然后读取这个解压文件,就变成 XML 了

word

输出结果:

<!--?xml version="1.0" encoding="UTF-8" standalone="yes"?-->
<w:document mc:ignorable="w14 w15 wp14" xmlns:m="http://schemas.openx
mlformats.org/officeDocument/2006/math" xmlns:mc="http://schemas.open
xmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-micros
oft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/off
iceDocument/2006/relationships" xmlns:v="urn:schemas-microsoft-com:vm
l" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/m
ain" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w14="htt
p://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://
schemas.microsoft.com/office/word/2012/wordml" xmlns:wne="http://sche
mas.microsoft.com/office/word/2006/wordml" xmlns:wp="http://schemas.o
penxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:wp14="h
ttp://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" x
mlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessin
gCanvas" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wor
dprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word
/2010/wordprocessingInk" xmlns:wps="http://schemas.microsoft.com/offi
ce/word/2010/wordprocessingShape"><w:body><w:p w:rsidp="00764658" w:r
sidr="00764658" w:rsidrdefault="00764658"><w:ppr><w:pstyle w:val="Tit
le"></w:pstyle></w:ppr><w:r><w:t>A Word Document on a Website</w:t></
w:r><w:bookmarkstart w:id="0" w:name="_GoBack"></w:bookmarkstart><w:b
ookmarkend w:id="0"></w:bookmarkend></w:p><w:p w:rsidp="00764658" w:r
sidr="00764658" w:rsidrdefault="00764658"></w:p><w:p w:rsidp="0076465
8" w:rsidr="00764658" w:rsidrdefault="00764658" w:rsidrpr="00764658">
<w: r> <w:t>This is a Word document, full of content that you want ve
ry much. Unfortunately, it’s difficult to access because I’m putting
it on my website as a .</w:t></w:r><w:prooferr w:type="spellStart"></
w:prooferr><w:r><w:t>docx</w:t></w:r><w:prooferr w:type="spellEnd"></
w:prooferr> <w:r> <w:t xml:space="preserve"> file, rather than just p
ublishing it as HTML</w:t> </w:r> </w:p> <w:sectpr w:rsidr="00764658"
w:rsidrpr="00764658"> <w:pgszw:h="15840" w:w="12240"></w:pgsz><w:pgm
ar w:bottom="1440" w:footer="720" w:gutter="0" w:header="720" w:left=
"1440" w:right="1440" w:top="1440"></w:pgmar> <w:cols w:space="720"><
/w:cols&g; <w:docgrid w:linepitch="360"></w:docgrid> </w:sectpr> </w:
body> </w:document>

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

推荐阅读更多精彩内容

  • # Python 资源大全中文版 我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列...
    aimaile阅读 26,454评论 6 428
  • GitHub 上有一个 Awesome - XXX 系列的资源整理,资源非常丰富,涉及面非常广。awesome-p...
    若与阅读 18,630评论 4 418
  • 不论是数据分析还是机器学习,乃至于高大上的AI,数据源的获取是所有过程的入口。 数据源的存在形式多为数据库或者文件...
    abel_cao阅读 2,673评论 1 46
  • 环境管理管理Python版本和环境的工具。p–非常简单的交互式python版本管理工具。pyenv–简单的Pyth...
    MrHamster阅读 3,788评论 1 61
  • 最近常常想到小时候家里的一些摆设,很多年没有回家了,听说家里的房子重新改建,好多东西估计是搬来搬去也找不到了。其实...
    彧瑛阅读 1,104评论 3 1