输出soup.findall()作为使用re模块进一步文本操作的输入

时间:2013-11-24 08:02:54

标签: python regex web-scraping beautifulsoup

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

普通变量文本输入正在工作,但如果我传递了soup.findall()的输出,则会抛出跟随错误。

  

回溯(最近一次调用最后一次):文件“scrape2.py”,第18行,in          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:期望的字符串或缓冲区

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

3 个答案:

答案 0 :(得分:0)

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

顺便说一句,从你正在做的事情来说,如果你想获得某个身份证的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')]

答案 1 :(得分:0)

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

但是你的正则表达式似乎是错误的 - 除了它与你的例子中的URL不匹配,它在网络位置有一个数字。

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

你应该做这样的事情:

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

您还必须决定如何处理文档不包含您正在查找的数据的可能性。我显示的代码会抛出异常,但您可以检查None.find()是否返回.a,如果您更愿意无异常处理它。致电has_key(),了解href元素是否存在<a>

答案 2 :(得分:0)

我有一个问题需要抓取我们需要获取渲染内容的位置,或者是典型浏览器中的可见内容。在下面的情况下,不可显示的标记嵌套在样式标记中,并且在我检查过的许多浏览器中都不可见。存在其他变体,例如将类标签设置显示为无。然后使用这个类作为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中它保留了未呈现的文本。在搜索了SO后,我们在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