BeautifulSoup - Поиск детей по местонахождению родителей другого ребенка - PullRequest
0 голосов
/ 16 июня 2019

Я хочу найти данные для конкретной даты, используя python, beautifulsoup и т. Д. Рассматриваемая дата, IMPORTANT DATE, равна Mar. 31, 2018, как показано ниже.

<tr class="ro">
<td class="pl " style="border-bottom: 0px;" valign="top"><a class="a" href="javascript:void(0);" onclick="top.Show.showAR( this, 'defref_dei_DocumentPeriodEndDate', window );">IMPORTANT DATE</a></td>
<td class="text">Mar. 31,  2018<span></span>
</td>
<td class="text">&#160;<span></span>
</td>
</tr>

Яиспользуя следующую строку кода для определения IMPORTANT DATE.

for item in soup.find('td', text='Document Period End Date').parent.find_all('td', {'class':['text']}):
    if len(item.text.strip()) > 0:
        report_date = [item.text.strip()]
        print(report_date)

Обратите внимание на использование if len(item...).Это хакерский способ избавиться от &#160, но он работает.Любое лучшее предложение здесь приветствуется, но не в центре моего вопроса ... переходя к этому.

Мой главный вопрос заключается в том, что если мы определили, что местоположение ребенка IMPORTANT DATE будет # 1 (см. ниже), как мы можем получить первого потомка некоторых элементов (тот же дедушка)?См. Ниже.

<tr>
<th class="tl" colspan="1" rowspan="1"><div style="width: 200px;"><strong>Condensed Consolidated Balance Sheets - USD ($)<br> $ in Thousands</strong></div></th>
<th class="th"><div>Mar. 31, 2018</div></th> # <-IMPORTANT DATE, 1st 
<th class="th"><div>Dec. 31, 2017</div></th> # <-wrong date 
</tr>
<tr class="ro">
<td class="pl " style="border-bottom: 0px;" valign="top"><a class="a" href="javascript:void(0);" onclick="top.Show.showAR( this, 'defref_us-gaap_InventoryNet', window );">Inventories, net</a></td>
<td class="nump">76,579<span></span> # <- data for important date 
</td>
<td class="nump">92,376<span></span> # <- data from wrong date
</td>
</tr>

Чтобы бросить кривая, иногда местоположение важных данных не является местоположением IMPORTANT DATE из-за того, что я предполагаю, что некоторые столбцы заголовка находятся под их родительским элементом <tr>,См. Ниже.

<tr>
<th class="th" colspan="1">3 Months Ended</th>
<th class="th" colspan="1"></th>
</tr>
<tr>
<th class="th"><div>Mar. 31, 2018</div></th> #<- IMPORTANT DATE, 3rd
<th class="th"><div>Dec. 31, 2017</div></th>
<tr class="ro">
<td class="pl " style="border-bottom: 0px;" valign="top"><a class="a" href="javascript:void(0);" onclick="top.Show.showAR( this, 'defref_us-gaap_LongTermDebt', window );">Long-term debt</a></td>
<td class="nump">data for important date<span></span> #<- important data is 1st
</td>
<td class="nump">unimportant data<span></span>
</td>

То, что я планировал сделать, было: 1) создать ссылку на наш IMPORTANT DATE в python, report_date, с которым нужно 2) сравнить даты наших важных данных с нашимиIMPORTANT DATE, наконец, 3) вернуть эти важные данные.Тем не менее, где-то между 1) и 2) мой код не работает, потому что при попытке следующих строк:

for item in soup.select('filename:contains("' + filename + '")'):
    for item in soup.find('td', text='Document Period End Date').parent.find_all('td', {'class':['text']}):
        if len(item.text.strip()) > 0:
            report_date = [item.text.strip()]
    for th in item.find_all('th', text=report_date):

Я знаю, что в какой-то момент css_selector soup.select("p > a:nth-of-type(2)") пригодится, но я не получилк этому шагу еще;Кажется, я довольно хорошо застрял.

Кто-нибудь может протянуть руку?

суп можно найти здесь

1 Ответ

0 голосов
/ 16 июня 2019

Вы можете получить последние два элемента (<td> или <th>) из строки (<tr>), выполнив tr.select('td, th')[-2:].Таким образом, вы всегда будете игнорировать этот необязательный первый столбец заголовка.Затем вы можете сделать zip() функцию для подключения данных:

from bs4 import BeautifulSoup

case_1 = '''<table><tr>
<th class="th" colspan="1">3 Months Ended</th>
<th class="th" colspan="1"></th>
</tr>
<tr>
<th class="th"><div>Mar. 31, 2018</div></th>
<th class="th"><div>Dec. 31, 2017</div></th>
<tr class="ro">
<td class="pl " style="border-bottom: 0px;" valign="top"><a class="a" href="javascript:void(0);" onclick="top.Show.showAR( this, 'defref_us-gaap_LongTermDebt', window );">Long-term debt</a></td>
<td class="nump">data for important date<span></span> #<- important data is 1st
</td>
<td class="nump">unimportant data<span></span>
</td>
'''

case_2 = '''
<table>
<tr>
<th class="tl" colspan="1" rowspan="1"><div style="width: 200px;"><strong>Condensed Consolidated Balance Sheets - USD ($)<br> $ in Thousands</strong></div></th>
<th class="th"><div>Mar. 31, 2018</div></th>
<th class="th"><div>Dec. 31, 2017</div></th>
</tr>
<tr class="ro">
<td class="pl " style="border-bottom: 0px;" valign="top"><a class="a" href="javascript:void(0);" onclick="top.Show.showAR( this, 'defref_us-gaap_InventoryNet', window );">Inventories, net</a></td>
<td class="nump">76,579<span></span>
</td>
<td class="nump">92,376<span></span>
</td>
</tr>'''

soup1 = BeautifulSoup(case_1, 'lxml')
soup2 = BeautifulSoup(case_2, 'lxml')

def get_data(soup):
    return [[row_data.text.strip() for row_data in tr.select('td, th')[-2:]] for tr in soup.select('tr')[-2:]]

print('Case 1:')
for i, (date, data_for_date) in enumerate(zip(*get_data(soup1)), 1):
    print('{}.\t{} - {}'.format(i, date, data_for_date))

print('\nCase 2:')
for i, (date, data_for_date) in enumerate(zip(*get_data(soup2)), 1):
    print('{}.\t{} - {}'.format(i, date, data_for_date))

Отпечатки:

Case 1:
1.  Mar. 31, 2018 - data for important date #
2.  Dec. 31, 2017 - unimportant data

Case 2:
1.  Mar. 31, 2018 - 76,579
2.  Dec. 31, 2017 - 92,376
...