当父元素在隐式命名空间中时,BeautifulSoup丢失子元素
我正在用selenium和BeautifulSoup为Nordstrom的网站制作一个屏幕抓取工具。这个网站其实并没有每个标签都放在一个命名空间里,但Firefox的webdriver为了避免混淆,给它创建了一个命名空间(具体来说,网站有一个<html xmlns>
标签,这让驱动有点困惑)。
因此,所有内容都放在了命名空间a0
里。不过,使用Beautiful Soup的find()
方法时,它只会返回父元素和(有时)一层子元素。
举个例子,这段html是这样的:
<div class='division'>
<a href='#'>
<img />
</a>
</div>
所有内容都在隐含的a0
命名空间中,所以我们可以用以下方式获取图片:
soup.find('a0:div',{'class':'division'}).find('a0:img')
但是,这样返回的是None
。我查看了soup.prettify()
,可以肯定a0:img
是在a0:div
里面。请问这是一个预期的功能(那我就需要找其他方法)还是一个bug(那我就需要找到解决办法)?
编辑:
为了避免混淆,这里有一个示例,展示整个工作流程:
from selenium import webdriver
from BeautifulSoup import BeautifulSoup # Note that this is BeautifulSoup 3
b = webdriver.Firefox()
b.get("http://shop.nordstrom.com/c/womens-skirts")
borscht = BeautifulSoup(b.page_source)
theImageThatCannotBeFound = borscht.find('a0:div',{'class':'fashion-item'}).find('a0:img')
上面的代码将theImageThatCannotBeFound
设置为None
,我认为这是不对的。希望这样能让事情更清楚。
1 个回答
2
这个方法对我有效。
import urllib
from BeautifulSoup import BeautifulSoup
url = 'http://shop.nordstrom.com/c/womens-skirts'
fp = urllib.urlopen(url)
soup = BeautifulSoup(fp)
print soup.find('div',{'class':'fashion-item'}).findAll('img') # also tried .find
试着去掉a0:
。这似乎就是你遇到的问题所在。
编辑:
我在使用Chrome和Firefox浏览器时,无论是在Selenium里面还是外面,查看时xmlns
都是空字符串,这就是为什么上面的代码对我有效。看起来是某个组件不匹配,导致我们得到的结果不一样,而你得到了命名空间a0:
。
因为我无法重现这个情况,我能找到的唯一解决办法(虽然有点笨拙)就是手动替换命名空间:
source = browser.page_source.replace('a0:div','div')
soup = BeautifulSoup(source)
print soup.find('div',{'class':'fashion-item'}).find('img')
我承认这并不是一个理想的解决方案。如果我找到更好的方法,我会继续寻找并更新我的回答。