2012-12-01 37 views
1

我试图解析从HTML代码的结果从搜索查询返回的数字,但是当我用查找/指数()似乎返回错误的位置。我搜索的字符串有重音,所以我尝试以Unicode形式搜索它。的Python:在HTML索引搜索Unicode字符串/ find返回错误的位置

的HTML代码的片段被解析:

<div id="WPaging_total"> 
    Aproximádamente 37 resultados. 
</div> 

,我寻找这样的:

str_start = html.index(u'Aproxim\xe1damente ') 
str_end = html.find(' resultados', str_start + 16)#len('Aproxim\xe1damente ')==16 
print html[str_start+16:str_end] #works by changing 16 to 24 

打印语句返回:

damente 37 

当预期结果是:

37 

看来str_start没有启动在我寻找,而不是8位后面的字符串的开头。

print html[str_start:str_start+5] 

输出:

l"> 

的问题是难以复制的,虽然,因为使用的代码片段时,只有整个HTML字符串中搜索时它不会发生。我可以简单地将str_start + 16更改为str_start + 24,以便按预期工作,但这并不能帮助我理解问题。这是一个Unicode问题吗?希望有人能够对这个问题提出一些看法。

谢谢。

LINK: http://guiasamarillas.com.mx/buscador/?actividad=Chedraui&localidad=&id_page=1

样品编号

from urllib2 import Request, urlopen 

url = 'http://guiasamarillas.com.mx/buscador/?actividad=Chedraui&localidad=&id_page=1' 
post = None 
headers = {'User-Agent':'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2)'}   
req = Request(url, post, headers) 
conn = urlopen(req) 

html = conn.read() 

str_start = html.index(u'Aproxim\xe1damente ') 
str_end = html.find(' resultados', str_start + 16) 
print html[str_start+16:str_end] 
+0

'html'是什么?一个unicode字符串?一个utf-8编码的字符串? –

+0

html是str类型,由urllib2使用Request/open返回。我试过unicode(html,'utf-8'),但我得到了完全相同的结果。 – LightOS

+0

你需要提供更多关于''''和'html'的细节。也许提供链接等,所以我们可以自己拉。 – jdotjdot

回答

3

你的问题最终归结为这样一个事实:在Python 2.x中,str类型表示一个字节序列,而unicode类型表示一个字符序列。由于一个字符可以由多个字节编码,这意味着字符串的一个unicode类型表示的长度可能与相同字符串的str类型表示的长度不同,并且以同样的方式,字符串的表示可以指向文本的不同部分,而不是表示str表示上的相同索引。

发生了什么事是,当你做str_start = html.index(u'Aproxim\xe1damente '),Python的自动html变量进行解码,假设它是在UTF-8编码。(嗯,其实,我的电脑,我只是得到了UnicodeDecodeError当我尝试执行该行。我们的一些有关文本编码系统设置必须是不同的。)因此,如果str_start为N,则这意味着u'Aproxim\xe1damente '出现在HTML的第n个字符。然而,当你使用它作为一个片索引后,试图和第(n + 16)后获得的内容个字符,你实际上得到的是(N + 16)之后的东西次字节,在这种情况下,并不等同,因为较早的页面内容包含重音字符,这些字符在utf-8中编码时占用2个字节。

最好的解决办法是简单,当你收到它的HTML转换为Unicode。你的示例代码的这个小修改将做你想要的没有错误或怪异的行为:

from urllib2 import Request, urlopen 

url = 'http://guiasamarillas.com.mx/buscador/?actividad=Chedraui&localidad=&id_page=1' 
post = None 
headers = {'User-Agent':'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2)'}   
req = Request(url, post, headers) 
conn = urlopen(req) 

html = conn.read().decode('utf-8') 

str_start = html.index(u'Aproxim\xe1damente ') 
str_end = html.find(' resultados', str_start + 16) 
print html[str_start+16:str_end] 
+0

谢谢马克,那工作完美!我愚蠢地尝试了'unicode(html).encode('utf-8')'。另外,我很抱歉无法为您的答案投票,我还没有代表。 – LightOS

+0

@LightOS很高兴有帮助。 :)正如你可能已经想通了,'unicode(html).encode'('utf-8')'行不会有帮助,因为在你的机器上它没有任何效果 - 它将utf-8字节串解码成一个unicode字符串,然后重新编码它。 (另一方面,在我的机器上,它尝试使用ascii编解码器进行解码并抛出'UnicodeDecodeError')。 –

+0

这让我很担心,因为我需要在其他机器上运行脚本,而文本编码的默认系统设置可能会导致差异并导致问题。 – LightOS

0

这不是真的清楚你想要做什么,但如果我猜正确,你试图要从HTML文件中获取大概的结果数量,您可能会更好,因为您使用re模块进行正则表达式。

import re 
re.search(ur'(?<=Aproxim\xe1damente)\d+', s).group(0) 

# returns: 
# u'37' 

最后,你最好的选择是一个真正的包像lxmlBeautifulSoup,但没有更多的情况下,我不能给你那些更具体的帮助。

+1

谢谢你的回复。我可以使用re模块或其他替代方法,但这仍然不能帮助我理解为什么使用index/find不起作用。 – LightOS