Извлечение данных с использованием tbodyclass и Beautifulsoup - PullRequest
1 голос
/ 31 мая 2019

Извлечение с помощью класса tbody с использованием BeautifulSoup и Python 3.

Я пытаюсь извлечь таблицу (сводку) поверх нее.Я использую BeautifulSoup для извлечения.Однако я получаю следующую ошибку при использовании tclass для извлечения таблицы, содержащей имя, возраст, информацию и т. Д.

Я знаю, что могу использовать предыдущую таблицу {class: datatable} для извлечения таблицы. Как бы я ни хотел попробоватьизвлечение с использованием класса tbody

Как извлечь таблицу с помощью tbodyclass и какую ошибку я делаю?Я немного новичок в поиске в Интернете, и любая подробная помощь будет признательна

Вот код

import numpy as np
import pandas as pd
from bs4 import BeautifulSoup
import requests

urls=['https://www.reuters.com/finance/stocks/company- officers/GOOG.O',
      'https://www.reuters.com/finance/stocks/company- officers/AMZN',
      'https://www.reuters.com/finance/stocks/company- officers/AAPL']

for item in urls:
   response=requests.get(item)
   data=response.content
   soup=BeautifulSoup(data,'html.parser')
   required_data=soup.find_all(class_='moduleBody')
   real_data=required_data.find_all(tbodyclass_='dataSmall')
   print(real_data)

Вот ошибка

Traceback (most recent call last):
 File "C:\Users\XXXX\Desktop\scrape.py", line 15, in <module>
real_data=required_data.find_all(tbodyclass_='dataSmall')
 File "C:\Users\XXXX\AppData\Local\Programs\Python\Python37\lib\site- 
 packages\bs4\element.py", line 1620, in __getattr__
"ResultSet object has no attribute '%s'. You're probably treating a list of items like a single item. Did you call find_all() when you meant to call find()?" % key
AttributeError: ResultSet object has no attribute 'find_all'. You're 
probably treating a list of items like a single item. Did you call 
find_all() when you meant to call find()?

Ответы [ 5 ]

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

Чтобы получить таблицу под summary, вы можете попробовать следующий скрипт:

import requests
from bs4 import BeautifulSoup

URLS = [
    'https://www.reuters.com/finance/stocks/company- officers/GOOG.O',
    'https://www.reuters.com/finance/stocks/company- officers/AMZN',
    'https://www.reuters.com/finance/stocks/company- officers/AAPL'
]

for url in URLS:
    r = requests.get(url,headers={"User-Agent":"Mozilla/5.0"})
    soup = BeautifulSoup(r.text,"lxml")
    for items in soup.select_one("h3:contains(Summary)").find_parent().find_next_sibling().select("table tr"):
        data = [' '.join(item.text.split()) for item in items.select("th,td")]
        print(data)
1 голос
/ 01 июня 2019

Чтобы выбрать только tbody, вам нужно выбрать только первое совпадение для этого tbody класса.Таким образом, вы можете использовать select_one.

table = soup.select_one('table:has(.dataSmall)')

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


Похоже, вы можете использовать панд

import pandas as pd

urls=['https://www.reuters.com/finance/stocks/company- officers/GOOG.O',
      'https://www.reuters.com/finance/stocks/company- officers/AMZN',
      'https://www.reuters.com/finance/stocks/company- officers/AAPL']
for url in urls:
    table = pd.read_html(url)[0]
    print(table)

Объединение с использованием панд и класса tbody, но с использованием тега родительской таблицы

import requests
import pandas as pd

urls=['https://www.reuters.com/finance/stocks/company- officers/GOOG.O',
      'https://www.reuters.com/finance/stocks/company- officers/AMZN',
      'https://www.reuters.com/finance/stocks/company- officers/AAPL']
with requests.Session() as s:
    for url in urls:
        r = s.get(url)
        soup = bs(r.content, 'lxml')
        table = soup.select_one('table:has(.dataSmall)')
        print(pd.read_html(str(table)))

Игнорирование тега таблицы (но добавление позже для разбора панд) - вам не нужно делать циклы tr и td внутри, а не передавать их пандам.

import pandas as pd

urls=['https://www.reuters.com/finance/stocks/company- officers/GOOG.O',
      'https://www.reuters.com/finance/stocks/company- officers/AMZN',
      'https://www.reuters.com/finance/stocks/company- officers/AAPL']
with requests.Session() as s:
    for url in urls:
        r = s.get(url)
        soup = bs(r.content, 'lxml')
        table = soup.select_one('.dataSmall')
        print(pd.read_html('<table>' + str(table) + '</table>'))
0 голосов
/ 31 мая 2019

Функция findall() возвращает набор результатов.Это полезно, когда присутствует более одного вхождения тега.
Вам нужно перебрать результаты и использовать findall() для каждого отдельно:

for item in urls:
   response = requests.get(item)
   data = response.content
   soup = BeautifulSoup(data, 'html.parser')
   required_data = soup.find_all(class_='moduleBody')
   for res in required_data:
    real_data = res.find_all(tbodyclass_='dataSmall')
    print(real_data)

Редактировать: достаточно одного find_all:

import requests
from bs4 import BeautifulSoup
url = ["https://www.reuters.com/finance/stocks/company-officers/GOOG.O", "https://www.reuters.com/finance/stocks/company-officers/AMZN.O", "https://www.reuters.com/finance/stocks/company-officers/AAPL.O"]
for URL in url:
    req = requests.get(URL)
    soup = BeautifulSoup(req.content, 'html.parser')
    for i in soup.find_all("tbody", {"class": "dataSmall"}):
        print(i)
0 голосов
/ 01 июня 2019

Непонятно, какую именно информацию вы пытаетесь извлечь, но делаете:

for res in required_data:
   real_data=res.find_all("tbody", class_="dataSmall")
   for dat in real_data:
       print(dat.text.strip())

выводит много информации о множестве людей ...

РЕДАКТИРОВАТЬ: Если вы ищете сводную таблицу, вам нужно это:

import pandas as pd

tabs = pd.read_html(url)    
print(tabs[0]

и вот твой стол.

0 голосов
/ 31 мая 2019

вы можете сделать это:

required_data.find_all("tbody", class_="dataSmall")
...