我正在尝试从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个空字符串。请帮助我真的想继续我的项目。
答案 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,因此我们必须依赖colspan
或border
等属性。 [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>'
试试这个。这应该适合你的情况。参见演示。
答案 2 :(得分:1)
你的正则表达没有多大意义。它尽可能少地匹配.htm">[A-Z]
,通常为零,产生一个空字符串。
此外,使用非常通用的正则表达式,不能保证它只匹配结果行。生成的页面包含许多其他地方,您可以在其中找到.htm">
后跟某些内容。
更一般地说,我会提倡一种方法,在这种方法中,您可以精确地识别每个生成的结果行,并从中提取所需的所有值。换句话说,尝试像
这样的东西re.findall('stuff (rank) stuff (title) stuff stuff stuff')
(我将其留作练习,用适当的HTML片段设计精确的正则表达式,我有stuff
个占位符)
并从每个匹配的行中提取“rank”组和“title”组。
当然,刮痧总是很脆弱。如果你的正则表达式非常紧张,如果网站在其布局中更改了一些细节,它可能会停止工作。如果你太放松了,有时候会回错。