Beautifulsoup: получить диапазон дивов - PullRequest
1 голос
/ 01 февраля 2020

Я только что узнал о том, как обрабатывать веб-страницы в python с помощью BeautifulSoup. Есть список div, из которого я хочу получить те, которые находятся в определенном диапазоне c. Диапазон определяется двумя div, у которых есть h2 дочерний элемент. Как бы я это сделал? Спасибо за вашу поддержку!

РЕДАКТИРОВАТЬ: я добавил фактическое представление моего html кода ниже вместо предыдущей "упрощенной" версии, в которой отсутствовали теги. Новый код показывает root div с классом foo-bar-details. Вложено 9 div тегов. Два из которых имеют вложенный тег h2. Все эти 9 div теги содержат img элементов, глубоко вложенных в них. Что мне нужно, так это каждый img элемент из тех div, которые находятся между теми, которые содержат элемент h2. Ожидаемый результат при применении к приведенному ниже коду html будет следующим:

<img src="../../images/123456_thumb.jpg" alt="Image 123456" title="Image 123456">
<img src="../../images/67890_thumb.JPG" alt="Image 67890 " title="Image 67890">

Это код html:

<div class="foo-bar-details">
    <div class="padding-y-10 padding-x-40 gray-sand-bg" id="sec-feat-3-1">
        <div class="row">
            <div class="col-sm-6 info-panel">
                <div class="row">
                    <div class="col-sm-6 margin-bottom-10">
                        <p class="margin-0">
                            <strong>fsuhfsdf </strong> 
                        </p>
                    </div>
                    <div class="col-sm-6 margin-bottom-10">
                        <p class="margin-0">
                            <strong>Feat</strong><a href="../linkglossary0.pdf" class="link" title="test"><span class="icon-help"></span></a> 
                        </p>
                    </div>
                </div>
            </div>
            <div class="col-sm-6 foo-images">
                <div class="row">
                    <a href="image-39826.html"><img src="../../images/39826_thumb.JPG" alt="Image 39826" title="Image 39826 "></a> 
                    <div class="img-description">
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="padding-y-10 padding-x-40 gray-sand-bg" id="sec-feat-3-1">
        <div class="row">
            <div class="col-sm-6 info-panel">
                <div class="row">
                    <div class="col-sm-6 margin-bottom-10">
                        <p class="margin-0">
                            <strong>JHFDFD </strong> 
                        </p>
                    </div>
                    <div class="col-sm-6 margin-bottom-10">
                        <p class="margin-0">
                            <strong>Feat</strong><a href="../linkglossary2.pdf" class="link" title="test"><span class="icon-help"></span></a> 
                        </p>
                    </div>
                </div>
            </div>
            <div class="col-sm-6 foo-images">
                <div class="row">
                    <a href="image-223234.html"><img src="../../images/223234_thumb.JPG" alt="Image 223234" title="Image 223234 "></a> 
                    <div class="img-description">
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="padding-y-10 padding-x-40 gray-sand-bg" id="sec-feat-3-1">
        <div class="row">
            <div class="col-sm-6 info-panel">
                <div class="row">
                    <div class="col-sm-6 margin-bottom-10">
                        <p class="margin-0">
                            <strong>sdfsdf </strong> 
                        </p>
                    </div>
                    <div class="col-sm-6 margin-bottom-10">
                        <p class="margin-0">
                            <strong>Feat</strong><a href="../linkglossary1.pdf" class="link" title="test"><span class="icon-help"></span></a> 
                        </p>
                    </div>
                </div>
            </div>
            <div class="col-sm-6 foo-images">
                <div class="row">
                    <a href="image-223823.html"><img src="../../images/223823_thumb.JPG" alt="Image 223823" title="Image 223823 "></a> 
                    <div class="img-description">
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="element-header mystic-bg padding-y-10 padding-x-20" id="elem-4">
        <h2 class="h3 margin-bottom-5">
            Foo 
        </h2>
        <ul class="list-inline margin-0">
            <li> <a href="#foo-feat-4-1">Foo feature</a> </li>
            ... 
        </ul>
    </div>
    <div id="info-panel-header" class="padding-y-10 padding-x-40">
        <div class="row">
            <div class="col-se-6 element-info">
                <div class="col-se-12">
                    <div class="row">
                    </div>
                </div>
            </div>
            <div class="col-sm-6 foo-images">
                <div class="row">
                    <a href="image-123456.html"><img src="../../images/123456_thumb.jpg" alt="Image 123456" title="Image 123456"></a> 
                    <div class="img-description">
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="padding-y-10 padding-x-40 gray-wild-sand-bg" id="sec-feat-4-1">
        <div class="row">
            <div class="col-sm-6 info-panel">
                <div class="row">
                    <div class="col-sm-6 margin-bottom-10">
                        <p class="margin-0">
                            <strong>Foo strin: </strong> 
                        </p>
                    </div>
                    <div class="col-sm-6 margin-bottom-10">
                        <p class="margin-0">
                            <strong>Barbar</strong><a href="../test.pdf" class="link" title="test"><span class="icon-help"></span></a> 
                        </p>
                    </div>
                </div>
                <div class="row">
                    <div class="col-sm-6 margin-bottom-10">
                        <p class="margin-0">
                            <strong>Mine: </strong> 
                        </p>
                    </div>
                    <div class="col-sm-6 margin-bottom-10">
                        <p class="margin-0">
                            TEST<a href="../link.pdf" class="my-link" title="title"><span class="icon-help"></span></a> 
                        </p>
                    </div>
                </div>
            </div>
            <div class="col-sm-6 foo-images">
                <div class="row">
                    <a href="image-67890.html"><img src="../../images/67890_thumb.JPG" alt="Image 67890 " title="Image 67890"></a> 
                    <div class="img-description">
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="element-header mystic-bg padding-y-10 padding-x-20" id="elem-5">
        <h2 class="h3 margin-bottom-5">
            Bar 
        </h2>
        <ul class="list-inline margin-0">
            <li> <a href="#foo-feat-5-1">Bar feature</a> </li>
            ... 
        </ul>
    </div>
    <div class="padding-y-10 padding-x-40 gray-sand-bg" id="sec-feat-3-1">
        <div class="row">
            <div class="col-sm-6 info-panel">
                <div class="row">
                    <div class="col-sm-6 margin-bottom-10">
                        <p class="margin-0">
                            <strong>fsuhfsdf </strong> 
                        </p>
                    </div>
                    <div class="col-sm-6 margin-bottom-10">
                        <p class="margin-0">
                            <strong>Feat</strong><a href="../linkglossary0.pdf" class="link" title="test"><span class="icon-help"></span></a> 
                        </p>
                    </div>
                </div>
            </div>
            <div class="col-sm-6 foo-images">
                <div class="row">
                    <a href="image-39826.html"><img src="../../images/39826_thumb.JPG" alt="Image 39826" title="Image 39826 "></a> 
                    <div class="img-description">
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="padding-y-10 padding-x-40 gray-sand-bg" id="sec-feat-3-1">
        <div class="row">
            <div class="col-sm-6 info-panel">
                <div class="row">
                    <div class="col-sm-6 margin-bottom-10">
                        <p class="margin-0">
                            <strong>fsuhfsdf </strong> 
                        </p>
                    </div>
                    <div class="col-sm-6 margin-bottom-10">
                        <p class="margin-0">
                            <strong>Feat</strong><a href="../linkglossary0.pdf" class="link" title="test"><span class="icon-help"></span></a> 
                        </p>
                    </div>
                </div>
            </div>
            <div class="col-sm-6 foo-images">
                <div class="row">
                    <a href="image-209876.html"><img src="../../images/209876_thumb.JPG" alt="Image 209876" title="Image 209876 "></a> 
                    <div class="img-description">
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

