为什么这么多行数据无法获得?

时间:2012-01-19 12:47:38

标签: python html parsing lxml

我的代码:

import urllib
import lxml.html
equitydown="http://sc.hkex.com.hk/gb/www.hkex.com.hk/chi/market/sec_tradinfo/stockcode/eisdeqty_c.htm"   
file=urllib.urlopen(equitydown).read()   
root=lxml.html.document_fromstring(file) 
rdata = root.xpath('//tr[@class="tr_normal" and (.//img)]')
for data in rdata:
    data.getparent().remove(data)
for code in root.xpath('//tr[@class="tr_normal"]/td[position()=1]'):
    print code

你可以看到输出,(省略很多)

00320
00321
00322
00323
00325
00326
00327
00328

但是当你打开Hong Kong Exchanges and Clearing Limited时,会得到很多行,例如(省略很多):

06830 华众控股 2,000 #  
06838 盈利时 2,000 #  
06868 天福 1,000 #    
06880 豪特保健 2,000 #   
06883 新濠博亚娱乐 300 #   

我输了很多代码:06830 06838 06868 06880 06883(省略很多),代码落后于00329,所有代码都丢失了。

我没有得到所有代码,为什么?


import urllib
import lxml.html
equitydown="http://sc.hkex.com.hk/gb/www.hkex.com.hk/chi/market/sec_tradinfo/stockcode/eisdeqty_c.htm"   
file=urllib.urlopen(equitydown).read()   
root=lxml.html.document_fromstring(file) 
for code in root.xpath('//tr[@class="tr_normal" and not(.//img)]/td[position()=1]'):
    print code.text_content()

输出仍然出错,请尝试运行它看看会发生什么? 00328背后的代码无法获取,原因是什么?

2 个答案:

答案 0 :(得分:2)

分诊说明:

将url内容的副本保存到文件,以防它成为移动目标。

把它扔到W3C HTML validator ...结果是:

  

抱歉,我无法验证此文档,因为它在第18行   包含一个或多个字节,我无法解释为gb2312(in   换句话说,找到的字节不是指定的有效值   字符编码)。请检查文件的内容和   字符编码指示。

     

错误是:euc-cn“\ xFA”未映射到Unicode

除此之外:有谎言,该死的谎言以及声称iso-8859-1gb2312的编码声明。

尝试content.decode('gb2312',失败了。

 >>> guff = open('lxml_hke_raw.htm', 'rb').read()
 >>> len(guff) 715608
 >>> guff.decode('gb2312') Traceback (most recent call last):
 File "<stdin>", line 1, in <module> UnicodeDecodeError: 'gb2312' codec can't
 decode bytes in position 171039-171040: illegal multibyte sequence
 >>> pos=171039
 >>> guff[pos:pos+2]
 '\xfa\xe2'

围绕失败位置的探索产生了以下内容(手动缩进,删除或缩写了许多不相关的属性):

<tr class="tr_normal">
    <td class="verd_black12" width="18%">00329</td>
    <td class="verd_black12" width="42%">
        <a 
            href="http://sc.hkex.com.hk/etc/etc/etc"
            target="_parent"
        >
            <img
                src="http://sc.hkex.com.hk:80/fs?FAE2+5+13+004B96"
                alt="\xfa\xe2"  #### not a valid gb2312 sequence ####
            > #### also the "img" element is not terminated ####
        \xc1\xfa\xb9\xfa\xbc\xca
        </a>
    </td>
    <td class="verd_black12" width="19%">10,000</td>
    <td class="verd_black12" width="3%" align="center">#</td>
    <td class="verd_black12" width="3%">&nbsp;</td>
    <td class="verd_black12" width="3%">&nbsp;</td>
    <td class="verd_black12" width="3%">&nbsp;</td>
</tr>

这表明它停在包含00329的元素的原因。请注意文件后面还有另一个案例。

未完善:

ucontent = content.decode('gb2312', 'replace')
repchar = u'\uFFFD'
print ucontent.count(repchar) # 2
ucontent2 = ucontent.replace(repchar, '[NON-GB2312 SEQUENCE]')
content2 = ucontent2.encode('gb2312')

可以将其写入新文件或解析:

root = lxml.html.document_fromstring(content2) 
for el in root.iter('tr'):
    if el.get('class') != 'tr_normal': continue
    print all(ch.tag == 'td' for ch in el), [ch.text for ch in el]

缩写输出:

True ['00001', None, '1,000', '#', 'H', 'O', 'F']
True ['00002', None, '500', '#', 'H', 'O', 'F']
...
True ['00328', None, '2,000', '#', u'\xa0', u'\xa0', u'\xa0']
True ['00329', None, '10,000', '#', u'\xa0', u'\xa0', u'\xa0']
True ['00330', None, '100', '#', 'H', 'O', 'F']
...
True ['06880', None, '2,000', '#', u'\xa0', u'\xa0', u'\xa0']
True ['06883', None, '300', '#', u'\xa0', u'\xa0', u'\xa0']

另一个难题:

Python 2.7.2使用gb18030解码原始内容。但是,更改文件中的字符集不起作用(00329后没有输出)。同样尝试使用lxml的encoding arg覆盖编码具有相同的效果。

观察:违规行为\xfa\xe2gb18030解码为u'\ue331',该行为位于BMP Private Use Area中,后者考虑img元素,该元素提供了用于显示预期字符的GIF的网址。

答案 1 :(得分:0)

请注意,00329是第一个img,因此我认为remove是问题所在。也许它弄乱了xpath迭代器,首先尝试将其转换为list

或尝试:

root=lxml.html.document_fromstring(file)
for code in root.xpath('//tr[@class="tr_normal" and not(.//img)]/td[position()=1]'):
  print code