我想检索特定行上 html 标记内的文本
I want to retrieve the text inside a html tag on a specific line
我正在使用 html.parser 和 urllib.request。我不会使用任何非本地模块,但如果有必要,我愿意使用其他本地模块。
目前(部分)我的代码如下所示:
class MyHTMLParser(HTMLParser):
def handle_data(self, data):
if self.getpos()[0] == 167:
print(self.data)
我遇到的问题是 HTMLParser.getpos 总是 returns (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))
关于如何从 div 解析数据 - 您应该跟踪何时进入 div 和退出 div,并在这些点之间积累数据。使用库很容易做到这一点,并且更接近实际的解析,尽管我不打算讨论什么是愚蠢的,什么不是。
您的行号问题是因为您正在使用 str
读取 bytes
对象。在解释器中,你可以看到为什么这是一个问题:
>>> str(b"ab\nc")
"b'ab\nc'"
它实际上并没有将其转换为某种等效的字符串,而是转换为字符串表示形式。这意味着字节对象中的换行符按字面意思表示为 \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 s - 如果行号失败,你可以尝试保持在 handle_starttag
.
中遇到的 divs 的计数
我正在使用 html.parser 和 urllib.request。我不会使用任何非本地模块,但如果有必要,我愿意使用其他本地模块。 目前(部分)我的代码如下所示:
class MyHTMLParser(HTMLParser):
def handle_data(self, data):
if self.getpos()[0] == 167:
print(self.data)
我遇到的问题是 HTMLParser.getpos 总是 returns (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))
关于如何从 div 解析数据 - 您应该跟踪何时进入 div 和退出 div,并在这些点之间积累数据。使用库很容易做到这一点,并且更接近实际的解析,尽管我不打算讨论什么是愚蠢的,什么不是。
您的行号问题是因为您正在使用 str
读取 bytes
对象。在解释器中,你可以看到为什么这是一个问题:
>>> str(b"ab\nc")
"b'ab\nc'"
它实际上并没有将其转换为某种等效的字符串,而是转换为字符串表示形式。这意味着字节对象中的换行符按字面意思表示为 \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 s - 如果行号失败,你可以尝试保持在 handle_starttag
.