Как использовать BeautifulSoup для получения текста из родительских и дочерних тегов для помещения в таблицу DOCX - PullRequest
3 голосов
/ 28 июня 2019

Я пытаюсь использовать BeautifulSoup для анализа заявок на google.com/patents и помещения их в таблицу DOCX.

Мне удалось получить утверждения, но, к сожалению, родительский тег div имеет первую часть утверждения, а дочерние div-ы являются частями остальной части утверждения, как показано на рисунке ниже.

HTML Code

Когда я запускаю программу, в первой ячейке таблицы есть родительский элемент и все дочерние элементы div-текста, а дочерние элементы div распространяют следующие ячейки таблицы.

Я хотел бы распространить первую ячейку в таблице DOCX с текстом из родительского div, исключая дочерние div, и следующие ячейки с текстом из дочерних div.

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

   from bs4 import BeautifulSoup
   import requests
   from docx import Document
   from docx.enum.table import WD_TABLE_DIRECTION

   document = Document()

   url = 'https://patents.google.com/patent/US7054130?oq=US7654309'

   response = requests.get(url)
   data = response.text
   soup = BeautifulSoup(data, 'html.parser')

   claims = soup.select('div .claim-text')

   table = document.add_table(rows=1, cols=2, style='Table Grid')

   for claim in claims:

        if not claim.find('claim-ref'):

            try:
                print(claim.text + '\n')
                cells = table.add_row().cells
                cells[0].text = claim.text

                # Add space between paragraphs
                document.add_paragraph('')

            except:

                continue

    document.save('my_test.docx')

Я хочу иметь возможность анализировать заявки с текстом из начала заявки, найденной в родительском элементе, в ячейку 1 таблицы DOCX и исключать дочерние элементы из этой ячейки. Дети должны идти в свою камеру соответственно.

Вот что я получаю, когда пытаюсь запустить программу: This is what I get when I try to run the program

Вот чего я хочу добиться: This is what I want

Мне не удалось понять, как отделить текст от родителя и детей.

Ответы [ 3 ]

1 голос
/ 30 июня 2019

Вы можете получить текст от родителя div, затем получить текст от детей div, затем добавить данные в новый список, созданный для этой цели.

//div/text[1] позволяет получить первыйтекст из div

[e for e in _list if e] позволяет удалить пустые элементы

Попробуйте это:

from lxml import html
import requests
from docx import Document
from docx.enum.table import WD_TABLE_DIRECTION

document = Document()

url = 'https://patents.google.com/patent/US7054130?oq=US7654309'

response = requests.get(url)
data = response.text
doc = html.fromstring(data)

parent_claim = [e.strip() for e in doc.xpath("//div[@id='CLM-00001']/div[@class='claim-text']/text()[1]") if e.strip()]
children_claims = [e.strip() for e in doc.xpath("//div[@id='CLM-00001']/div[@class='claim-text']/div[@class='claim-text']/text()") if e.strip()]
table = document.add_table(rows=1, cols=2, style='Table Grid')
claims = []
for e in parent_claim:
    claims.append(e)
for e in children_claims:
    claims.append(e)

for claim in claims:

        print(claim + '\n')
        cells = table.add_row().cells
        cells[0].text = claim

        # Add space between paragraphs
        document.add_paragraph('')

document.save('my_test.docx')

Вывод:

enter image description here

1 голос
/ 30 июня 2019

Чтобы избежать дублирования, просто получите весь текст из верхнего div и разделите его соответствующим образом, например:

from bs4 import BeautifulSoup
import requests
from docx import Document

document = Document()
url = 'https://patents.google.com/patent/US7054130?oq=US7654309'
response = requests.get(url)
data = response.text
soup = BeautifulSoup(data, 'html.parser')
claims_section = soup.find('section', itemprop='claims').div.div
table = document.add_table(rows=0, cols=2, style='Table Grid')

for div in claims_section.find_all('div', class_='claim', recursive=False):
    div_claim_text = div.find_next('div', class_='claim-text')
    lines = [line.strip() for line in div_claim_text.text.splitlines() if line.strip()]

    for line in lines:
        cells = table.add_row().cells
        cells[0].text = line

document.save('my_test.docx')

Этот подход хранит только независимые претензии.

0 голосов
/ 01 июля 2019

Я думал, что нашел решение; но применение кода в реальной жизни доказало, что код неисправен.

Вложенные div вызывали повторяющиеся записи в таблице. Я попытался использовать функцию декомпозиции, чтобы исправить проблему, но она не работает, если в заявке есть несколько слоев вложенных тегов div.

from bs4 import BeautifulSoup
import requests
from docx import Document
from docx.enum.table import WD_TABLE_DIRECTION

document = Document()
url = 'https://patents.google.com/patent/US7054130?oq=US7654309'
response = requests.get(url)
data = response.text
soup = BeautifulSoup(data, 'html.parser')
#claims = soup.select('div .claim-text')
claims =soup.find_all("div", class_="claim-text")




for claim in claims:

    table = document.add_table(rows=0, cols=2, style='Table Grid')
    if claim.find('claim-ref'):
        continue

    else:
        try:
            claim.find('div').decompose()
        except:
            continue
        for row in claim.parent.text.split('\n'):
            if row == '':
                continue
            else:
                cells = table.add_row().cells
                cells[0].text = row
                print(row)
            # Add space between tables
    document.add_paragraph('')

Еще раз спасибо!

...