Каков приемлемый способ отбросить первые пару строк текста?

Используя библиотеку запросов, я соскоб строк текста с веб-сайта SEC.gov для личного проекта. Я получаю сообщение об ошибке, потому что пытаюсь присвоить значение переменным до того, как будут достигнуты правильные строки. Я видел этот вопрос, который почти идентичен.

Как заставить python игнорировать первые пару строк текстового файла

Однако я хочу, чтобы программа могла определять, сколько строк пропустить, а не жестко кодировать ее.

Я жестко закодировал это, но я считаю, что количество строк потенциально может измениться. Кроме того, я полагаю, что могу проверить строку на наличие разделителя (|), и если в строке его нет, то выкинуть строку, но это будет означать проверку смешного количества символов. Код:

try:
    for year in range(start_year, current_year + 1):
        url = 'https://www.sec.gov/Archives/edgar/full-index/%s/%s/master.idx' %(year, quarter)
        r = requests.get(url)
        lines = r.text.splitlines(True)
        for line in lines[12:]:
            # cik, company_name, filling_type, filling_date, edgar_url = line.split('|')
            # if cik == 729986:
            #     print(line)

Есть ли способ, чтобы python попробовал выполнить задание, и если он выдает ошибку, отбросить его таким образом? Сказать,

try:
    cik, company_name, filling_type, filling_date, edgar_url = line.split('|')
except Exception as e:
    continue

Вот две строки того, что будет возвращено, если я смогу правильно пропустить строку, как это делает жесткое кодирование:

72971|WELLS FARGO & COMPANY/MN|SC 13G|2019-02-14|edgar/data/72971/0000072971-19-000222.txt

729986|UNITED BANKSHARES INC/WV|10-K|2019-03-01|edgar/data/729986/0001193125-19-060795.txt

Однако первые 14 строк (я полагаю) описывают такие данные, как:

Retrieved from: SEC.gov, Tuesday April 9th, 2019
Email: ########.gov

что приводит к сбою следующей строки:

cik, company_name, filling_type, filling_date, edgar_url = line.split('|')

Решение, которое я в итоге закодировал, основано на решении, отмеченном здесь как правильное, потому что я думаю, что оно больше всего соответствует моему первоначальному мышлению. Все ответы дали мне пищу для размышлений, пока я продолжаю развивать этот проект. Я думаю, что у каждого решения есть преимущества. Вот мой окончательный код, не стесняйтесь критиковать его:

try:
    for year in range(start_year, current_year + 1):
        url = 'https://www.sec.gov/Archives/edgar/full-index/%s/%s/master.idx' %(year, quarter)
        r = requests.get(url)
        lines = r.text.splitlines(True)
        for line in lines[0:]:
            row = line.split('|')
            if len(row) == 5:
                cik, company_name, filling_type, filling_date, edgar_url = row[0:5]
                
except requests.exceptions.HTTPError as e:
    print(e)

СУПЕР Обновлено: Есть ли способ получить решение одной строки: что-то вроде этого:

