1

I am kind off a newbie within the python field and try to set up a webscraping tool. So I am experimenting some codes.

import requests
import bs4

website = requests.get("https://www.hltv.org/stats/teams")

soup = bs4.BeautifulSoup(website.text, "html.parser")

leaderboard = soup.find("table", {id: "stats-table player-ratings-table"})
tbody = leaderboard.find("tbody")

for tr in tbody.find.all('tr'):
    team = tr.find.all('td')[0].text.strip()
    maps = tr.find.all('td')[1].text.strip()
    kd = tr.find.all('td')[3].text.strip()
    rating = tr.find.all('td')[4].text.strip()

    print(team, maps, kd, rating)

I get the following error, any help? I use 2.7.

 File "/Users/*****/Python/New Webscraping/WebS.py", line 11, in <module>
    tbody = leaderboard.find("tbody")
AttributeError: 'NoneType' object has no attribute 'find'

Process finished with exit code 1
John Rut
  • 39
  • 1
  • 1
  • 3
  • See [Python: Attribute Error - 'NoneType' object has no attribute 'something'](https://stackoverflow.com/questions/8949252/python-attribute-error-nonetype-object-has-no-attribute-something?rq=1) – Alistair Carscadden Oct 02 '18 at 07:59
  • Your `leaderboard` object was set to `None`, probably because the output of the `find` did not return what you expected. Try to print your soup and check what's wrong with it... – toti08 Oct 02 '18 at 08:02
  • You simply confused `id` and `class` attributes... – Andersson Oct 02 '18 at 08:23
  • Maybe ven better duplicate: https://stackoverflow.com/questions/34301815/understand-the-find-function-in-beautiful-soup (the link mentioned above explains what the error means, this link explains why `find()` returns `None`). – wovano Nov 10 '21 at 09:58

4 Answers4

2

Try the following to get your desired output. I ignored the first tr by indexing it like [1:] as there is no td within it. Moreover, there is no such method .find.all() in BeautifulSoup. you can use .find_all() or .findAll() instead.

import requests
from bs4 import BeautifulSoup

res = requests.get("https://www.hltv.org/stats/teams")
soup = BeautifulSoup(res.text, "html.parser")
for tr in soup.find("table",class_="player-ratings-table").find_all("tr")[1:]:
    team = tr.find_all('td')[0].text.strip()
    maps = tr.find_all('td')[1].text.strip()
    kd = tr.find_all('td')[3].text.strip()
    rating = tr.find_all('td')[4].text.strip()
    print(team, maps, kd, rating)
SIM
  • 21,997
  • 5
  • 37
  • 109
1

Looking at the source code of the website you're trying to scrape it looks like the keyword you're looking for is not id but class:

<table class="stats-table player-ratings-table">

So you should change your code to:

leaderboard = soup.find("table", {'class': "stats-table player-ratings-table"})

Also you should change the find.all to findAll.

toti08
  • 2,448
  • 5
  • 24
  • 36
0

Reading errors is a skill that will benefit you greatly when programming. The important parts of the error, for you, are:

AttributeError: 'NoneType' object has no attribute 'find' on line 11 of ...WebS.py

And the actual line of code that the error was thrown on: tbody = leaderboard.find("tbody").

The attribute find was called on the reference leaderboard on that line, and the error is telling you that NoneTypes have no find, so that means leaderboard == None.

To further break down the error, if you were still confused (on a different error), you should read about what comes before that colon, in this case AttributeError. But most frequently, you should google the error.

Alistair Carscadden
  • 1,198
  • 5
  • 18
-1

It means that there are some items that do not have team or maps or kid or rating. You should do 'error handling'

import requests
import bs4

website = requests.get("https://www.hltv.org/stats/teams")

soup = bs4.BeautifulSoup(website.text, "html.parser")

leaderboard = soup.find("table", {id: "stats-table player-ratings-table"})
tbody = leaderboard.find("tbody")

for tr in tbody.find.all('tr'):
    try:
        team = tr.find.all('td')[0].text.strip()
    except AttributError:
        team = ''
    
    try:
        maps = tr.find.all('td')[1].text.strip()
    except AttributError:
        maps = ''

    try:
        kd = tr.find.all('td')[3].text.strip()
    except AttributError:
        kd = ''

    try:
        rating = tr.find.all('td')[4].text.strip()
    except AttributError:
        rating = ''

    print(team, maps, kd, rating)
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 09 '21 at 19:19
  • You should know ErrorHandling method. !!! – Arman Malkhasyan Nov 10 '21 at 12:41