Ответы [ 3 ]

2 голосов
/ 01 февраля 2020

Вот решение, включающее lxml.html:

Мы извлекаем все div s между first и last div s, которые содержат h2 тег:

import lxml.html


# HTML file saved as "file.html"
file_name = "file.html"
with open(file_name, 'r') as f:
    tree = lxml.html.fromstring(f.read())

# all_div = tree.findall('div')
all_div = tree.find_class('foo-bar-details')[0].findall('div')
start, stop = None, None
for k, div in enumerate(all_div):
    if div.findall('h2') and start is None:
        print("Range starts at %d" % k)
        start = k
        continue
    if div.findall('h2') and start is not None:
        print("Range stops at %d" % k)
        stop = k + 1  # add one as range stops at k - 1
        continue

# div_list = all_div[start:stop]
img_list = [_.xpath('.//img') for _ in all_div[start:stop]]
print(img_list)
# [[], [<Element img at 0x20b58d73f40>], [<Element img at 0x20b58d73f90>], []]

# Or
img_list = [_.xpath('.//img/@src') for _ in all_div[start:stop]]
print(img_list)
# [[], ['../../images/123456_thumb.jpg'], ['../../images/67890_thumb.JPG'], []]
0 голосов
/ 02 февраля 2020

Если я правильно вас понимаю, вы хотите найти <img> теги и соответствующие <h2>, к которым относятся изображения.

