Почему я не могу получить доступ к информации в tbody? - PullRequest
1 голос
/ 17 июня 2019

[Это исходный код сайта] [1] Я занимаюсь поиском в сети с BeautifulSoup, но не могу найти tr в tbody;На самом деле в исходном коде сайта есть tr in;однако функция find_all может возвращать только tr в thead.

ссылка, по которой я работаю: https://cpj.org/data/killed/?status=Killed&motiveConfirmed%5B%5D=Confirmed&type%5B%5D=Journalist&start_year=1992&end_year=2019&group_by=year

Вот мой код:

```from bs4 import BeautifulSoup

```url = "https://cpj.org/data/killed/?status=Killed&motiveConfirmed%5B%5D=Confirmed&type%5B%5D=Journalist&start_year=1992&end_year=2019&group_by=year"
```html = urlopen(url)
```soup = BeautifulSoup(html,'lxml')
```type(soup)
```tr = soup.find_all("tr")
```print(tr)


  [1]: https://i.stack.imgur.com/NFwEV.png

Ответы [ 2 ]

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

Чтобы получить табличное содержимое с помощью селекторов, которые вы видите, осматривая элементы, вы можете попробовать использовать этот pyppeteer , как я показал ниже, как работатьс.Следующий подход является асинхронным.Итак, я предлагаю вам пойти на это, если вы не найдете API для игры:

import asyncio
from pyppeteer import launch

url = "https://cpj.org/data/killed/?status=Killed&motiveConfirmed%5B%5D=Confirmed&type%5B%5D=Journalist&start_year=1992&end_year=2019&group_by=year"

async def get_table(link):
    browser = await launch(headless=False)
    [page] = await browser.pages()
    await page.goto(link)
    await page.waitForSelector("table.js-report-builder-table tr td")
    for tr in await page.querySelectorAll("table.js-report-builder-table tr"):
        tds = [await page.evaluate('e => e.innerText',td) for td in await tr.querySelectorAll("th,td")]
        print(tds)

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(get_table(url))

Вывод будет выглядеть так:

['Name', 'Organization', 'Date', 'Location', 'Attack', 'Type of Death', 'Charge']
['Abadullah Hananzai', 'Radio Azadi,Radio Free Europe/Radio Liberty', 'April 30, 2018', 'Afghanistan', 'Killed', 'Murder', '']
['Abay Hailu', 'Agiere', 'February 9, 1998', 'Ethiopia', 'Killed', 'Dangerous Assignment', '']
['Abd al-Karim al-Ezzo', 'Freelance', 'December 21, 2012', 'Syria', 'Killed', 'Crossfire', '']
['Abdallah Bouhachek', 'Révolution et Travail', 'February 10, 1996', 'Algeria', 'Killed', 'Murder', '']
['Abdel Aziz Mahmoud Hasoun', 'Masar Press', 'September 5, 2013', 'Syria', 'Killed', 'Crossfire', '']
['Abdel Karim al-Oqda', 'Shaam News Network', 'September 19, 2012', 'Syria', 'Killed', 'Murder', '']
0 голосов
/ 17 июня 2019

Данные запрашиваются через API, возвращающий json, т.е. они добавляются динамически, поэтому они не отображаются в вашем запросе на целевой странице.Вы можете найти конечную точку API на вкладке сети, которая используется для получения информации.

Вы можете изменить один из параметров на число, превышающее ожидаемый набор результатов, затем проверьте, нужно ли делать дальнейшие запросы.

import requests

r = requests.get('https://cpj.org/api/datamanager/reports/entries?distinct(personId)&includes=organizations,fullName,location,status,typeOfDeath,charges,startDisplay,mtpage,country,type,motiveConfirmed&sort=fullName&pageNum=1&pageSize=2000&in(status,%27Killed%27)&or(eq(type,%22media%20worker%22),in(motiveConfirmed,%27Confirmed%27))&in(type,%27Journalist%27)&ge(year,1992)&le(year,2019)').json()

В противном случае вы можете выполнить первоначальный вызов и проверить, сколько еще запросов нужно сделать, и изменить соответствующие параметры в URL.Вы можете видеть, что возвращено pageCount.

Здесь вы можете увидеть соответствующие части в ответе для размера страницы 20:

{'rowCount': 1343,
 'pageNum': 1,
 'pageSize': '20',
 'pageCount': 68,

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

После изменения большего числа вы можете увидеть следующее:

'rowCount': 1343,
 'pageNum': 1,
 'pageSize': '2000',
 'pageCount': 1,

Вы можете преобразовать в таблицу с помощью панд:

import requests
import pandas as pd

r = requests.get('https://cpj.org/api/datamanager/reports/entries?distinct(personId)&includes=organizations,fullName,location,status,typeOfDeath,charges,startDisplay,mtpage,country,type,motiveConfirmed&sort=fullName&pageNum=1&pageSize=2000&in(status,%27Killed%27)&or(eq(type,%22media%20worker%22),in(motiveConfirmed,%27Confirmed%27))&in(type,%27Journalist%27)&ge(year,1992)&le(year,2019)').json()
df = pd.DataFrame(r['data'])
print(df)

Пример df:

enter image description here


Пример проверки фактического количества и создания дополнительного запроса для запроса записей:

import requests
import pandas as pd

request_number = 1000

with requests.Session() as s:
    r = s.get('https://cpj.org/api/datamanager/reports/entries?distinct(personId)&includes=organizations,fullName,location,status,typeOfDeath,charges,startDisplay,mtpage,country,type,motiveConfirmed&sort=fullName&pageNum=1&pageSize=' + str(request_number) + '&in(status,%27Killed%27)&or(eq(type,%22media%20worker%22),in(motiveConfirmed,%27Confirmed%27))&in(type,%27Journalist%27)&ge(year,1992)&le(year,2019)').json()
    df = pd.DataFrame(r['data'])
    actual_number = r['rowCount']
    if actual_number > request_number:
        request_number = actual_number - request_number
        r = s.get('https://cpj.org/api/datamanager/reports/entries?distinct(personId)&includes=organizations,fullName,location,status,typeOfDeath,charges,startDisplay,mtpage,country,type,motiveConfirmed&sort=fullName&pageNum=2&pageSize=' + str(request_number) + '&in(status,%27Killed%27)&or(eq(type,%22media%20worker%22),in(motiveConfirmed,%27Confirmed%27))&in(type,%27Journalist%27)&ge(year,1992)&le(year,2019)').json()
        df2 = pd.DataFrame(r['data'])
        final = pd.concat([df,df2])
    else:
        final = df
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...