Выравнивание HTML-таблиц в CSV с использованием BS4 для использования с Pandas - PullRequest
0 голосов
/ 31 января 2019

Я начал pet-проект, создавая то, что по сути является индексированной компиляцией множества статистических данных НФЛ с красивым простым графическим интерфейсом.К счастью, на сайте https://www.pro -football-reference.com есть все данные, которые вы можете представить в виде таблиц, которые можно экспортировать в формат CSV на сайте и скопировать / вставить вручную.Я начал это делать, а затем, используя библиотеку Pandas, начал читать CSV-файлы в DataFrames, чтобы использовать данные.

Это прекрасно работает, однако ручная загрузка всех этих данных довольно утомительна, поэтому я решилпопытайтесь создать веб-скребок, который может очищать HTML-таблицы и преобразовывать их в пригодный для использования формат CSV.Я изо всех сил пытаюсь, в частности, изолировать отдельные таблицы, но также и при том, чтобы создаваемый CSV отображался в удобочитаемом / пригодном для использования формате.

Вот как выглядит скребок прямо сейчас:

from bs4 import BeautifulSoup
import requests
import csv

def table_Scrape():
    url = 'https://www.pro-football-reference.com/teams/nwe/2008.htm'
    req = requests.get(url)
    soup = BeautifulSoup(req.text, 'html.parser')
    table = soup.select_one('table.stats_table')
    headers = [th.text.encode("utf-8") for th in table.select("tr th")]
    with open("out.csv", "w", encoding='utf-8') as f:
        wr = csv.writer(f)
        wr.writerow(headers)
        wr.writerows([
            [td.text.encode("utf-8") for td in row.find_all("td")]
            for row in table.select("tr + tr")
        ])    
table_Scrape()

Это правильно отправляет запрос на URL, но не извлекает данные, которые я ищу, это Rushing_and_Receiving.Вместо этого он выбирает первую таблицу на странице «Статистика и рейтинг команды».Он также отображает CSV в довольно уродливом / бесполезном формате, например так:

b'',b'',b'',b'Tot Yds & TO',b'',b'',b'Passing',b'Rushing',b'Penalties',b'',b'Average Drive',b'Player',b'PF',b'Yds',b'Ply',b'Y/P',b'TO',b'FL',b'1stD',b'Cmp',b'Att',b'Yds',b'TD',b'Int',b'NY/A',b'1stD',b'Att',b'Yds',b'TD',b'Y/A',b'1stD',b'Pen',b'Yds',b'1stPy',b'#Dr',b'Sc%',b'TO%',b'Start',b'Time',b'Plays',b'Yds',b'Pts',b'Team Stats',b'Opp. Stats',b'Lg Rank Offense',b'Lg Rank Defense'

b'309',b'4944',b'920',b'5.4',b'22',b'8',b'268',b'288',b'474',b'3222',b'27',b'14',b'6.4',b'176',b'415',b'1722',b'8',b'4.1',b'78',b'81',b'636',b'14',b'170',b'30.6',b'12.9',b'Own 27.8',b'2:38',b'5.5',b'29.1',b'1.74'
b'8',b'5',b'',b'',b'8',b'13',b'1',b'',b'12',b'12',b'13',b'5',b'13',b'',b'4',b'6',b'4',b'7',b'',b'',b'',b'',b'',b'1',b'21',b'2',b'3',b'2',b'5',b'4'
b'8',b'10',b'',b'',b'20',b'20',b'7',b'',b'7',b'11',b'31',b'15',b'21',b'',b'11',b'15',b'4',b'15',b'',b'',b'',b'',b'',b'24',b'16',b'5',b'13',b'14',b'15',b'11'

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

table = soup.select_one('table.stats_table')

Яэто то, что я бы по-прежнему считал новичком в Python, поэтому, если кто-то сможет помочь мне в запросе и разборе конкретной таблицы с BS4 в формат CSV, я был бы очень благодарен!

Заранее спасибо!

Ответы [ 3 ]

0 голосов
/ 31 января 2019

Решение pandas не сработало для меня из-за загрузки ajax, но вы можете увидеть в консоли URL-адрес, с которого загружается каждая таблица, и запросить ее напрямую.В этом случае URL-адрес: https://widgets.sports-reference.com/wg.fcgi?css=1&site=pfr&url=%2Fteams%2Fnwe%2F2008.htm&div=div_rushing_and_receiving

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

Это похоже на работу.

from bs4 import BeautifulSoup
import requests
import csv

def table_Scrape():
    url = 'https://widgets.sports-reference.com/wg.fcgi?css=1&site=pfr&url=%2Fteams%2Fnwe%2F2008.htm&div=div_rushing_and_receiving'
    req = requests.get(url)
    soup = BeautifulSoup(req.text, 'html.parser')
    table = soup.find('table', id='rushing_and_receiving')
    headers = [th.text for th in table.findAll("tr")[1]]
    body = table.find('tbody')
    with open("out.csv", "w", encoding='utf-8') as f:
        wr = csv.writer(f)
        wr.writerow(headers)
        for data_row in body.findAll("tr"):
            th = data_row.find('th')
            wr.writerow([th.text] + [td.text for td in data_row.findAll("td")])

table_Scrape()
0 голосов
/ 31 января 2019

Хотелось бы, чтобы оба этих ответа были правильными, поскольку оба они полезны, но, увы, второй ответ, использующий BeautifulSoup, является лучшим ответом, поскольку он позволяет изолировать конкретные таблицы, тогда как характерСтруктура сайта ограничивает эффективность метода read_html в Pandas.

Спасибо всем, кто откликнулся!

0 голосов
/ 31 января 2019

Я бы вообще отказался от красивого супа, так как панды хорошо подходят для этого места.(по крайней мере первые 4 таблицы, которые я затмил) Документация здесь

import pandas as pd

url = 'https://www.pro-football-reference.com/teams/nwe/2008.htm'
data = pd.read_html(url)
# data is now a list of dataframes (spreadsheets) one dataframe for each table in the page
data[0].to_csv('somefile.csv')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...