【问题标题】:How can I scrape data from a text table using Python?如何使用 Python 从文本表中抓取数据?
【发布时间】:2011-05-03 18:27:33
【问题描述】:

我有以下文本,我想抓取数据项并将它们保存在 excel 中。有没有办法在 Python 中做到这一点?

text = """
                                       ANNUAL COMPENSATION                   LONG-TERM COMPENSATION
                              --------------------------------------- -------------------------------------
                                                                                AWARDS            PAYOUTS
                                                                      -------------------------- ----------
                                                                                      SECURITIES
                                                          OTHER         RESTRICTED    UNDERLYING            ALL OTHER
   NAME AND PRINCIPAL                                     ANNUAL           STOCK       OPTIONS/     LTIP    COPMPENSA-
        POSITION         YEAR SALARY ($)   BONUS ($) COMPENSATION ($) AWARD(S) ($)(1) SAR'S (#)  PAYOUTS($) TION($)(3)
   ------------------    ---- ----------   --------- ---------------- --------------- ---------- ---------- ----------
JOHN W. WOODS            1993  $595,000    $327,250    There is no      $203,190.63     18,000               $ 29,295
 Chairman, President, &  1992  $545,000    $245,250    compensation      166,287.50     18,825    (2) Not    $ 29,123
 Chief Executive Officer 1991  $515,000    $283,251   required to be                    45,000   Applicable
 of AmSouth & AmSouth                                  disclosed in
 Bank N.A.                                             this column.
C. STANLEY BAILEY        1993  $266,667(4) $133,333                      117,012.50      4,500               $ 11,648
 Vice Chairman, AmSouth  1992  $210,000    $ 84,000                       42,400.00      4,800               $ 12,400
 & AmSouth Bank N.A.     1991  $186,750    $ 82,170                      161,280.00      9,750
C. DOWD RITTER           1993  $266,667(4) $133,333                      117,012.50      4,500               $ 13,566
 Vice Chairman, AmSouth  1992  $210,000    $ 84,000                       42,400.00      4,800               $ 12,920
 & AmSouth Bank N.A.     1991  $188,625    $ 82,995                      161,280.00      9,750
WILLIAM A. POWELL, JR.   1993  $211,335    $ 95,101                                     11,000               $124,548
 President, AmSouth      1992  $330,000    $132,000                       98,050.00     11,100               $ 22,225
 and Vice Chairman,      1991  $308,000    $169,401                                     24,000
 AmSouth Bank N.A.
 Retired in 1993
A. FOX DEFUNIAK, III     1993  $217,000    $ 75,950                       52,971.88      4,500               $ 11,122
 Senior Executive Vice   1992  $200,000    $ 62,000                       42,400.00      4,800               $ 11,240
 President, Birmingham   1991  $177,500    $ 78,100                      161,280.00      9,750
 Banking Group,
 AmSouth Bank N.A.
E. W. STEPHENSON, JR.    1993  $177,833    $ 71,133                       52,971.88      3,400               $  9,256
 Senior Executive Vice   1992  $150,000    $ 45,000                       27,825.00      3,150               $  8,560
 President, AmSouth      1991  $140,000    $ 52,488                      107,520.00      6,750
 and Chairman & Chief
 Executive Officer,
 AmSouth Bank of Florida
"""

现在,我只是想以带有“|”的 csv 样式格式获取它符号分隔数据项,然后手动提取数据到excel:

tmp = open('tmp.txt','w')
tmp.write(text)
tmp.close()

data1 = []

for line in open('tmp.txt'):
    line = line.lower()
    if 'SALARY' in line:
        line = line.replace(' ','|')
    line = line.replace('--', '')
    line = line.replace('- -', '')
    line = line.replace('-  -', '')
    line = line.replace('(1)', '')
    line = line.replace('(2)', '')
    line = line.replace('(3)', '')
    line = line.replace('(4)', '')
    line = line.replace('(5)', '')
    line = line.replace('(6)', '')
    line = line.replace('(7)', '')
    line = line.replace('(8)', '')
    line = line.replace('(9)', '')
    line = line.replace('(10)', '')
    line = line.replace('(11)', '')
    line = line.replace('(S)', '')
    line = line.replace('($)', '')
    line = line.replace('(#)', '')
    line = line.replace('$', '')
    line = line.replace('-0-', '0')
    line = line.replace(')', '|')
    line = line.replace('(', '|-')
    line = re.sub(r'\s(\d)', '|\\1', line)
    line = line.replace(' ', '')
    line = line.replace('||', '|')
    data1.append(line)
