Извлечение конкретного текстового раздела между тегами из HTML - PullRequest
2 голосов
/ 08 мая 2019

Я хотел бы извлечь текст в определенном разделе из файла HTML (раздел «Элемент 1А»).Я хочу, чтобы текст начинался с «Элемента 1А», в разделе контента, а не из таблицы содержания, и заканчивался «Элементом 1В».Но есть несколько одинаковых текстов «Пункт 1А» и «Пункт 1В».Как я могу определить, какой конкретный текст следует начинать и останавливать.

import requests
from bs4 import BeautifulSoup
import re

url = "https://www.sec.gov/Archives/edgar/data/1606163/000114420416089184/v434424_10k.htm"
res = requests.get(url)
soup = BeautifulSoup(res.text, "html.parser")
text = soup.get_text()

item1a = re.search(r"(item\s1A\.?)(.+)(item\s1B\.?)", text, re.DOTALL | re.IGNORECASE)

item1a.group(2)

На выходе выводится текст из первого «элемента 1А» в таблице содержания, а не заголовок раздела.

Таким образом, я хочу знать:

  1. Как захватить текст из «Элемента 1А» раздела содержимого вместо «Элемента 1А» из таблицы содержимого.

  2. Почему он захватил последний «Элемент 1B» вместо того, чтобы останавливаться на «Элементе 1B» из таблицы содержания.

1 Ответ

1 голос
/ 08 мая 2019

Поскольку у вас есть soup, который помогает вам работать со структурой HTML, почему бы не воспользоваться этим преимуществом?

Один из способов выразить это - «найти текст между двумя тегами с определенными атрибутами»«.(Теги, представляющие заголовки 1A и 1B.) Для этого вы можете передать вызываемую функцию (функцию) в soup.find():

import requests
from bs4 import BeautifulSoup
from bs4.element import Tag
import re

url = "https://www.sec.gov/Archives/edgar/data/1606163/000114420416089184/v434424_10k.htm"
res = requests.get(url)
soup = BeautifulSoup(res.text, "html.parser")

def is_pstyle(tag: tag) -> bool:
    return tag.name == "p" and tag.has_attr("style")

def is_i1a(tag: Tag) -> bool:
    return is_pstyle(tag) and re.match(r"Item 1A\..*", tag.text)

def is_i1b(tag: Tag) -> bool:
    return is_pstyle(tag) and re.match(r"Item 1B\..*", tag.text)

def grab_1a_thru_1b(soup: BeautifulSoup) -> str:
    start = soup.find(is_i1a)
    def gen_t():
        for tag in start.next_siblings:
            if is_i1b(tag):
                break
            else:
                if hasattr(tag, "get_text"):
                    yield tag.get_text()  # get_text("\n")
                else:
                    yield str(tag)
    return "".join(gen_t())

if __name__ == "__main__":
    print(grab_1a_thru_1b(soup))

Первая часть вывода:

The risks and uncertainties described below
are those specific to the Company which we currently believe have the potential to be material, but they may not be the only ones
we face. If any of the following risks, or any other risks and uncertainties that we have not yet identified or that we currently
consider not to be material, actually occur or become material risks, our business, prospects, financial condition, results of
operations and cash flows could be materially and adversely affected. Investors are advised to consider these factors along with
the other information included in this Annual Report and to review any additional risks discussed in our filings with the SEC.
 
Risks Associated with Our Business
 
We are a newly formed company with no operating history and, accordingly, you have no basis on which to evaluate our ability to achieve our business
objective.

Мини-функции is_pstyle, is_i1a и is_i1b, которые вы можете рассматривать как «фильтры» - просто разные способы точно найти начальный и конечный теги.Затем вы перебираете одноуровневые теги между этими тегами.(.get_text() будет работать рекурсивно внутри каждого тега родного брата.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...