如何从美丽的汤中收集html中的数据并将其列入清单

时间:2018-01-06 13:03:02

标签: python html python-3.x beautifulsoup

我想从html文件中收集数据,然后将一些数据放入变量或列表中。 但我不太了解美丽的汤。特别是如何浏览结构。

这里获取src url属性的最佳方法是什么? :

<div id="headshot">
<img title="Photo of someone" alt="Photo of somenone" src="url/file.jpg">
</div>

这里如何导航并将p类值放入列表中? :

                <p class="bioheading">value</p>
                <div class="biodata">value</div>
                <p class="bioheading">value</p>
                <p class="biodata">value</p>
                <p class="bioheading">value</p>
                <p class="biodata"><a href"http://url.com/month=01&amp;year=2018&amp;day=02">January 01, 1900</a> (117 years old)</p>
                <p class="bioheading">value</p>
                <p class="biodata">value</p>
                <p class="bioheading">value</p>
                <p class="biodata">value</p>

同样的:

<div id="vitalbox" class="tab-content">
<div role="tabpanel" class="tab-pane active" id="home">
    <div class="row">
        <div class="col-xs-12 col-sm-4">
            <p class="bioheading">value</p>
            <p class="biodata">value</p>
            <p class="bioheading">value</p>
            <p class="biodata">value</p>
            <p class="bioheading">value</p>
            <p class="biodata">value</p>
        </div>

这里如何获得性别价值? :

<input name="Gender" value="m" type="hidden">

特别是这个HTML可能会出错。 对不起这个初学者的问题。

最好的问候。

编辑:

k=0
a_table=[]
bday1=''
for link in soup.findAll('a'):
    a_table.append(str(link.get('href')))
    #out.write(str(i)+'\t'+str(p.text)+'\n')
    if re.match(regs4,str(link.get('href')),re.M) != None:
        bday1 = re.search(regs1,str(link.get('href')),re.M)
    else:
        bday1 = 'http://url.com/calendar.asp?calmonth=01&amp;calyear=2018&amp;calday=01'
    k=k+1

我试着收集一个href =并检查它是否需要url。与正则表达式 .find_All()将无法正常运行错误:

builtins.TypeError: 'NoneType' object is not callable

所以我正在使用.findAll()

这也不起作用,还有几个输入:

for _input in soup.findAll('input'):
    if str(_input.attrs['name']) == 'Gender':
        if str(_input.attrs['value']) == 'f':
            out.write('F') 
        elif str(_input.attrs['value']) == 'm':
            out.write('M')
        else:
            out.write('—')

得到此错误:

builtins.KeyError: 'name'

2 个答案:

答案 0 :(得分:3)

对比尔的答案进行一些修改/改进:

  • 您可以使用.select_one()代替.select()[0]通过CSS选择器查找单个元素
  • 您不需要attrs并使用类似字典的标记属性访问权限:

    soup.select_one('#headshot img')['src']
    
  • .get_text() is a bit more robust than accessing .text directly

  • 您可以改进用于获取p元素的CSS选择器,并使用类名称以bio开头的事实:

    #vitalbox #home p[class^=bio]
    
  • 您应该使用find_all()而不是已弃用的findAll()

  • 您甚至可以使用soup('p')快捷方式代替soup.find_all('p')soup.input['value']代替soup.find('input').attrs['value']

答案 1 :(得分:2)

select #headshot找到id'headshot'的元素,img找到带有此标记的后代元素。由于select可能会找到元素列表,因此我们会坚持列表中的第一项,并询问元素src属性。

>>> HTML = '''\
... <div id="headshot">
... <img title="Photo of someone" alt="Photo of somenone" src="url/file.jpg">
... </div>'''
>>> soup = bs4.BeautifulSoup(HTML, 'lxml')
>>> soup.select('#headshot img')[0].attrs['src']
'url/file.jpg'

使用findAll标识所有p元素,然后在列表解析中获取每个元素的文本。

>>> HTML = '''\
... <p class="bioheading">value</p>
... <div class="biodata">value</div>
... <p class="bioheading">value</p>
... <p class="biodata">value</p>
... <p class="bioheading">value</p>
... <p class="biodata"><a href"http://url.com/month=01&amp;year=2018&amp;day=02">January 01, 1900</a> (117 years old)</p>
... <p class="bioheading">value</p>
... <p class="biodata">value</p>
... <p class="bioheading">value</p>
... <p class="biodata">value</p>'''
>>> soup = bs4.BeautifulSoup(HTML, 'lxml')
>>> [p.text for p in soup.findAll('p')]
['value', 'value', 'value', 'value', 'January 01, 1900 (117 years old)', 'value', 'value', 'value', 'value']

如上所述,使用select明确指定所需内容,然后在列表推导中获取文本值。

>>> HTML = '''\
... <div id="vitalbox" class="tab-content">
... <div role="tabpanel" class="tab-pane active" id="home">
... <div class="row">
... <div class="col-xs-12 col-sm-4">
... <p class="bioheading">value</p>
... <p class="biodata">value</p>
... <p class="bioheading">value</p>
... <p class="biodata">value</p>
... <p class="bioheading">value</p>
...  <p class="biodata">value</p>
...  </div>'''
>>> soup = bs4.BeautifulSoup(HTML, 'lxml')
>>> [p.text for p in soup.select('#vitalbox #home .row .col-xs-12 p')]
['value', 'value', 'value', 'value', 'value', 'value']

在这种情况下,只有一个元素,即input;因此,我使用find。由于我使用了find(而不是产生列表的方法),我知道最多会返回一个元素。我请求它的属性。

>>> HTML = '''\
... <input name="Gender" value="m" type="hidden">'''
>>> soup = bs4.BeautifulSoup(HTML, 'lxml')
>>> soup.find('input').attrs['value']
'm'