data = ''.join(data1)

问题是我必须这样做数千次,而且要花很长时间才能遍历每个表并保存我需要的项目。有没有办法创建一个字典来记录最左侧列中列出的每个人的年份、薪水、奖金、其他年度薪酬等内容?

【问题讨论】:

    标签: python scrape


    【解决方案1】:

    这里有一些代码可以帮助您入门:

    text = """JOHN ...""" # text without the header
    
    # These can be inferred if necessary
    cols = [0, 24, 29, 39, 43, 52, 71, 84, 95, 109, 117]
    
    db = []
    row = []
    for line in text.strip().split("\n"):
        data = [line[cols[i]:cols[i+1]] for i in xrange((len(cols)-1))]
        if data[0][0] != " ":
            if row:
                db.append(row)
            row = map(lambda x: [x], data)
        else:
            for i, c in enumerate(data):
                row[i].append(c)
    print db
    

    这将生成一个数组,其中每个人都有一个元素。每个元素将是所有列的数组,并且将包含所有行的数组。通过这种方式,您可以轻松访问不同年份,或执行诸如连接人名之类的操作:

    for person in db:
        print "Name:", person[0][0]
        print " ".join(s.strip() for s in person[0][1:])
        print
    

    将产生:

    Name: JOHN W. WOODS           
    Chairman, President, & Chief Executive Officer of AmSouth & AmSouth Bank N.A.
    
    Name: C. STANLEY ...
    

    【讨论】:

    • 这很棒。太感谢了。如果列不均匀 [0, 24, 29, 39, 43, 52, 71, 84, 95, 109, 117],是否有一种简单的方法来推断列?
    • 是的,寻找特征。例如,您可以在标题下方使用带有----- 的行并使用string.split(' ') 将其拆分。您将不得不查看几个不同的文档,看看您是否可以挑选出始终适用的特征。
    【解决方案2】:

    您需要编写一系列生成器来对数据进行连续传递,以减少噪音和复杂性。

    不是任何编程语言都可以轻松解决的问题。

    def strip_top( source_text ):
        src= iter( source_text )
        for line in src:
            if line.rstrip().startswith("AWARDS"):
                next( src )
                break
        for line in src:
            yield line
    
    def columnize( source_text ):
        """Assumes strip_top or similar to remove confusing extra headers"""
        for line in src:
            yield line[0:24], line[25:30], ... for each coumn
    
    def collapse_headers( source_text ):
        """Assumes columnize( strip_top())."""
        src= iter( source_text )
        headings= [ [] for i in range(9) ]
        for line in src:
            if line[0] == "------------------":
                break
            for col in range(9):
                headings[col].append(line[col].strip())
        yield [ " ".join(h) for h in headings ]
        for line in src:
            yield line
    
    etc.
    

    然后,您的“主”程序将这些转换组合成一个管道。

    with open("some file","r") as text:
        for line in collapse_headers( columnize( strip_top( text ) ) ):
            # further cleanup?  
            # actual processing
    

    这允许您单独“调整”转换序列的每一部分。

    【讨论】:

      【解决方案3】:

      好吧,分离列很容易,它们是固定宽度的,所以你可以这样做:

      cells = [rowtext[0:24], rowtext[25:29], ...]
      

      分隔行有点困难。看来你可以单独处理标题,然后检查

      cells[0] == cells[0].upper()
      

      看看你是否应该开始一个新的行块(即当行中的第一个单元格在块大写中时)。当然,我假设您的数千个文件都具有几乎完全相同的格式。

      将数据转换为可用格式后,在 Python 中对其进行整理就很容易了。您可以将其全部保存在字典中,或者如果它太大,则将其作为大 CSV 文件或 sqlite 数据库写入磁盘。

      【讨论】:

        猜你喜欢
        • 2022-01-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-02
        • 1970-01-01
        • 2021-03-29
        • 2017-08-09
        相关资源
        最近更新 更多