Вот мой html
:
<html>
<body>
<h2>Pizza</h2>
<p>This is some random paragraph without child tags.</p>
<p>Delicious homebaked pizza.<br><em></em>$8.99 pp</em></p>
<h2>Eggplant Parmesan</h2>
<p>Try the authentic <i>Italian flavor</i> of baked aubergine.<br><em>$6.99 pp</em></p>
<h2>Italian Ice Cream</h2>
<p>Our dessert specialty.<br><em>$3.99 pp</em></p>
</body>
</html>
Используя BeautifulSoup, я хочу получить текст, отображаемый для тегов h2
и p
, заменить их префиксной версией в дереве, а также распечатать их на экране. Для тегов h2
это прекрасно работает:
from bs4 import BeautifulSoup
with open("/var/www/html/Test/index.html", "r") as f:
soup = BeautifulSoup(f, "lxml")
f = open("/var/www/html/Test/I18N_index.html", "w+")
for h2 in soup.find_all('h2'):
i18n_string = "I18N_"+h2.string
h2.string.replace_with(i18n_string)
print(h2.string)
f.write(str(soup))
###Output:##############################################
# $ python ./test.py
# I18N_Pizza
# I18N_Eggplant Parmesan
# I18N_Italian Ice Cream
########################################################
В моем I18N_index.html все 3 строки отображаются правильно с префиксом «I18N _».
Однако мои теги p
содержат дочерние теги, и для них тип возвращаемого значения - «Нет». В результате конкатенация больше не работает:
for p in soup.find_all('p'):
i18n_string = "I18N_"+p.string
p.string.replace_with(i18n_string)
print(p.string)
f.write(str(soup))
###Output:##################################################
# $ python ./test.py
# I18N_Pizza
# I18N_Eggplant Parmesan
# I18N_Italian Ice Cream
# I18N_This is some random paragraph without child tags.
# Traceback (most recent call last):
# File "./test.py", line 15, in <module>
# i18n_string = "I18N_"+p.string
# TypeError: cannot concatenate 'str' and 'NoneType' objects
############################################################
Из этой темы Я узнал о функции join
. Это позволит мне выполнить конкатенацию и распечатать получившиеся строки на экране, но не заменять их в дереве супа:
for p in soup.find_all('p'):
joined = ''.join(p.strings)
i18n_string = "I18N_"+joined
#joined.replace_with(i18n_string)
print (i18n_string)
###Output with 'joined.replace_with(i18n_string)' DISABLED:###
# I18N_Pizza
# I18N_Eggplant Parmesan
# I18N_Italian Ice Cream
# I18N_This is some random paragraph without child tags.
# I18N_Delicious homebaked pizza.$8.99 pp
# I18N_Try the authentic Italian flavor of baked aubergine.$6.99 pp
# I18N_Our dessert specialty$3.99 pp
############################################################
###Output with 'joined.replace_with(i18n_string)' ENABLED:#####
# I18N_Pizza
# I18N_Eggplant Parmesan
# I18N_Italian Ice Cream
# Traceback (most recent call last):
# File "./test.py", line 41, in <module>
# joined.replace_with(i18n_string)
# AttributeError: 'unicode' object has no attribute 'replace_with'
############################################################
В этой теме упоминается другое решение, основанное на isinstance
, но я не смог заставить это работать.
Если я правильно понимаю, функция join объединяет строки, но возвращает объект 'unicode', а не объект string, и именно поэтому атрибут replace_with не работает. Как я могу обойти это? Любая помощь очень ценится.