我想检索特定行上的html标记内的文本

时间:2017-09-25 12:07:21

标签: python urllib

我正在使用html.parser和urllib.request。我不打算使用任何非原生模块,但如果有必要,我愿意使用其他原生模块。 目前(部分)我的代码如下所示:

class MyHTMLParser(HTMLParser):
    def handle_data(self, data):
        if self.getpos()[0] == 167:
            print(self.data)

我遇到的问题是HTMLParser.getpos总是返回一个(1,x)的元组,其中x是一个每次增加的数字,但看起来是随机的),如下所示:

(1, 21)
(1, 41)
(1, 51)
(1, 77)
(1, 134)
(1, 206)
(1, 406)
(1, 509)
(1, 553)
(1, 627)
(1, 680)
(1, 784)
(1, 1143)
(1, 1368)

我觉得整个html.parser模块都是以非常愚蠢的方式编写的,本来可以想得更好。显然它有效,但这是违反直觉的。
完整代码:

from urllib.request import *
from html.parser import HTMLParser
class MyHTMLParser(HTMLParser):
    def handle_data(self, data):
      print(self.getpos())
      if self.getpos()[0] == 167:
        print(data)
parser = MyHTMLParser()
html = urlopen("https://www.azlyrics.com/lyrics/aha/takeonme.html").read()
parser.feed(str(html))

1 个答案:

答案 0 :(得分:0)

关于如何从div中解析数据 - 您应该在输入div并退出div时进行跟踪,并在这些点之间累积数据。这对于库来说很容易,并且与实际的解析相比更接近,尽管我不打算讨论什么是愚蠢的,什么不是。

您的行号问题是因为您使用str来阅读bytes个对象。在解释器中,您可以看到为什么这是一个问题:

>>> str(b"ab\nc")
"b'ab\\nc'"

它实际上并没有将它转换为一种等效字符串,而是转换为字符串表示形式。这意味着bytes对象中的换行符字面上表示为\n,因此您没有得到任何行号。要解码字节对象,您应该使用.decode。以下代码应该有效:

import sys

from html.parser import HTMLParser
from urllib.request import urlopen

class LyricParser(HTMLParser):
    def get_lyrics(self, html):
        self.read_lyrics = False
        self.lyrics = []
        self.feed(html)
        return "".join(self.lyrics)

    def handle_starttag(self, tag, attrs):
        if tag == "div" and self.getpos()[0] == 167:
            self.read_lyrics = True

    def handle_data(self, data):
        if self.read_lyrics:
            self.lyrics.append(data)

    def handle_endtag(self, tag):
        if tag == "div":
            self.read_lyrics = False

parser = LyricParser()
page = urlopen("https://www.azlyrics.com/lyrics/aha/takeonme.html")
lyrics = parser.get_lyrics(page.read().decode('utf-8'))
print(lyrics)

对我而言,这正确输出如下内容:

Talking away
I don't know what I'm to say
I'll say it anyway
Today's another day to find you
...

看过这个页面我必须得出结论你是对的 - 它的结构很棒,识别歌词div的唯一方法是按行号,或者前一个div的数量 - 如果行号失败,你可以尝试在handle_starttag中保持div的计数。