Python在字符串中使用通配符

时间:2015-01-02 08:30:53

标签: python html regex web-scraping html-parsing

我正在尝试从boxofficemoviemojo.com废弃数据,并且我已正确设置所有内容。但是我收到一个我无法弄清楚的逻辑错误。基本上我想拍摄前100部电影并将数据写入csv文件。

我目前正在使用此网站的html进行测试(其他年份相同):http://boxofficemojo.com/yearly/chart/?yr=2014&p=.htm

有很多代码,但这是我正在努力的主要部分。代码块如下所示:

def grab_yearly_data(self,page,year):
    # page is the url that was downloaded, year in this case is 2014.

    rank_pattern=r'<td align="center"><font size="2">([0-9,]*?)</font>'
    mov_title_pattern=r'(.htm">[A-Z])*?</a></font></b></td>'
    #mov_title_pattern=r'.htm">*?</a></font></b></td>' # Testing

    self.rank= [g for g in re.findall(rank_pattern,page)]
    self.mov_title=[g for g in re.findall(mov_title_pattern,page)]

self.rank完美无缺。但是self.mov_title不能正确存储数据。我想收到一个包含102个元素和电影标题的列表。但是我收到102个空字符串:''。一旦我弄清楚我做错了什么,程序的其余部分将非常简单,我在网上找不到我的问题的答案。我已经尝试过多次更改mov_title_pattern而且我没有收到任何内容或102个空字符串。请帮助我真的想继续我的项目。

3 个答案:

答案 0 :(得分:2)

只是don't attempt to parse HTML with regex - 这会节省你的时间,最重要的是 - 头发,并会让你的生活更轻松。

以下是使用BeautifulSoup HTML parser的解决方案:

from bs4 import BeautifulSoup
import requests

url = 'http://boxofficemojo.com/yearly/chart/?yr=2014&p=.htm'
response = requests.get(url)

soup = BeautifulSoup(response.content)

for row in soup.select('div#body td[colspan="3"] > table[border="0"] tr')[1:-3]:
    cells = row.find_all('td')
    if len(cells) < 2:
        continue

    rank = cells[0].text
    title = cells[1].text
    print rank, title

打印:

1 Guardians of the Galaxy
2 The Hunger Games: Mockingjay - Part 1
3 Captain America: The Winter Soldier
4 The LEGO Movie
...
98 Transcendence
99 The Theory of Everything
100 As Above/So Below

select()调用中的表达式是CSS Selector - 一种方便且有效的定位元素的方法。但是,由于此特定页面上的元素不方便地与id映射或标有class es,因此我们必须依赖colspanborder等属性。 [1:-3]切片用于消除标题和总行数。


对于this page,要进入桌面,您可以依赖图表元素并获取下一个table兄弟:

for row in soup.find('div', id='chart_container').find_next_sibling('table').find_all('tr')[1:-3]:
    ...

答案 1 :(得分:1)

mov_title_pattern=r'.htm">([A-Za-z0-9 ]*)</a></font></b></td>'

试试这个。这应该适合你的情况。参见演示。

https://www.regex101.com/r/fG5pZ8/6

答案 2 :(得分:1)

你的正则表达没有多大意义。它尽可能少地匹配.htm">[A-Z],通常为零,产生一个空字符串。

此外,使用非常通用的正则表达式,不能保证它只匹配结果行。生成的页面包含许多其他地方,您可以在其中找到.htm">后跟某些内容。

更一般地说,我会提倡一种方法,在这种方法中,您可以精确地识别每个生成的结果行,并从中提取所需的所有值。换句话说,尝试像

这样的东西
re.findall('stuff (rank) stuff (title) stuff stuff stuff')

(我将其留作练习,用适当的HTML片段设计精确的正则表达式,我有stuff个占位符) 并从每个匹配的行中提取“rank”组和“title”组。

当然,刮痧总是很脆弱。如果你的正则表达式非常紧张,如果网站在其布局中更改了一些细节,它可能会停止工作。如果你太放松了,有时候会回错。