处理lxml中的编码时出错

时间:2013-10-01 17:05:52

标签: python character-encoding lxml

我有一个非常简单的任务,可以从网页http://subscribe.ru/catalog?rss输出锚点内的所有文本。这是我的代码:

# encoding: utf-8
from lxml import etree

import urllib2
from lxml.html import document_fromstring

data = urllib2.urlopen('http://subscribe.ru/catalog?rss')
S=data.read()

oHTML = document_fromstring(S)
loLinks = oHTML.xpath("//a")

for oLink in loLinks:
    print etree.tostring(oLink)
    sLink = oLink.xpath('string()')[0]

输出如下:

C:\Development\Python27\python.exe "D:/Topic Modeling/Playground/delme3.py"
Traceback (most recent call last):
  File "D:/Topic Modeling/Playground/delme3.py", line 15, in <module>
<a onclick="rgNav('js_tab_auth');return false;" href="">&#247;&#200;&#207;&#196; &#206;&#193; &#211;&#193;&#202;&#212;</a>
    sLink = oLink.xpath('string()')[0]
<a onclick="rgNav('js_tab_reg');return false;" href="">&#242;&#197;&#199;&#201;&#211;&#212;&#210;&#193;&#195;&#201;&#209; </a>
IndexError: string index out of range
<a class="forgot_pass" href="/member/totalrecall">&#250;&#193;&#194;&#217;&#204;&#201; &#208;&#193;&#210;&#207;&#204;&#216;?</a>

<a class="button_blue_2" id="js_loginFormBut" href="#">&#247;&#207;&#202;&#212;&#201;</a>

<a class="font_gray link_txd" href="/faq/vereinbarung.html">&#213;&#211;&#204;&#207;&#215;&#201;&#209; &#208;&#207;&#204;&#216;&#218;&#207;&#215;&#193;&#206;&#201;&#209; &#211;&#197;&#210;&#215;&#201;&#211;&#207;&#205; Subscribe.ru</a>
<a class="button_blue_2" id="js_regFormBut" href="#">&#238;&#193;&#222;&#193;&#212;&#216; &#210;&#197;&#199;&#201;&#211;&#212;&#210;&#193;&#195;&#201;&#192;</a>

<a class="rg_btn_soc rg_bs_01 js_tap_panel_selector" action="auth_email" href="#"><span><i/>Email</span></a>

<a class="rg_btn_soc rg_bs_01 js_tap_panel_selector" action="auth_openid" href="#"><span><i/>OpenID</span></a>

<a class="rg_btn_soc rg_bs_02 js_tap_panel_selector" action="auth_vkontakte" href="#"><span><i/>&#247;&#203;&#207;&#206;&#212;&#193;&#203;&#212;&#197;</span></a>

<a class="rg_btn_soc rg_bs_02 js_tap_panel_selector" action="auth_mailru" href="#"><span><i/>Mail.Ru</span></a>
 {#/if}
 {#if $P.login_register_tab == 2}

<a class="rg_btn_soc rg_bs_01 js_tap_panel_selector" action="reg_email" href="#"><span><i/>Email</span></a>

<a class="rg_btn_soc rg_bs_01 js_tap_panel_selector" action="reg_openid" href="#"><span><i/>OpenID</span></a>

<a class="rg_btn_soc rg_bs_02 js_tap_panel_selector" action="reg_vkontakte" href="#"><span><i/>&#247;&#203;&#207;&#206;&#212;&#193;&#203;&#212;&#197;</span></a>

<a class="rg_btn_soc rg_bs_02 js_tap_panel_selector" action="reg_mailru" href="#"><span><i/>Mail.Ru</span></a>
 {#/if}

<a href="" onclick="return false;">&#242;&#197;&#199;&#201;&#211;&#212;&#210;&#193;&#195;&#201;&#209;</a>
<a href="" onclick="ajax_recall_code();return false">&#247;&#217;&#211;&#204;&#193;&#212;&#216; &#197;&#221;&#197; &#210;&#193;&#218;</a>
<a href="#" class="button_blue_2" id="js_confirmFormBut">&#231;&#207;&#212;&#207;&#215;&#207;</a>

<a class="green" href="http://subs.link.subscribe.ru/422433"><strong>&#242;&#197;&#218;&#213;&#204;&#216;&#212;&#193;&#212;&#217; &#207;&#206;&#204;&#193;&#202;&#206; &#207;&#208;&#210;&#207;&#211;&#193;: "&#243;&#208;&#193;&#205; &#201;&#204;&#201; &#206;&#197; &#211;&#208;&#193;&#205;? &#247;&#207;&#212; &#215; &#222;&#197;&#205; &#215;&#207;&#208;&#210;&#207;&#211;!"</strong></a> 


<a title="Subscribe.Ru" href="/" class="logo"><dfn class="logokanal"/></a>


Process finished with exit code 1

因此提取了链接,但由于某种原因无法提取链接文本。输出暗示编码存在一些问题(引用内容仅由人类可读文本组成)。我怎么能解决这个问题?

尝试使用utf-8进行解码也不起作用:

# encoding: utf-8
from lxml import etree
import urllib2
import chardet
from lxml import html

data = urllib2.urlopen('http://subscribe.ru/catalog?rss')
S=data.read()

encoding = chardet.detect(S)['encoding']
print encoding
if encoding != 'utf-8':
    S = S.decode(encoding,'replace').encode('utf-8')

oHTML = html.fromstring(S)
loLinks = oHTML.xpath("//a")

for oLink in loLinks:
    print etree.tostring(oLink)
    sLink = oLink.xpath('string()')[0]

失败并出现同样的错误。

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

你得到IndexError(问题与编码无关)。

如果<a>元素为空(并且其中一些元素位于该网页上),则代码中的oLink.xpath('string()')将返回一个空列表。然后oLink.xpath('string()')[0]会为您提供IndexError

以下代码将为您提供您想要的(我认为)。 HTML页面以KOI8-R编码。请注意,您可以使用lxml直接从URL解析。

from lxml import html

URL = 'http://subscribe.ru/catalog?rss'

parser = html.HTMLParser(encoding="KOI8-R")
content = html.parse(URL, parser)
anchors = content.xpath("//a")

for anchor in anchors:
    text = anchor.text
    if text:  # if the anchor is not empty
        print text.encode("utf-8")

此程序的输出以:

开头
Вход на сайт
Регистрация 
Забыли пароль?
Войти
условия пользования сервисом Subscribe.ru
Начать регистрацию
Регистрация
Выслать еще раз
Готово

并以:

结束
Спорт
Прогноз погоды
Новости и СМИ
Страны и Регионы
Общество
Дом и семья
Все разделы
ЗАО «Интернет-Проекты»