df = pd.DataFrame([line.split('|') for line in lines if len(line.split('|') == 4])
# I think this calls the split function twice though which might be finicky.

Задам в новом вопросе.

Вы сами поставили ответ (попробуйте, кроме как с разделением строки). Какой у Вас вопрос?

Edward Aung 09.04.2019 07:12

@EdwardAung Мое первоначальное решение таково: try: for year in range(start_year, current_year + 1): url = 'https://www.sec.gov/Archives/edgar/full-index/%s/%s/master.‌​idx' %(year, quarter) r = requests.get(url) lines = r.text.splitlines(True) for line in lines[12:]: # cik, company_name, filling_type, filling_date, edgar_url = line.split('|') Я не думаю, что ключевое слово try: следует использовать для пропуска строк, а больше для обнаружения ошибок. Тем не менее, я вижу, что вы говорите. Есть ли неспособность присвоить ошибку?

David Frick 09.04.2019 20:43
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
2
101
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

import re
import requests
import pandas as pd

def get_data(url):
    r = requests.get(url)
    r.raise_for_status()

    # Find the csv header
    m1 = re.search("\\n(\w\s*\|?)+\\n", r.text)

    # Find end of dash line starting from end of header
    start = r.text.find("\n", m1.end()) + 1

    # r.text[start:] is the part of the text after the initial header
    # Get individual lines
    lines = r.text[start:].splitlines()

    # If you have Pandas, you can pack everything into a nice DataFrame    
    cols = m1.group().strip().split('|')
    df = pd.DataFrame([line.split('|') for line in lines], columns=cols)
    return df

url = 'https://www.sec.gov/Archives/edgar/full-index/2019/QTR1/master.idx'
df = get_data(url)
df.head()

дает

       CIK            Company Name Form Type  Date Filed                                     Filename
0  1000045  NICHOLAS FINANCIAL INC      10-Q  2019-02-14  edgar/data/1000045/0001193125-19-039489.txt
1  1000045  NICHOLAS FINANCIAL INC         4  2019-01-15  edgar/data/1000045/0001357521-19-000001.txt
2  1000045  NICHOLAS FINANCIAL INC         4  2019-02-19  edgar/data/1000045/0001357521-19-000002.txt
3  1000045  NICHOLAS FINANCIAL INC         4  2019-03-15  edgar/data/1000045/0001357521-19-000003.txt
4  1000045  NICHOLAS FINANCIAL INC       8-K  2019-02-01  edgar/data/1000045/0001193125-19-024617.txt

Мне нравится это решение, и я мог бы реализовать фрейм данных, поэтому я благодарен за ваше предложение.

David Frick 09.04.2019 20:40

Является ли фрейм данных таким же быстрым, как список всех строк? @lightalchemist

David Frick 09.04.2019 21:30

DataFrame является частью Пакет панд. Будет ли это быстрее, зависит от того, какие операции вы хотите выполнять на линиях. В этом случае строки разбиваются на отдельные поля, и Pandas позволяет очень быстро искать, выбирать, рисовать, читать и записывать данные. Для некоторых операций это определенно намного быстрее, поскольку 1) некоторые из основных операций написаны на C и Cython и 2) он предоставляет лучшие структуры (например, индекс) для быстрого поиска данных, соответствующих некоторым условиям.

lightalchemist 10.04.2019 03:48
Ответ принят как подходящий

Вы ожидаете в общей сложности 5 столбцов. Игнорируйте каждую строку, в которой нет 5 столбцов.

import requests

def get_index(year, quarter):
    url = 'https://www.sec.gov/Archives/edgar/full-index/%s/%s/master.idx' % (year, quarter)
    r = requests.get(url)

    for line in r.text.splitlines():
        row = line.split('|')
        if len(row) == 5:
            yield row

rows = get_index(2018, 'QTR1')
next(rows)  # skip header row

for i, row in enumerate(rows):
    print(row)
    if i > 10:
        break

Все решения кажутся довольно хорошими. Тем не менее, я думаю, что это лучшее долгосрочное решение. Спасибо.

David Frick 09.04.2019 20:39

Вы можете искать строку только "-", а затем брать строки после

import requests
import pandas as pd
url = 'https://www.sec.gov/Archives/edgar/full-index/2018/QTR1/master.idx'
r = requests.get(url).text
records = r.splitlines()
results = []
header = 'CIK|Company Name|Form Type|Date Filed|Filename'
found = False
for row in records:
    if found:
        results.append(row.split('|'))
    if not found and set(row.strip()) == {'-'}:
        found = True
df = pd.DataFrame(results, columns = header.split('|') )
print(df.head())

Это интересное решение. Однако возможно, что строка, которую я хочу, содержит -, что отбросило бы это. Может быть, JP Morgan Chase — это JPMorgan, например, Chase. Кроме того, я думаю, что выбранное решение немного более эффективно. Ваш код очень читабелен, хотя! Спасибо.

David Frick 09.04.2019 20:42

Нет. Потому что я использую set, чтобы убедиться, что в строке есть только -

QHarr 09.04.2019 22:09

Другие вопросы по теме