我的代码:
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背后的代码无法获取,原因是什么?
答案 0 :(得分:2)
分诊说明:
将url内容的副本保存到文件,以防它成为移动目标。
把它扔到W3C HTML validator ...结果是:
抱歉,我无法验证此文档,因为它在第18行 包含一个或多个字节,我无法解释为gb2312(in 换句话说,找到的字节不是指定的有效值 字符编码)。请检查文件的内容和 字符编码指示。
错误是:euc-cn“\ xFA”未映射到Unicode
除此之外:有谎言,该死的谎言以及声称iso-8859-1
或gb2312
的编码声明。
尝试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%"> </td>
<td class="verd_black12" width="3%"> </td>
<td class="verd_black12" width="3%"> </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\xe2
由gb18030
解码为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