2012-12-01 36 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