使用通配符Beautifulsoup查找href值

时间:2013-11-23 10:05:34

标签: python html beautifulsoup

我正在尝试使用Beautiful Soup和Python收集网址列表。我是两者的新用户,我需要帮助找出如何使用通配符查找href值。 HTML代码看起来像

<table class="sortable  stats_table" id="team_index">
 <colgroup>...</colgroup>
 <thead>...</thead>
 <tbody>
     <tr class data-row="0">
          <td align="left">...</td>
          <td align="left">...</td>
          <td align="left">
                <a href="/teams/crd/2013.htm">Arizona Cardinals</a>
          </td>
          <td align="right">6</td>
     <tr class data-row="1">
          <td align="left">...</td>
          <td align="left">...</td>
          <td align="left">
                <a href="/teams/crd/2012.htm">Arizona Cardinals</a>
          </td>
          <td align="right">6</td>
 </tbody>
 <tfoot></tfoot>
</table>

为简洁起见,我只包含了html表的前两行。我想找到<a>所有href="/teams/XXX/YYYY.htm"代码,其中XXX是团队名称,YYYY是年份,并将它们全部放入网址列表中。现在我使用以下代码

from bs4 import BeautifulSoup   
from urllib2 import urlopen     
import re

BASE_URL = "http://www.pro-football-reference.com"
teams_url = ("http://www.pro-football-reference.com/teams/crd/")

soup=BeautifulSoup(urlopen(teams_url),"lxml")

teamtable = soup.find(lambda tag: tag.name=="table" and tag.has_attr("id") and     
            tag["id"]=="team_index")

rows = teamtable.find_all("tr", attrs={""})

test=rows.find_all('a', {'href': lambda x : x.startswith('/teams/')})

masterlist = [BASE_URL + link.a["href"] for link in test]

从以前编译的url列表中提取变量teams_url,其中包含"http://www.pro-football-reference.com/teams/XXX/"形式的成员。由于最后一行,我提供的代码会出现以下错误:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'ResultSet' object has no attribute 'find_all'
soup.find_all('a', {'href': lambda x : x.startswith('/teams/')})

问题1)如何让代码收集表中的所有标签,以便我有一个列表

masterlist = [`www.pro-football-reference.com/teams/crd/2013', 
              `www.pro-football-reference.com/teams/crd/2012',
              `www.pro-football-reference.com/teams/crd/2011'
              ...]

没有硬编码团队缩写,因为我将把这段代码传递给`teams_url&#39;每个团队列表中的变量。

问题2)数据中有50年(行),但我只想将标签从2012年拉到2000年。我该怎么做?

此外,由于html代码中的行标记为<tr class data-row="0">,因此我的代码中可能会出现拼写错误,但是,由于某种原因,lxml和html5解析器都返回了标记的属性作为<tr class="">并且我不知道为什么或如何解决这个问题,所以任何额外的帮助都会很棒。

谢谢

2 个答案:

答案 0 :(得分:1)

几点:

此:

teamtable = soup.find(lambda tag: tag.name=="table" and tag.has_attr("id") and     
            tag["id"]=="team_index")

可以简单地说:

teamtable = soup.find('table', {'id': 'team_index'})

以下内容没有按照您的想法进行... attrs = {""}创建一个项目集(空字符串),而attrs需要映射:

rows = teamtable.find_all("tr", attrs={""})

您可以删除attrs并改为使用rows = teamtable.find_all('tr')

然后:

test=rows.find_all('a', {'href': lambda x : x.startswith('/teams/')})

可以成为(如果你想在以后进行更复杂的匹配时有用):

import re
test = rows.find_all('a', href=re.compile('/teams/'))

或者,至少lambda x: x and x.startswith('/teams/')以避免对没有href的元素发生属性错误...

然后在完成所有工作后,你应该能够继续......

答案 1 :(得分:0)

您可以在find_all

的attrib匹配参数中使用正则表达式
>>> import re
>>> for possible_link in soup.find_all('a', {'href': re.compile(r'/teams/crd/\d.*')}):
...   print possible_link.text, possible_link.attrs
... 
2013 {'href': '/teams/crd/2013.htm'}
Arizona Cardinals {'href': '/teams/crd/2013.htm'}
2012 {'href': '/teams/crd/2012.htm'}
Arizona Cardinals {'href': '/teams/crd/2012.htm'}
-- SNIP --
1920 {'href': '/teams/crd/1920.htm'}
Chicago Cardinals {'href': '/teams/crd/1920.htm'}

简而言之,.attrs将包含您要查找的href,.text会显示<a>TEXT</a>标记之间的文字。