【问题标题】:Having problems understanding BeautifulSoup filtering在理解 BeautifulSoup 过滤时遇到问题
【发布时间】:2015-11-26 18:09:45
【问题描述】:

谁能解释一下过滤是如何与 Beautiful Soup 一起工作的。我得到了下面的 HTML,我试图从中过滤特定数据,但我似乎无法访问它。我尝试了各种方法,从收集所有 class=g 到仅抓取该特定 div 中感兴趣的项目,但我只得到无返回或没有打印。

每个页面都有一个<div class="srg"> div 和多个<div class="g"> div,我希望使用的数据是<div class="g"> 的数据。其中每一个都有 多个 div,但我只对 <cite><span class="st"> 数据感兴趣。我正在努力理解过滤的工作原理,任何帮助将不胜感激。

我尝试遍历 div 并抓取相关字段:

 soup = BeautifulSoup(response.text)   

 main = soup.find('div', {'class': 'srg'})
 result = main.find('div', {'class': 'g'})
 data = result.find('div', {'class': 's'})
 data2 = data.find('div')
 for item in data2:
     site = item.find('cite')
     comment = item.find('span', {'class': 'st'})

 print site
 print comment

我也尝试过进入初始 div 并找到所有;

 soup = BeautifulSoup(response.text) 

 s = soup.findAll('div', {'class': 's'})

 for result in s:
     site = result.find('cite')
     comment = result.find('span', {'class': 'st'})

 print site
 print comment

测试数据

<div class="srg">
    <div class="g">
    <div class="g">
    <div class="g">
    <div class="g">
        <!--m-->
        <div class="rc" data="30">
            <div class="s">
                <div>
                    <div class="f kv _SWb" style="white-space:nowrap">
                        <cite class="_Rm">http://www.url.com.stuff/here</cite>
                    <span class="st">http://www.url.com. Some info on url etc etc
                    </span>
                </div>
            </div>
        </div>
        <!--n-->
    </div>
    <div class="g">
    <div class="g">
    <div class="g">
</div>

更新

在 Alecxe 的解决方案之后,我再次尝试将其正确,但仍然没有打印任何内容。所以我决定再看看soup,它看起来不一样。我之前从requestsresponse.text。我只能认为BeautifulSoup 修改了response.text 或者我第一次弄错了样本(不确定如何)。然而,下面是基于我从soup 打印中看到的新示例。在此之下,我尝试获取我所追求的元素数据。

<li class="g">
<h3 class="r">
    <a href="/url?q=url">context</a>
</h3>
<div class="s">
    <div class="kv" style="margin-bottom:2px">
        <cite>www.url.com/index.html</cite> #Data I am looking to grab
        <div class="_nBb">‎
            <div style="display:inline"snipped">
                <span class="_O0"></span>
            </div>
            <div style="display:none" class="am-dropdown-menu" role="menu" tabindex="-1">
                <ul>
                    <li class="_Ykb">
                        <a class="_Zkb" href="/url?/search">Cached</a>
                    </li>
                </ul>
            </div>
        </div>
    </div>
    <span class="st">Details about URI </span> #Data I am looking to grab

更新尝试

到目前为止,我尝试采用 Alecxe 的方法没有成功,我是否走在正确的道路上?

soup = BeautifulSoup(response.text)

for cite in soup.select("li.g div.s div.kv cite"):
    span = cite.find_next_sibling("span", class_="st")

    print(cite.get_text(strip=True))
    print(span.get_text(strip=True))

