Проблема с Python: TypeError: unhashable тип: 'slice' во время просмотра веб-страниц - PullRequest
0 голосов
/ 03 мая 2018

Я пытаюсь почерпнуть некоторую информацию с сайта. Я был в состоянии успешно очистить текст, который я искал, но когда я пытаюсь создать функцию для добавления текстов вместе, я получаю TypeError неприемлемого типа.

Вы знаете, что здесь может происходить? Кто-нибудь знает, как решить эту проблему?

Вот код, о котором идет речь:

records = []
for result in results:
    name = result.contents[0][0:-1]

и вот код целиком для целей воспроизведения:

import requests
from bs4 import BeautifulSoup

r = requests.get('https://skinsalvationsf.com/2012/08/updated-comedogenic-ingredients-list/')
soup = BeautifulSoup(r.text, 'html.parser')
results = soup.find_all('td', attrs={'valign':'top'})

records = []
for result in results:
    name = result.contents[0][0:-1]

Образец results предметов:

<td valign="top" width="33%">Acetylated Lanolin <sup>5</sup></td>,
<td valign="top" width="33%">Coconut Butter<sup> 8</sup></td>,
...
<td valign="top" width="33%"><sup> </sup></td>

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

Ответы [ 2 ]

0 голосов
/ 03 мая 2018

Чтобы понять, почему вы получаете TypeError: unhashable type: 'slice' прочитайте t.m.adam ответ . В двух словах в последней итерации result переменные указывают на объект bs4.element.Tag вместо bs4.element.NavigableString.

Ниже приведено рабочее решение с использованием блока try-exc, поскольку последние 2 <td> элементов в списке не содержат "stripped_strings" и выдают ValueError: not enough values to unpack (expected 2, got 0).

Код: (Python 3.6+, если вы хотите использовать f-strings)

from bs4 import BeautifulSoup
import requests

url = 'https://skinsalvationsf.com/2012/08/updated-comedogenic-ingredients-list/'
headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36'}
html = requests.get(url, headers=headers).text
soup = BeautifulSoup(r.text, 'html.parser')

tds = soup.find_all('td')
for td in tds:
    try:
        ingredient, rating = td.stripped_strings
    except ValueError:
        pass
    else:
        print(f'{ingredient} -> {rating}')

Выход:

Acetylated Lanolin -> 5
Coconut Butter -> 8
...
Xylene -> 7
Octyl Palmitate -> 7
<ч />

Вы также можете избавиться от всего try-except-else и пропустить последние 2 <td>:

tds = soup.find_all('td')[:-2]
for td in tds:
    ingredient, rating = td.stripped_strings
    ...

Однако администраторы веб-сайта могут решить добавить или удалить некоторые ингредиенты, из-за чего в коде могут отсутствовать некоторые ингредиенты.

0 голосов
/ 03 мая 2018

В некоторых ваших собранных результатах contents не содержит текста, а содержит только Tag объекты, поэтому вы получаете TypeError при попытке выбрать фрагмент из словаря атрибутов Tag.

Вы можете отследить такие ошибки с помощью блока try-Кроме

for result in results:
    try:
        name = result.contents[0][0:-1]
    except TypeError:
        continue

Или вы можете использовать .strings для выбора только NavigableString содержимого,

for result in results:
    name = list(result.strings)[0][0:-1]

Но, похоже, это только последний элемент, который не имеет текстового содержимого, так что вы можете просто проигнорировать его.

results = soup.find_all('td', attrs={'valign':'top'})[:-1]

for result in results:
    name = result.contents[0][:-1]
...