Python 在字符串中使用通配符
Python Using wildcard inside of strings
我正在尝试从 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 个空字符串。请帮助我真的很想继续我的项目。
mov_title_pattern=r'.htm">([A-Za-z0-9 ]*)</a></font></b></td>'
尝试 this.This 应该适合您的 case.See 演示。
你的正则表达式没有多大意义。它匹配 .htm">[A-Z]
的次数越少越好,通常为零,产生一个空字符串。
此外,对于像这样的非常通用的正则表达式,不能保证它只匹配结果行。生成的页面包含许多其他地方,您可以在这些地方找到 .htm">
后跟一些东西。
更一般地说,我会提倡一种方法,您可以在其中制作一个正则表达式,该正则表达式可以精确标识每个生成的结果行,并从中提取您想要的所有值。换句话说,尝试类似
re.findall('stuff (rank) stuff (title) stuff stuff stuff')
(我把它留作练习,用适当的 HTML 片段设计一个精确的正则表达式,其中我有 stuff
占位符)
并从每个匹配的行中提取 "rank" 组和 "title" 组。
诚然,抓取始终是一项脆弱的工作。如果你让你的正则表达式非常紧凑,如果网站改变了它布局中的一些细节,它很可能会停止工作。如果你让它太放松,它有时会 return 错误的东西。
只是 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
标记,我们必须依赖像 colspan
或 border
这样的属性。 [1:-3]
slice 是用来消除表头和总行的。
对于 this page,要到达 table,您可以依赖图表元素并获取它的下一个 table
兄弟:
for row in soup.find('div', id='chart_container').find_next_sibling('table').find_all('tr')[1:-3]:
...
我正在尝试从 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 个空字符串。请帮助我真的很想继续我的项目。
mov_title_pattern=r'.htm">([A-Za-z0-9 ]*)</a></font></b></td>'
尝试 this.This 应该适合您的 case.See 演示。
你的正则表达式没有多大意义。它匹配 .htm">[A-Z]
的次数越少越好,通常为零,产生一个空字符串。
此外,对于像这样的非常通用的正则表达式,不能保证它只匹配结果行。生成的页面包含许多其他地方,您可以在这些地方找到 .htm">
后跟一些东西。
更一般地说,我会提倡一种方法,您可以在其中制作一个正则表达式,该正则表达式可以精确标识每个生成的结果行,并从中提取您想要的所有值。换句话说,尝试类似
re.findall('stuff (rank) stuff (title) stuff stuff stuff')
(我把它留作练习,用适当的 HTML 片段设计一个精确的正则表达式,其中我有 stuff
占位符)
并从每个匹配的行中提取 "rank" 组和 "title" 组。
诚然,抓取始终是一项脆弱的工作。如果你让你的正则表达式非常紧凑,如果网站改变了它布局中的一些细节,它很可能会停止工作。如果你让它太放松,它有时会 return 错误的东西。
只是 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
标记,我们必须依赖像 colspan
或 border
这样的属性。 [1:-3]
slice 是用来消除表头和总行的。
对于 this page,要到达 table,您可以依赖图表元素并获取它的下一个 table
兄弟:
for row in soup.find('div', id='chart_container').find_next_sibling('table').find_all('tr')[1:-3]:
...