#python #html #beautifulsoup #html-parsing
Вопрос:
Я пытаюсь очистить данные в Интернете, некоторые из которых являются <li>
элементами. Я думаю, проблема в том, что у некоторых <ul>
родителей нет <li>
детей.
Пример HTML-кода таков — =
<div class="tab-pane predefined-carrier-DPDUK ">
<img src="https://assets.easypost.com/assets/images/carriers/dpd-logo.c4b107116e903920a5794e69e1990827.svg" alt="DPD UK">
<ul>
<li>Parcel</li>
<li>Pallet</li>
<li>ExpressPak</li>
<li>FreightParcel</li>
<li>Freight</li>
</ul>
</div>
<div class="tab-pane predefined-carrier-ChinaEMS ">
<img src="https://assets.easypost.com/assets/images/carriers/china-ems-logo-ca.0c938786bd8d8f141e8fa9337a3362a4.png" alt="EMS">
<p>No predefined packages for EMS.</p>
<ul></ul>
</div>
<div class="tab-pane predefined-carrier-Estafeta ">
<img src="https://assets.easypost.com/assets/images/carriers/estafeta-logo-ca.886242ba90c68a1d68f0e4e5a3a14419.png" alt="Estafeta">
<ul>
<li>ENVELOPE</li>
<li>PARCEL</li>
</ul>
</div>
Таким образом, некоторые из <ul>
них не вернут никаких результатов, т. е. не <li>
будут иметь детей. Я придумал пару «решений»
Этот должен повторяться через каждый <ul>
, но он всегда терпит неудачу во втором try
, поэтому не возвращает <li>
import requests
from bs4 import BeautifulSoup
r = requests.get("https://www.easypost.com/docs/api#parcels", headers={'User-agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0'})
c = r.content
soup= BeautifulSoup(c, "html.parser")
all = soup.find_all("div", {"class":lambda L: L and L.startswith("tab-pane predefined-carrier")})
for item in all:
print("n".join([img['alt'] for img in item.find_all('img', alt=True)]))
try:
print(item.find("p").text)
except:
print("HAS PACKAGES")
try:
for ul in all.find_all("ul"):
for litag in ultag.find_all("li"):
print(litag.text)
except:
print("has no list items")
print("")
Результирующий набор таков :
DPD UK
HAS PACKAGES
has no list items
EMS
No predefined packages for EMS.
has no list items
Estafeta
HAS PACKAGES
has no list items
Второе решение заключается в том, что оно возвращает <li>
, но я не могу найти способ, чтобы каждый <li>
из них печатался в новой строке:
import requests
from bs4 import BeautifulSoup
r = requests.get("https://www.easypost.com/docs/api#parcels", headers={'User-agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0'})
c = r.content
soup= BeautifulSoup(c, "html.parser")
all = soup.find_all("div", {"class":lambda L: L and L.startswith("tab-pane predefined-carrier")})
for item in all:
print("n".join([img['alt'] for img in item.find_all('img', alt=True)]))
try:
print(item.find("p").text)
except:
print("HAS PACKAGES")
try:
print(item.find_all("ul")[0].text)
except:
pass
print("")
Результирующий набор аналогичен этому:
DPD UK
HAS PACKAGES
ParcelPalletExpressPakFreightParcelFreight
EMS
No predefined packages for EMS.
Estafeta
HAS PACKAGES
ENVELOPEPARCEL
Надеюсь, кто-нибудь наставит меня на правильный путь, ТИА
Комментарии:
1. похоже, что первая ошибка в написании должна быть
for ul in item.find_all("ul"):
2. Спасибо за ответ, я попытался это сделать, но затем вернул данные следующим образом: > DPD >>Нет предопределенных пакетов для DPD. > Обратитесь в службу поддержки >> Свяжитесь с отделом продаж > > > >>> > DPD UK >>>>>ЕСТЬ ПАКЕТЫ > > > > > > > Обратитесь в службу поддержки > > > > > > > > Свяжитесь с отделом продаж >>>>>>>> >>>>>>>>>EMS >>>>>>>>>>Нет предопределенных пакетов для EMS. > Обратитесь в службу поддержки >> Свяжитесь с отделом продаж
Ответ №1:
Это может вам помочь. Я попытался извлечь <ul>
его и проверить, есть ли <li>
в нем теги. Только тогда я печатаю этот <li>
контент в новой строке.
import requests
from bs4 import BeautifulSoup
r = requests.get("https://www.easypost.com/docs/api#parcels", headers={'User-agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0'})
c = r.content
soup= BeautifulSoup(c, "html.parser")
div_tag = soup.find_all("div", {"class":lambda L: L and L.startswith("tab-pane predefined-carrier")})
for i in div_tag:
uls = i.find('ul')
# Checks if <ul> is empty. That is no <li> tags present
if uls.text != '':
# Gets all the <li> from <ul>
li_tags = uls.findAll('li')
# print the text of <li> one after other in new line
for item in li_tags:
print(item.text)
print('n')
Sample Output:
Parcel
Pallet
ExpressPak
FreightParcel
Freight
ENVELOPE
PARCEL
Parcel
Satchel
Комментарии:
1. Это здорово, спасибо! Он хорошо работает как автономный, но когда я вставляю его в свой
for item in all:
блок кода, я получаюAttributeError: 'int' object has no attribute 'text'
, что изменил первую строку в вашем коде, наfor i in item:
которую я получаю вышеуказанную ошибку. Если я изменю его на » для i во всех:, I get all the
<li>», указанный для всех элементов в переменной all