Python извлекать текст с разрезами строк - PullRequest
1 голос
/ 19 сентября 2019

Я использую Python 3.7 и у меня есть файл test.txt, который выглядит следующим образом:

<P align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<FONT size="2">Prior to this offering, there has been no public
market for our common stock. The initial public offering price
of our common stock is expected to be between
$&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and
$&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;per
share. We intend to list our common stock on the Nasdaq National
Market under the symbol
&#147;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#148;.
</FONT>

Мне нужно извлечь все, что следует за «быть между» (строка 4) до «на акцию»(строка 7).Вот код, который я запускаю:

price = []
with open("test.txt", 'r') as f:
    for line in f:
        if "be between" in line:
            price.append(line.rstrip().replace('&nbsp;','')) #remove '\n' and '&nbsp;'
print(price)
['of our common stock is expected to be between']

Сначала я нахожу «быть между», а затем прошу добавить строку, но проблема в том, что все, что идет дальше, обрезается, потому что это в следующих строках,

Мой желаемый результат будет:

['of our common stock is expected to be between $ and $ per share']

Как я могу это сделать?Заранее большое спасибо.

Ответы [ 6 ]

2 голосов
/ 19 сентября 2019

Правильный путь с html.unescape и re.search Особенности:

import re
from html import unescape

price_texts = []
with open("test.txt", 'r') as f:
    content = unescape(f.read())
    m = re.search(r'price\b(.+\bper\s+share\b)', content, re.DOTALL)
    if m:
        price_texts.append(re.sub(r'\s{2,}|\n', ' ', m.group(1)))

print(price_texts)

Выход:

[' of our common stock is expected to be between $ and $ per share']
0 голосов
/ 19 сентября 2019

Это также будет работать:

import re

price = []    
with open("test.txt", 'r') as f:
    for line in f:
        price.append(line.rstrip().replace('&nbsp;',''))
text_file = " ".join(price)

be_start = re.search("be between", text_file).span()[0]
share_end = re.search("per share", text_file).span()[1]
final_file = text_file[be_start:share_end]
print(final_file)

Вывод:

"be between $and $per share"
0 голосов
/ 19 сентября 2019

Вот еще одно простое решение: он собирает все строки в одну длинную строку, определяет начальный индекс 'be between', конечный индекс 'per share', а затем принимает соответствующую подстроку.

    from re import search
    price = []
    with open("test.txt", 'r') as f:
        one_line_txt = ''.join(f.readlines()).replace('\n', ' ').replace('&nbsp;','')
    start_index = search('be between', one_line_txt).span()[0]
    end_index = search('per share', one_line_txt).span()[1]
    print(price.append(one_line_txt[start_index:end_index]))

Выходные данные:

['be between $and $per share']
0 голосов
/ 19 сентября 2019

грязный способ сделать это:

   price = []
    with open("test.txt", 'r') as f:
        for i,line in enumerate(f):
            if "be between" in line:
                price.append(line.rstrip().replace('&nbsp;','')) #remove '\n' and '&nbsp;'
            if i > 3 and i <= 6:
                price.append(line.rstrip().replace('&nbsp;',''))
    print(str(price).split('.')[0]+"]")
0 голосов
/ 19 сентября 2019

это также работает:

import re

with open('test.txt','r') as f:
   txt = f.read()

start = re.search('\n(.*?)be between\n',txt)
end = re.search('per(.*?)share',txt,re.DOTALL)
output = txt[start.span()[1]:end.span()[0]].replace('&nbsp;','').replace('\n','').replace('and',' and ')
print(['{} {} {}'.format(start.group().replace('\n',''),output,end.group().replace('\n', ' '))])

вывод:

['of our common stock is expected to be between $ and $ per share']
0 голосов
/ 19 сентября 2019

Вам нужно решить, когда добавить строку к price:

is_capturing = False
is_inside_per_share = False
for line in f:
    if "be between" in line and "per share" in line:
        price.append(line)
        is_capturing = False
    elif "be between" in line:
        is_capturing = True
    elif "per share" in line:
        # CAUTION: possible off-by-one error
        price.append(line[:line.find('per share') + len('per share')].rstrip().replace('&nbsp;',''))
        is_capturing = False
        is_inside_per_share = False
    elif line.strip().endswith("per"):
        is_inside_per_share = True
    elif line.strip().startswith("share") and is_inside_per_share:
        # CAUTION: possible off-by-one error
        price.append(line[:line.find('share') + len('share')].rstrip().replace('&nbsp;',''))
        is_inside_per_share = False
        is_capturing = False

    if is_capturing:
        price.append(line.rstrip().replace('&nbsp;','')) #remove '\n' and '&nbsp;'

Это всего лишь эскиз, поэтому вам, вероятно, придется немного его настроить

...