【问题标题】:Output of soup.findall() as input for further text manipulation using re modulesoup.findall() 的输出作为使用 re 模块进行进一步文本操作的输入
【发布时间】:2013-12-08 23:03:16
【问题描述】:

尝试使用 BeautifulSoup 从网页中提取文本。 想要将 soup.findall() 的输出作为输入传递给使用 re 模块进行进一步数据清理

普通变量文本输入正常,但如果我传递soup.findall() 的输出,它会抛出以下错误。

Traceback(最近一次调用最后一次):文件“scrape2.py”,第 18 行,在 url = re.search('http://[az.]/[A-Za-z/%0-9-]', univ) 文件 "/usr/lib/python2.7 /re.py”,第 142 行,正在搜索中 return _compile(pattern, flags).search(string) TypeError: expected string or buffer

soup.findall() 的可变打印正在工作。 如何直接传递soup.findall() 的输出作为输入ro re.search 命令。

完整的源代码

from BeautifulSoup import BeautifulSoup
import urllib2
import os
import re
page=urllib2.urlopen(url)


soup = BeautifulSoup(open("rr-ss.html").read())
univ=soup.findAll('div',{'id':'divBrand1'})

print univ
text = '<span class="normaltextblue"><a href="http://www.roya3d.com/zdae/bug/coastdfilm-coated%20tab">Rocks</a></span>&nbsp;&nbsp;&nbsp;'


#following command throwing error 
url = re.search( 'http://[a-z.]*/[A-Za-z/%0-9-]*', univ)

#following line working fine
url = re.search( 'http://[a-z.]*/[A-Za-z/%0-9-]*', text)

if url:
    found = url.group(0)    
    print found

【问题讨论】:

    标签: python regex web-scraping beautifulsoup


    【解决方案1】:

    findAll 返回 HTML 元素列表。列表不是字符串,HTML 元素也不是字符串,因此除非先将它们转换为字符串,否则不能对它们应用正则表达式。因此,您的实际问题“如何将findAll 的输出传递给regex.search()”的答案是使用unicode(univ)

    但是您的正则表达式似乎是错误的——除此之外,它与您示例中的 URL 不匹配,该 URL 在网络位置中有一个数字。

    此外,应该只有一个元素具有给定的id(这是 HTML 中的 id 点,它在文档中是唯一的)。所以findAll 似乎是错误的,除非你故意允许损坏的 HTML。

    你可能应该这样做:

    url = soup.find('div', {'id':'divBrand1'}).a['href']
    

    您还必须决定如何处理文档不包含您要查找的数据的可能性。我展示的代码会引发异常,但如果您希望在没有异常的情况下处理它,您可以检查是否从 .find().a 返回了 None。调用has_key() 以查看href 是否存在于&lt;a&gt; 元素上。

    【讨论】:

      【解决方案2】:

      当你发现这个问题时,你可以只打印“dir(object)”和“type(object)”,所以 findAll 结果是一个列表,您可以只访问 findAll 的元素。

      顺便说一句,从你的所作所为,我想知道你是否想获得某个 id 的 href? 我建议你可以使用 css 选择器,并使用 get('href'),例如

      #get the divs
      divbrands = soup.select('#divBrand1')
      for divbrand in divbrands:
          #get all <a></a> tags
          links = divbrand.select('a')
          for link in links:
              #get all the href
              print link.get('href')
      

      也可以写成一行:

      hrefs = [link.get('href') for link in soup.select('#divBrand1 > a')]
      

      【讨论】:

        【解决方案3】:

        我在抓取需要获取渲染内容或典型浏览器中的可见内容的位置时遇到了问题。在下面的情况下,不可显示的标签嵌套在样式标签中,并且在我检查过的许多浏览器中不可见。存在其他变体,例如将类标记设置显示定义为无。然后将此类用于 div。

        <html>
          <title>  Title here</title>
        
          <body>
        
            lots of text here <p> <br>
            <h1> even headings </h1>
        
            <style type="text/css"> 
                <div > this will not be visible </div> 
            </style>
        
        
          </body>
        
        </html>
        

        上面发布的一个解决方案是:

        html = Utilities.ReadFile('simple.html')
        soup = BeautifulSoup.BeautifulSoup(html)
        texts = soup.findAll(text=True)
        visible_texts = filter(visible, texts)
        print(visible_texts)
        
        
        [u'\n', u'\n', u'\n\n        lots of text here ', u' ', u'\n', u' even headings ', u'\n', u' this will not be visible ', u'\n', u'\n']
        

        这个解决方案在很多情况下确实有应用,并且通常可以很好地完成工作,但是在上面发布的 html 中,它保留了未呈现的文本。在搜索了一些解决方案之后,这里出现了 BeautifulSoup get_text does not strip all tags and JavaScriptRendered HTML to plain text using Python

        import nltk
        
        %timeit nltk.clean_html(html)
        was returning 153 us per loop
        

        ... 或使用 html2text

        betterHTML = html.decode(errors='ignore')
        %timeit html2text.html2text(betterHTML)
        %3.09 ms per loop
        

        【讨论】:

          猜你喜欢
          • 2021-01-05
          • 2022-01-27
          • 1970-01-01
          • 2015-10-31
          • 2021-07-08
          • 2021-01-11
          • 2022-08-11
          • 2018-09-11
          • 2014-10-27
          相关资源
          最近更新 更多