格式化文本(.prn)文件中的数据
我正在想办法处理以下数据。我在抓取一个网站,并使用一个文本文件(.prn文件,主要用于打印,这个文件里有我想要的数据,我觉得用这个文件比用Adobe Acrobat文件更好)来收集数据。我的问题是,当我把数据导入到Python时,数据是一个字母一个字母地垂直显示在屏幕上,虽然有多行数据,但这些数据却只在一列中流入。我想知道有没有人知道怎么才能让数据以更“传统”的方式导入,这样我就可以像访问row[0]、row[1]等那样来处理数据……
这是我的代码,可能会有帮助(你也可以看到我尝试过的一些其他功能)。
import os
import urllib
import urllib2
import string
import sys
import os
from bs4 import BeautifulSoup
import csv
import mechanize
from numpy import*
import datetime
import traceback
from pylab import*
site="http://www.treasurydirect.gov/govt/reports/pd/mspd/mspd.htm"
br = mechanize.Browser()
br.set_handle_equiv(False)
br.open(site)
print 'br.title',br.title()
allforms = list(br.forms())
br.form = allforms[0]
br.follow_link(text_regex="February", nr=0)
#br.click_link(text='February', nr=0) # this works to
#next page
print br.title()
allforms = list(br.forms())
print allforms
br.form = allforms[0]
getstuff=br.click_link(text="Text (.prn)", nr=0) # this works to
#getstuff= br.click_link(text="Adobe Acrobat (.pdf)", nr=0) Adobe Acrobat (.pdf)
br.open(getstuff)
csvData=br.response().read() # use read to BeautifulSoup(x)
#site = BeautifulSoup(csvData)
#print site
for row in csvData:
print row[0]
这是文本文件(.prt文件)所在的确切网站页面: http://www.treasurydirect.gov/govt/reports/pd/mspd/2013/2013_feb.htm
我正在尝试处理文本文件(.prn)中SUMMARY部分的数据。请给我一些关于如何最好地处理这些数据的建议。
我使用的是python27、mechanize、beautiful soup和urllib。
1 个回答
用 beautiful soup 读取文本文件时,得到的结果是一个字符串,而不是你期待的行列表。所以,当你对这个字符串进行迭代时,每次迭代只会返回一个字符。这就是为什么看起来你的文本被转置成了单列的原因。
首先,你根本不需要 beautiful soup!你是在获取一个文本文件,而不是 HTML 文件。Beautiful Soup 是用来解析 HTML 或 XML 的工具。而且我觉得 mechanize 也没必要(我看过你之前的问题,但其实你不需要解析 HTML 页面来找到链接,因为你已经知道最终的 URL 了)。
在我看来,你应该把这个算法分成三个部分:
- 把文本获取为行列表
- 去掉不必要的行
- 格式化你的行,以便符合你的需求
你的问题主要和第一部分有关,但既然你也在询问如何获取最终数据,我想你也需要其他两个部分的帮助 :)
这是我的建议:我们可以先定义三个函数,每个函数对应算法的一个部分……
import urllib2, re
def get_data_text(month, year):
"""given a month and a year, this method returns the raw data file (as a list of rows)"""
url_pattern = 'http://www.treasurydirect.gov/govt/reports/pd/mspd/{year:4d}/opds{month:02d}{year:4d}.prn'
url = url_pattern.format(month=month, year=year)
source = urllib2.urlopen(url)
data = source.readlines()
source.close()
return data
def keep_only_interesting_rows(data, interesting_rows):
"""filter data rows in order to keep only the ones that start with strings in interesting_rows list"""
return [line for line in data if any([line.strip().startswith(ir) for ir in interesting_rows])]
def convert_data_to_dict(data):
"""converts every row in data to a dictionary element """
return {re.sub('\.*\s*$', '', el[0:46]).strip():(int(el[47:63].replace(',','')), int(el[69:90].replace(',','')), int(el[95:115].replace(',',''))) for el in data}
所以现在我定义了三个函数,每个函数对应我提议的解决方案中的一个部分。
这些函数怎么用呢?这里有个例子:
interesting_rows = ['Bills', 'Notes', 'Total Public Debt Outstanding'] # add the initial part of any row you are interested at (without leading spaces)
mytext = get_data_text(2, 2013) # gets the text for feb, 2013 as rows
data = keep_only_interesting_rows(mytext, interesting_rows) # filter rows
final_data = convert_data_to_dict(data) # convert remaining rows into a dict
print final_data
print final_data['Bills'][2] # this gives you the third column
# >>> {'Notes': (7416574, 5888, 7422462), 'Bills': (1738404, 3546, 1741950), 'Total Public Debt Outstanding': (11822436, 4864853, 16687289)}
# >>> 1741950
如果你想出于某种原因访问你最初的文本文件中的某一行(.prn 文件),你可以输入:
mytext = get_data_text(9, 2012) # this time let's get the text for September, 2012
print mytext[0]
这将返回:
MONTHLY STATEMENT OF THE PUBLIC DEBT