#python #python-3.x #web-scraping #beautifulsoup
#python #python-3.x #веб-очистка #beautifulsoup
Вопрос:
Я пытаюсь извлечь информацию с веб-страницы, используя beautifulsoup и python. Я хочу извлечь информацию прямо под определенным тегом. Чтобы узнать, правильный ли это тег, я хотел бы сравнить его текст, а затем извлечь текст в следующем непосредственном теге.
Скажем, например, если следующее является частью HTML-страницы-источника,
<div class="row">
::before
<div class="four columns">
<p class="title">Procurement type</p>
<p class="data strong">Services</p>
</div>
<div class="four columns">
<p class="title">Reference</p>
<p class="data strong">ANAJSKJD23423-Commission</p>
</div>
<div class="four columns">
<p class="title">Funding Agency</p>
<p class="data strong">Health Commission</p>
</div>
::after
</div>
<div class="row">
::before
::after
</div>
<hr>
<div class="row">
::before
<div class="twelve columns">
<p class="title">Countries</p>
<p class="data strong">
<span class>Belgium</span>
", "
<span class>France</span>
", "
<span class>Luxembourg</span>
</p>
<p></p>
</div>
::after
</div>
Я хочу проверить, имеет ли значение <p class="title">
text, так как Procurement type
тогда я хочу распечатать сервисы
Аналогично, если <p class="title">
имеет текстовое значение as Reference
, то я хочу распечатать ANAJSKJD23423-Commission, и если <p class="title">
имеет значение as Countries
, то распечатайте все страны, то есть Бельгию, Францию, Люксембург.
Я знаю, что могу извлечь все тексты <p class="data strong">
и добавить их в список, а затем извлечь все значения с помощью индексации. Но дело в том, что порядок их появления <p class="title>
не fixed….at в некоторых местах страны могут быть упомянуты перед типом закупок. Поэтому я хочу выполнить проверку текстовых значений, а затем извлечь текстовое значение следующего непосредственного тега. Я все еще новичок в BeautifulSoup, поэтому любая помощь приветствуется. Спасибо
Ответ №1:
Вы можете сделать это многими способами.Вот так.
from bs4 import BeautifulSoup
htmldata='''<div class="row">
::before
<div class="four columns">
<p class="title">Procurement type</p>
<p class="data strong">Services</p>
</div>
<div class="four columns">
<p class="title">Reference</p>
<p class="data strong">ANAJSKJD23423-Commission</p>
</div>
<div class="four columns">
<p class="title">Funding Agency</p>
<p class="data strong">Health Commission</p>
</div>
::after
</div>
<div class="row">
::before
::after
</div>
<hr>
<div class="row">
::before
<div class="twelve columns">
<p class="title">Countries</p>
<p class="data strong">
<span class>Belgium</span>
", "
<span class>France</span>
", "
<span class>Luxembourg</span>
</p>
<p></p>
</div>
::after
</div>'''
soup=BeautifulSoup(htmldata,'html.parser')
items=soup.find_all('p', class_='title')
for item in items:
if ('Procurement type' in item.text) or ('Reference' in item.text):
print(item.findNext('p').text)
Ответ №2:
Вы также можете использовать :contains
псевдокласс с bs4 4.7.1. Хотя я передал его в виде списка, вы можете выделить каждое условие
from bs4 import BeautifulSoup as bs
import re
html = 'yourHTML'
soup = bs(html, 'lxml')
items=[re.sub(r'ns ','', item.text.strip()) for item in soup.select('p.title:contains("Procurement type") p, p.title:contains(Reference) p, p.title:contains(Countries) p')]
print(items)
Вывод:
Ответ №3:
Вы можете добавить аргумент для проверки наличия определенного текста при использовании .find()
или .find_all()
затем использовать .next_sibling
или findNext()
для захвата следующих тегов с содержимым
Ie:
soup.find('p', {'class':'title'}, text = 'Procurement type')
Учитывая:
html = '''<div class="row">
::before
<div class="four columns">
<p class="title">Procurement type</p>
<p class="data strong">Services</p>
</div>
<div class="four columns">
<p class="title">Reference</p>
<p class="data strong">ANAJSKJD23423-Commission</p>
</div>
<div class="four columns">
<p class="title">Funding Agency</p>
<p class="data strong">Health Commission</p>
</div>
::after
</div>
<div class="row">
::before
::after
</div>
<hr>
<div class="row">
::before
<div class="twelve columns">
<p class="title">Countries</p>
<p class="data strong">
<span class>Belgium</span>
", "
<span class>France</span>
", "
<span class>Luxembourg</span>
</p>
<p></p>
</div>
::after
</div>'''
вы могли бы сделать что-то вроде:
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'html.parser')
alpha = soup.find('p', {'class':'title'}, text = 'Procurement type')
for sibling in alpha.next_siblings:
try:
print (sibling.text)
except:
continue
Вывод:
Services
или
ref = soup.find('p', {'class':'title'}, text = 'Reference')
for sibling in ref.next_siblings:
try:
print (sibling.text)
except:
continue
Вывод:
ANAJSKJD23423-Commission
или
countries = soup.find('p', {'class':'title'}, text = 'Countries')
names = countries.findNext('p', {'class':'data strong'}).text.replace('", "','').strip().split('n')
names = [name.strip() for name in names if not name.isspace()]
for country in names:
print (country)
Вывод:
Belgium
France
Luxembourg