AttributeError: объект 'NoneType' не имеет атрибута 'tbody' - Spyder 3.3.1 / beautifulsoup4 / python 3.6 - PullRequest
0 голосов
/ 27 сентября 2018

Привет, это мои настройки: Spyder 3.3.1 / beautifulsoup4 / python 3.6

Приведенный ниже код взят из статьи на среднем уровне ( здесь ) о создании веб-страниц с использованием python и Beautifulsoup.Предполагалось, что это будет быстрое чтение, но теперь ДВА дня спустя я все еще не могу заставить код работать в spyder и продолжать получать:

File "/Users/xxxxxxx/Documents/testdir/swiftScrape.py", line 9, in table_to_df
    return pd.DataFrame([[td.text for td in row.findAll('td')] for row in table.tbody.findAll('tr')])

AttributeError: 'NoneType' object has no attribute 'tbody'

Не уверен, что происходит неправильно, и, похоже, это ошибка реализации.Может ли кто-нибудь помочь в освещении этой проблемы.

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

import os
import bs4
import requests
import pandas as pd

PATH = os.path.join("C:\\","Users","xxxxx","Documents","tesdir")

def table_to_df(table):
    return pd.DataFrame([[td.text for td in row.findAll('td')] for row in table.tbody.findAll('tr')])

def next_page(soup):
    return "http:" + soup.find('a', attrs={'rel':'next'}).get('href')

res = pd.DataFrame()
url = "http://bank-code.net/country/FRANCE-%28FR%29/"
counter = 0

while True:
    print(counter)
    page = requests.get(url)
    soup = bs4.BeautifulSoup(page.content, 'lxml')
    table = soup.find(name='table', attrs={'id':'tableID'})
    res = res.append(table_to_df(table))
    res.to_csv(os.path.join(PATH,"BIC","table.csv"), index=None, sep=';', encoding='iso-8859-1')
    url = next_page(soup)
    counter += 1

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Спасибо @bruno desthuilliers за ваши указатели.Очень признателен.

Это переписанный код, который работал для меня с использованием Selenium и webdriver, а не import requests:

import os
import bs4
import pandas as pd
from selenium import webdriver

PATH = os.path.join('/','Users','benmorris','documents','testdir')

def table_to_df(table):
    return pd.DataFrame([[td.text for td in row.find_all('td')] for row in soup.find_all('tr')])

def next_page(soup):
    return "http:" + soup.find('a', attrs={'rel':'next'}).get('href')

res = pd.DataFrame()
url = "http://bank-code.net/country/FRANCE-%28FR%29/"
counter = 0
driver = webdriver.Chrome()
driver.get(url)

while True:
    print(counter)
    page = driver.get(url)
    soup = bs4.BeautifulSoup(driver.page_source, 'lxml')
    table = driver.find_element_by_xpath('//*[@id="tableID"]')
    if table is None:
        print("no table 'tableID' found for url {}".format(url))
        print("html content:\n{}\n".format( page.content))
        continue
    res = res.append(table_to_df(table))
    res.to_csv(os.path.join(PATH,"BIC","table.csv"), index=False, sep=',', encoding='iso-8859-1')
    url = next_page(soup)
    counter += 1
0 голосов
/ 27 сентября 2018

Как и пример потерянного примера кода, найденного в Интернете, этот код не является кодом производственного уровня - он слепо предполагает, что запросы http всегда выполняются успешно, и возвращает ожидаемое содержимое.Правда в том, что это не так часто (сетевые ошибки, прокси или брандмауэр блокируют вас, сайт отключен - временно или определенно, обновления на сайте, которые изменили либо URL-адреса и / или разметку страницы и т. Д.).

Ваша проблема проявляется здесь:

def table_to_df(table):
    return pd.DataFrame([[td.text for td in row.findAll('td')] for row in table.tbody.findAll('tr')])

и происходит от table на самом деле None, что означает, что здесь в цикле for:

table = soup.find(name='table', attrs={'id':'tableID'})

не былотег "table" с идентификатором "tableID" найден в HTML-документе.Вы можете проверить это, напечатав фактическое содержание HTML:

while True:
    print(counter)
    page = requests.get(url)
    soup = bs4.BeautifulSoup(page.content, 'lxml')
    table = soup.find(name='table', attrs={'id':'tableID'})
    if table is None:
        print("no table 'tableID' found for url {}".format(url))
        print("html content:\n{}\n".format( page.content))
        continye

    # etc
...