Python issue: TypeError: unhashable type: 'slice' during web scraping
Python issue: TypeError: unhashable type: 'slice' during web scraping
我正在尝试从网站上抓取一些信息。我能够成功地抓取我正在寻找的文本,但是当我尝试创建一个函数来将文本附加在一起时,我得到了一个不可散列类型的 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>
提前致谢!!
在您收集的一些结果中,contents
不包含文本,仅包含 Tag
个对象,因此当您尝试 select 切片时,您会得到 TypeError
Tag
的属性字典。
您可以使用 try-except 块捕获此类错误,
for result in results:
try:
name = result.contents[0][0:-1]
except TypeError:
continue
或者您可以使用 .strings
来 select 只有 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]
要了解您获得 TypeError: unhashable type: 'slice'
的原因,请阅读 t.m.adam's answer。简而言之,在最后一次迭代中 result
变量指向 bs4.element.Tag
对象而不是 bs4.element.NavigableString
.
下面是使用 try-except 块的工作解决方案,因为列表中的最后 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
...
但是,网站的维护者可能决定添加或删除一些成分,导致代码遗漏一些成分。
我正在尝试从网站上抓取一些信息。我能够成功地抓取我正在寻找的文本,但是当我尝试创建一个函数来将文本附加在一起时,我得到了一个不可散列类型的 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>
提前致谢!!
在您收集的一些结果中,contents
不包含文本,仅包含 Tag
个对象,因此当您尝试 select 切片时,您会得到 TypeError
Tag
的属性字典。
您可以使用 try-except 块捕获此类错误,
for result in results:
try:
name = result.contents[0][0:-1]
except TypeError:
continue
或者您可以使用 .strings
来 select 只有 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]
要了解您获得 TypeError: unhashable type: 'slice'
的原因,请阅读 t.m.adam's answer。简而言之,在最后一次迭代中 result
变量指向 bs4.element.Tag
对象而不是 bs4.element.NavigableString
.
下面是使用 try-except 块的工作解决方案,因为列表中的最后 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
...
但是,网站的维护者可能决定添加或删除一些成分,导致代码遗漏一些成分。