ошибка в bs4 при извлечении сведений в python

#python #beautifulsoup

Вопрос:

Я использую python и bs4 для очистки данных github, и я хочу очистить звезды пользователей с помощью этой функции

 def total_stars(username):
    try:
        html = requests.get('https://github.com/' username).text
        soup = BeautifulSoup(html, 'html.parser')
        total_commit = soup.select_one(
            '#js-pjax-container div.container-xl.px-3.px-md-4.px-lg-5 div div.flex-shrink-0.col-12.col-md-3.mb-4.mb-md-0 div div.js-profile-editable-replace div.d-flex.flex-column div.js-profile-editable-area.d-flex.flex-column.d-md-block div.flex-order-1.flex-md-order-none.mt-2.mt-md-0 div a:nth-child(3) span').text
        print(total_stars)
        return (total_commit)
    except:
        return (0)

 

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

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

Спасибо!

Комментарии:

1. Это происходит потому, что страница пользователя Github изменила макет с тех пор, как этот код работал. Почему бы не использовать API REST GitHub вместо очистки HTML?

Ответ №1:

Когда soup.select_one() вы не можете найти нужный элемент, он возвращается None .

Итак, ваше исключение исходит из этой строки(посмотрите .text в конце).:

 total_commit = soup.select_one(
            '#js-pjax-container div.container-xl.px-3.px-md-4.px-lg-5 div div.flex-shrink-0.col-12.col-md-3.mb-4.mb-md-0 div div.js-profile-editable-replace div.d-flex.flex-column div.js-profile-editable-area.d-flex.flex-column.d-md-block div.flex-order-1.flex-md-order-none.mt-2.mt-md-0 div a:nth-child(3) span').text
 

Макеты веб-страниц могут измениться в любое время.

Старайтесь использовать идентификаторы как можно чаще. Они вряд ли изменятся (по сравнению с другими селекторами).

Комментарии:

1. как мне напрямую получить идентификаторы на вкладке «Проверка элементов» chrome?

2. @stark Да, найдите элемент там и посмотрите, есть ли у него (или у его ближайшего родителя) идентификатор.

3. это не работает

Ответ №2:

Что происходит?

Что — то странное в вашем образце кода- Кому вы собираетесь звонить? 😉 Вы используете сочетание имен переменных total_commits , total_stars и это тяжелое css selector , что очень сбивает с толку.

Однако элемент, который вы пытаетесь выбрать, не существует или не может быть найден, и вы не смогли вызвать .text None Type

Как это исправить?

Сделайте это как можно проще, найдите свою цель по href содержимому tab=stars и выберите ее <span> :

 soup.select_one('a[href*="tab=stars"] span')
 

Чтобы избежать каких-либо None Type ошибок, просто проверьте, существует ли элемент, и получите его текст или установите total_stars значение 0:

 total_stars = soup.select_one('a[href*="tab=stars"] span').text if soup.select_one('a[href*="tab=stars"] span') else 0 
 

Пример

 def total_stars(username):
    
    html = requests.get(f'https://github.com/{username}').text
    soup = BeautifulSoup(html, 'html.parser')

    total_stars = soup.select_one('a[href*="tab=stars"] span').text if soup.select_one('a[href*="tab=stars"] span') else 0

    return (total_stars)
    
total_stars('fabpot')
 

Выход

 188