我正在使用漂亮的汤解析多个HTML页面。大多数情况下工作得很好。我想包括文本以及链接的URL。
当前语法为:
soup = MyBeautifulSoup(''.join(body), 'html.parser')
body_text = self.remove_newlines(soup.get_text())
我在网上找到了一个覆盖_all_strings函数的建议:
class MyBeautifulSoup(BeautifulSoup):
def _all_strings(self, strip=False, types=(NavigableString, CData)):
for descendant in self.descendants:
# return "a" string representation if we encounter it
if isinstance(descendant, Tag) and descendant.name == 'a':
yield str('<{}> '.format(descendant.get('href', '')))
# skip an inner text node inside "a"
if isinstance(descendant, NavigableString) and descendant.parent.name == 'a':
continue
# default behavior
if (
(types is None and not isinstance(descendant, NavigableString))
or
(types is not None and type(descendant) not in types)):
continue
if strip:
descendant = descendant.strip()
if len(descendant) == 0:
continue
yield descendant
但是,这会产生运行时错误:
in _all_strings
(types is not None and type(descendant) not in types)):
TypeError: argument of type 'object' is not iterable
是否有方法绕过此错误?
谢谢!
1条答案
按热度按时间u5i3ibmn1#
and type(descendant) not in types
更改为**and not isinstance(descendant, types)
***使用您建议的更改,我得到了相同的错误
但是更改后的错误应该是不同的-错误追溯中提到的行(*
types is not None and type(descendant) not in types)
*)正是我建议更改的行...无论如何,我对此进行了更深入的研究,我建议的更改只是引起了另一种错误;主要问题是由
get_text
使用types=default
调用_all_strings
引起的;default
在这个新子类中似乎没有任何意义(这就是为什么您会看到 *<class 'object'> ....
*)。你可以在函数的开头检查
types
,确保它是一个类或者是一个元组:然而,不使用
default
作为types
也意味着JavaScript和CSS不再被排除在外。所以[个人]我更愿意用两个全新的方法编写新类,并使用它们:这还允许您指定源URL [如
soup.get_text(srcUrl='https://example.com/')
],以便relative paths可以转换为完整链接,并且可以忽略JavaScript链接(如果您不介意忽略这些链接,请删除条件中的 *or href.startswith('javascript:')
* 部分)。顺便说一句,我已经注解掉了
a
标记[或者,更确切地说,aRef
中包含的任何标记]中省略字符串的部分,但是您可以根据需要取消注解它们;但是,如果取消注解 *skipTags += list(aRef.keys())
* 行,则 *if descendant.parent.name in aRef: continue
* 行将变得多余。