Этот пример (переменная txt содержит фрагмент HTML из вашего вопрос):

from bs4 import BeautifulSoup

soup = BeautifulSoup(txt, 'html.parser')

out = {}
for img in soup.select('div:has(h2) ~ div img'):
    out.setdefault(img.find_previous('h2').get_text(strip=True), []).append(img['src'])

from pprint import pprint
pprint(out)

Отпечатки:

{'Bar': ['../../images/39826_thumb.JPG', '../../images/209876_thumb.JPG'],
 'Foo': ['../../images/123456_thumb.jpg', '../../images/67890_thumb.JPG']}
0 голосов
/ 02 февраля 2020

Другое решение, включающее SimplifiedDo c:

from simplified_scrapy.simplified_doc import SimplifiedDoc
html ='''
<div class="foo-bar-details">
    <div class="element-header mystic-bg padding-y-10 padding-x-20" id="elem-4">
        <h2 class="h3 margin-bottom-5">
            Foo 
        </h2>
        <ul class="list-inline margin-0">
            <li> <a href="#foo-feat-4-1">Foo feature</a> </li>
            ... 
        </ul>
    </div>
    <div id="info-panel-header" class="padding-y-10 padding-x-40">Test 1</div>
    <div class="padding-y-10 padding-x-40 gray-wild-sand-bg" id="foo-feat-4-1">Test 2</div>
    <div class="padding-y-10 padding-x-40 " id="foo-feat-4-2">Test 3</div>
    <div class="padding-y-10 padding-x-40 gray-wild-sand-bg" id="foo-feat-4-3">Test 4</div>
    <div class="element-header mystic-bg padding-y-10 padding-x-20" id="elem-5">
        <h2 class="h3 margin-bottom-5">
            Bar 
        </h2>
        <ul class="list-inline margin-0">
            <li> <a href="#foo-feat-5-1">Bar feature</a> </li>
            ... 
        </ul>
    </div>
</div>
'''
doc = SimplifiedDoc(html)
divs = doc.select('div.foo-bar-details').divs.contains('<h2')
print ([div.id for div in divs])
divs = doc.select('div.foo-bar-details').divs.notContains('<h2')
print ([div.id for div in divs])

Результат:

['elem-4', 'elem-5']
['info-panel-header', 'foo-feat-4-1', 'foo-feat-4-2', 'foo-feat-4-3']

Simplifieddo c библиотека не полагается на стороннюю библиотеку, которая легче и быстрее, идеально подходит для начинающих. Вот еще примеры здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...