【问题讨论】:

    标签: python html beautifulsoup


    【解决方案1】:

    首先获取类名srgdiv,然后在srg 中找到类名s 的所有div,并获取sitecomment 的文本。下面是我的工作代码-

    from bs4 import BeautifulSoup
    
    html = """<div class="srg">
        <div class="g">
        <div class="g">
        <div class="g">
        <div class="g">
            <!--m-->
            <div class="rc" data="30">
                <div class="s">
                    <div>
                        <div class="f kv _SWb" style="white-space:nowrap">
                            <cite class="_Rm">http://www.url.com.stuff/here</cite>
                        <span class="st">http://www.url.com. Some info on url etc etc
                        </span>
                    </div>
                </div>
            </div>
            <!--n-->
        </div>
        <div class="g">
        <div class="g">
        <div class="g">
    </div>"""
    
    soup = BeautifulSoup(html , 'html.parser')
    labels = soup.find('div',{"class":"srg"})
    
    spans = labels.findAll('div', {"class": 'g'})
    
    sites = []
    comments = []
    
    for data in spans:
        site = data.find('cite',{'class':'_Rm'})
        comment = data.find('span',{'class':'st'})
        if site:#Check if site in not None
            if site.text.strip() not in sites:
                sites.append(site.text.strip())
            else:
                pass
        if comment:#Check if comment in not None
            if comment.text.strip() not in comments:
                comments.append(comment.text.strip())
            else: pass
    
    print sites
    print comments
    

    输出-

    [u'http://www.url.com.stuff/here']
    [u'http://www.url.com. Some info on url etc etc']
    

    编辑--

    为什么你的代码不起作用

    试一试-

    您正在使用 result = main.find('div', {'class': 'g'}) 它将抓取单个和第一个遇到的元素,但第一个元素没有 div 类名称 s 。所以这段代码的下一部分将不起作用。

    试试两个-

    您正在打印不在打印范围内的sitecomment。所以尝试在 for 循环中打印。

    soup = BeautifulSoup(html,'html.parser') 
    
    s = soup.findAll('div', {'class': 's'})
    
    for result in s:
        site = result.find('cite')
        comment = result.find('span', {'class': 'st'})
        print site.text#Grab text
        print comment.text
    

    【讨论】:

    • 谢谢,尽管这无助于解释它为什么有效以及为什么我的无效:(
    • 有没有办法不需要遍历 div 的层次结构来获取数据?我的仍然没有工作,我认为这是因为我从样本中遗漏了很多 html(纯粹是为了保持简单),因为有很多数据。但我只对采样的数据感兴趣。
    【解决方案2】:

    您不必手动处理层次结构 - 让BeautifulSoup 担心它。您的第二种方法接近您真正应该尝试做的事情,但是一旦您获得带有 class="s" 且内部没有 cite 元素的 div,它就会失败。

    相反,您需要让BeautifulSoup 知道您对包含特定元素的特定元素感兴趣。让我们询问位于 div 元素内的 cite 元素和位于 div 元素内的 class="g"class="srg" - div.srg div.g cite CSS selector 会找到我们所要询问的内容:

    for cite in soup.select("div.srg div.g cite"):
        span = cite.find_next_sibling("span", class_="st")
    
        print(cite.get_text(strip=True))
        print(span.get_text(strip=True))
    

    然后,一旦找到cite,我们就会“横向移动”并使用class="st" 抓取下一个span 兄弟元素。不过,是的,我们假设它存在。

    对于提供的示例数据,它会打印:

    http://www.url.com.stuff/here
    http://www.url.com. Some info on url etc etc
    

    更新输入数据的更新代码:

    for cite in soup.select("li.g div.s div.kv cite"):
        span = cite.find_next("span", class_="st")
    
        print(cite.get_text(strip=True))
        print(span.get_text(strip=True))
    

    另外,请确保您使用的是第 4 个BeautifulSoup 版本:

    pip install --upgrade beautifulsoup4
    

    导入语句应该是:

    from bs4 import BeautifulSoup
    

    【讨论】:

    • 捂脸! bs4是修复!当然,我的过滤并没有出现,但是一旦修复就是 bs4
    猜你喜欢
    • 2021-10-21
    • 1970-01-01
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-17
    • 2013-03-19
    相关资源
    最近更新 更多