我使用BeautifulSoup来解析一个简单的HTML表。由于数据中的一些不一致,BeautifulSoup似乎无法正确解析和标记内容。下面是代码:
import requests
from bs4 import BeautifulSoup
page = 1
city = 'vantaa'.capitalize()
URL = 'https://asuntojen.hintatiedot.fi/haku/?cr=1&t=3&l=0&search=1&sf=0&so=a&renderType=renderTypeTable&print=1&z={}&c={}'.format(page, city)
page = requests.get(URL)
soup = BeautifulSoup(page.content, "html.parser")
tables = soup.find_all('tbody', attrs={'class':'odd'})
table = max(tables, key=len)
rows = table.find_all('tr')
一个正确标记的行看起来像这样:
<tr>
<td class="area">Area 1</td>
<td>Random string 1+1q, d</td>
<td class="type">xb</td>
<td class="cellAlignRight">38,00</td>
<td class="cellAlignRight">132000</td>
<td class="cellAlignRight">3474</td>
<td class="cellAlignRight">1661</td>
<td>1/1</td>
<td>no</td>
<td>less.</td>
<td>oma
<td>G<sub>2013</sub></td>
</td>
</tr>
然而,在文档中间出现了错误,最后几行合并成一个大字符串
<tr>
<td class="neighborhood">Itä-hakkila</td>
<td>1h, avokeitti&#...</td>
<td class="houseType">rt</td>
<td class="cellAlignRight">21,50</td>
<td class="cellAlignRight">149000</td>
<td class="cellAlignRight">6930</td>
<td class="cellAlignRight">2017</td>
<td>1/2</td>
<td>ei</td>
<td>hyvä</td>
<td>oma <td>C<sub>2013</sub></td>
</tr>
<tr>
<td class="neighborhood">Kivist&#246;</td>
<td>1h+kt</td>
<td class="houseType">kt</td>
<td class="cellAlignRight">27,00</td>
<td class="cellAlignRight">132000</td>
<td class="cellAlignRight">4889</td>
<td class="cellAlignRight">2018</td>
<td>5/6</td>
<td>on</td>
<td>hyvä</td>
<td>vuokra <td>C<sub>2013</sub></td>
</tr>
这似乎是由这个单元格1h, avokeitti&#...
引起的,BeautifulSoup变成了<td>1h, avokeitti&#...</td>
,在网页上的实际HTML中没有这样的问题
<tr>
<td class="neighborhood">Itä-hakkila</td>
<td>1h, avokeitti&#...</td>
<td class="houseType">rt</td>
<td class="cellAlignRight">21,50</td>
<td class="cellAlignRight">149000</td>
<td class="cellAlignRight">6930</td>
<td class="cellAlignRight">2017</td>
<td>1/2</td>
<td>ei</td>
<td>hyvä</td>
<td>oma <td>C<sub>2013</sub></td>
</tr>
我试过使用unicode.unescape()
给TypeError: 'NoneType' object is not callable
整个表,我试过使用re.sub(r'<', '<', text)
来清理整个表或单行,但这给TypeError: expected string or bytes-like object
。
我通过执行df_list = pd.read_html(page.text)
将表作为数据框取出来绕过了这个问题(并且不得不处理其他格式问题),但原始问题没有解决。
使用解析器html5lib
正确解析此HTML
soup = BeautifulSoup(page.content, "html5lib")
可能需要使用pip
来安装模块html5lib
请参阅文档中有关不同解析器的更多信息:安装解析器
有advantages
和disadvantages
的表