如何用BeautifulSoup提取嵌套数据?问题续篇
BeautifulSoup提取数据部分失败的问题排查
我写了一段用BeautifulSoup提取网页中链接、标题、价格和位置信息的代码,在部分页面运行正常,但某些页面只能提取少量记录甚至完全无法提取。以下是正常运行的页面结构和代码,以及无法正常运行的页面结构示例。
正常运行示例
代码
from bs4 import BeautifulSoup html = ''' <li class="cl-static-search-result" title="BELLO HONDA ACCORD "95 MIL MILLAS". REALMENTE COMO NUEVO"> <a href="link1"> <div class="title">BELLO HONDA ACCORD "95 MIL MILLAS". REALMENTE COMO NUEVO</div> <div class="details"> <div class="price">$4,600</div> <div class="location"> Miami </div> </div> </a> </li> <li class="cl-static-search-result" title="Honda Element"> <a href=" link2 "> <div class="title">Honda Element</div> <div class="details"> <div class="price">$4,950</div> <div class="location"> Coral springs </div> </div> </a> </li> <li class="cl-static-search-result" title="Mint Jeep"> <a href=" link3 "> <div class="title">Mint Jeep</div> <div class="details"> <div class="price">$8,500</div> <div class="location"> Pompano </div> </div> </a> </li> ''' data = [] soup = BeautifulSoup(html) for e in soup.select('li[title]'): data.append({ 'link':e.a.get('href'), 'title':e.get('title'), 'price': e.select_one('.price').get_text(), 'location': e.select_one('.location').get_text(strip=True) }) print(data)
这段代码能正常提取所有3条记录的信息。
无法正常运行的页面结构示例
<li class="cl-static-search-result" title="Joyner 650"> <a href="LINK1"> <div class="title">Joyner 650</div> <div class="details"> <div class="price">$4,100</div> <div class="location"> Fernley </div> </div> </a> </li> <li class="cl-static-search-result" title="2009 Subaru legacy AWD!"> <a href="LINK2"> <div class="title">2009 Subaru legacy AWD!</div> <div class="details"> <div class="price">$6,300</div> </div> </a> </li> <li class="cl-static-search-result" title="2011 international durastar 4300 box truck"> <a href="LINK3"> <div class="title">2011 international durastar 4300 box truck</div> <div class="details"> <div class="price">$21,900</div> <div class="location"> Lodi </div> </div> </a> </li>
使用上述代码处理这段HTML时,只能提取第一条记录,后续记录被跳过。
问题原因
问题出在代码的容错处理缺失:第二个<li>节点中没有.location元素,代码中直接调用e.select_one('.location').get_text()会触发AttributeError,导致循环中断,后续记录无法被处理。
解决方案
修改代码,对可能缺失的元素做存在性判断,避免抛出异常中断循环。可以使用三元表达式或者if语句处理:
修改后的代码
from bs4 import BeautifulSoup html = ''' <li class="cl-static-search-result" title="Joyner 650"> <a href="LINK1"> <div class="title">Joyner 650</div> <div class="details"> <div class="price">$4,100</div> <div class="location"> Fernley </div> </div> </a> </li> <li class="cl-static-search-result" title="2009 Subaru legacy AWD!"> <a href="LINK2"> <div class="title">2009 Subaru legacy AWD!</div> <div class="details"> <div class="price">$6,300</div> </div> </a> </li> <li class="cl-static-search-result" title="2011 international durastar 4300 box truck"> <a href="LINK3"> <div class="title">2011 international durastar 4300 box truck</div> <div class="details"> <div class="price">$21,900</div> <div class="location"> Lodi </div> </div> </a> </li> ''' data = [] soup = BeautifulSoup(html) for e in soup.select('li[title]'): # 处理位置信息,判断元素是否存在 location_elem = e.select_one('.location') location = location_elem.get_text(strip=True) if location_elem else None data.append({ 'link': e.a.get('href').strip(), # 顺便处理链接的空格 'title': e.get('title'), 'price': e.select_one('.price').get_text().strip(), 'location': location }) print(data)
这段代码会对缺失的location字段返回None,不会中断循环,能提取所有3条记录。
内容的提问来源于stack exchange,提问作者user3618585
相关产品推荐
相关产品推荐

