格式化文本(.prn)文件中的数据

时间:2013-03-21 21:14:40

标签: python web-scraping beautifulsoup mechanize

我正在尝试找出处理以下数据的最佳方法。我正在抓取一个网站并使用一个文本(.prn)文件(一个用于打印的文件,这个文件包含我想要的数据,我认为这将比Adobe Acrobat文件更好)从中收集数据。我的问题是当我将数据带入python时:数据一次只在屏幕上垂直向下,所以即使有多行,这些数据也只是在一列上流入。我想知道是否有人会知道如何使数据进入,以更“传统”的方式我可以引入行[0],行[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

我正在尝试处理SUMMARY下的Text(.prn)文件中的数据。 请提供有关处理数据的最佳方法的建议。

我正在使用python27,机械化,美丽的汤和urllib

1 个答案:

答案 0 :(得分:0)

使用漂亮的汤读取文本文件似乎会在csvData中返回一个字符串,而不是您期望的行列表。因此,对字符串进行迭代会在每个迭代步骤返回一个char。这就是为什么您的文本似乎转换为单列。

首先,你似乎根本不需要美丽的汤!您正在检索文本文件,而不是HTML文件。 Beautiful Soup 是一个HTML / XML解析器。另外 mechanize 对我来说似乎没必要(我已经看过your previous question但实际上,你不需要解析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