следующие братья и сестры селен python с условиями - PullRequest
2 голосов
/ 02 августа 2020

Я пытаюсь собрать следующих братьев и сестер до определенного брата, но я все еще не могу понять, как это сделать, я пытался найти до и после родного брата с именем класса, но получил неверные результаты

Мой html:

<div class="MainClass">

        <div class="InfoClass">
            <div class="left-wrap">
              <span class="date">2 August 2020</span>
            </div>
        </div>

        <div class="DataClass">
            <em class="Code">
                <span>1</span>
            </em>
        </div>
        
        <div class="DataClass">
            <em class="Code">
                <span>2</span>
            </em>
        </div>
        
        <div class="DataClass">
            <em class="Code">
                <span>3</span>
            </em>
        </div>
        
        <div class="DataClass">
            <em class="Code">
                <span>4</span>
            </em>
        </div>
    
        <div class="InfoClass">
            <div class="left-wrap">
              <span class="date">15 August 2020</span>
            </div>
        </div>

        <div class="DataClass">
            <em class="Code">
                <span>5</span>
            </em>
        </div>

        <div class="DataClass">
            <em class="Code">
                <span>6</span>
            </em>
        </div>
</div>

Вот мой Python Код:

mainClass = driver.find_elements_by_xpath("//div[@class='MainClass']//following-sibling::div[@class='InfoClass']")

        for mc in mainClass:
            kDate = header.find_element_by_xpath(".//span[@class='date']").text
            print(kDate)
            
            datarows = header.find_elements_by_xpath("following-sibling::div[@class='DataClass' and preceding-sibling::div[@class='DataClass']]")
            
            for datarow in datarows:
                mc = datarow.find_element_by_xpath(".//em[@class='Code']").text
                print("Code : "+mc)

Результаты, которые я получил:

2 August 2020
2
3
4
5
6
15 August 2020 
5
6

То, что я хочу в результате получается класс "Код", сгруппированный по датам:

2 August 2020
1
2
3
4
15 August 2020 
5
6

Ответы [ 4 ]

2 голосов
/ 02 августа 2020

Что касается ожидаемого результата, почему бы вам не извлечь текст из всех элементов span, поскольку они уже в порядке? Например, с L XML:

data=tree.xpath("//span/text()")
print(*data, sep="\n")

Вывод:

2 August 2020
1
2
3
4
15 August 2020
5
6

Если вы действительно хотите использовать циклы и создать словарь, вот предложение. Сначала данные:

data = """<div class="MainClass">

        <div class="InfoClass">
            <div class="left-wrap">
              <span class="date">2 August 2020</span>
            </div>
        </div>

        <div class="DataClass">
            <em class="Code">
                <span>1</span>
            </em>
        </div>
        
        <div class="DataClass">
            <em class="Code">
                <span>2</span>
            </em>
        </div>
        
        <div class="DataClass">
            <em class="Code">
                <span>3</span>
            </em>
        </div>
        
        <div class="DataClass">
            <em class="Code">
                <span>4</span>
            </em>
        </div>
    
        <div class="InfoClass">
            <div class="left-wrap">
              <span class="date">15 August 2020</span>
            </div>
        </div>

        <div class="DataClass">
            <em class="Code">
                <span>5</span>
            </em>
        </div>

        <div class="DataClass">
            <em class="Code">
                <span>6</span>
            </em>
        </div>
</div>"""

Затем код:

import lxml.html
tree = lxml.html.fromstring(data)

dates = [el.text for el in tree.xpath("//span[@class='date']")]
print(dates)

dc=[]
for els in dates:
    lists=[el.text for el in tree.xpath("//div[span[text()='"+els+"']]/../following-sibling::div[@class='DataClass']//span[preceding::span[@class='date'][1][.='"+els+"']]")]
    dc.append(lists)

print(dc)

dictionary = dict(zip(dates,dc))
print(dictionary)

Комментарии:

Сначала вы извлекаете даты в список. Затем все полагаются на следующий XPath (тот, который вы искали?), Чтобы получить соответствующие классы данных:

//div[span[text()='"+els+"']]/../following-sibling::div[@class='DataClass']//span[preceding::span[@class='date'][1][.='"+els+"']]

+els+ - даты, полученные ранее.

Наконец, вы создаете словарь. Этот код написан для LXML. Просто замените tree.xpath на Selenium equialent (driver.find_elements_by_xpath), чтобы он заработал.

Вывод (даты, классы данных, словарь):

['2 August 2020', '15 August 2020']
[['1', '2', '3', '4'], ['5', '6']]
{'2 August 2020': ['1', '2', '3', '4'], '15 August 2020': ['5', '6']}

РЕДАКТИРОВАТЬ: Если вам нужно распечатайте словарь, вы можете использовать:

for keys,values in dictionary.items():
    print(keys)
    print(*values,sep='\n')

Вывод по запросу:

2 August 2020
1
2
3
4
15 August 2020
5
6
1 голос
/ 02 августа 2020

Вы можете использовать тот же простой код, что и в предыдущем вопросе, но используя list для сбора правильных значений, если .Code не является уникальным. Он также работает, если 2 августа 2020 и 15 августа 2020 будут одинаковыми code

codes = list()
for e in driver.find_elements_by_class_name('Code'):
    code = e.text
    date = e.find_element_by_xpath("(./preceding::span[@class='date'])[last()]").text
    codes.append({"date": date, "code": code})

for c in codes:
    print(f'date: {c["date"]}, code: {c["code"]}')

Результат:

date: 2 August 2020, code: 1
date: 2 August 2020, code: 2
date: 2 August 2020, code: 3
date: 2 August 2020, code: 4
date: 15 August 2020, code: 5
date: 15 August 2020, code: 6

Если вам нужен dict с датой в качестве ключа и коды в качестве значений:

codes = dict()
for e in driver.find_elements_by_class_name('Code'):
    code = e.text
    date = e.find_element_by_xpath("(./preceding::span[@class='date'])[last()]").text
    if date in codes:
        codes[date].append(code)
    else:
        codes.update({date: [code]})

for k, v in codes.items():
    print(f'{k} : {v}')

С выводом:

2 August 2020 : ['1', '2', '3', '4']
15 August 2020 : ['5', '6']
1 голос
/ 02 августа 2020

Я нашел способ отображать нужный вам текст.

mainClassText = driver.find_element_by_xpath("//div[@class='MainClass']").text
print(mainClassText)

, если хотите, вы также можете превратить это в список.

mainClassTextList = mainClassText.split("\n")
for ele in mainClassTextList:
    print(ele)

Он будет отображаться в обоих случаях:

2 August 2020
1
2
3
4
15 August 2020
5
6
1 голос
/ 02 августа 2020

Поскольку все блоки div, содержащие дату и данные, находятся на одном уровне в div MainClass. Мы можем получить желаемый результат, используя один общий c xpaths для всех диапазонов, содержащих дату и данные.

 driver = webdriver.Chrome()
driver.get("https://bilalzamel.htmlsave.net/")

mainClass = driver.find_elements_by_xpath("//div[@class='MainClass']//span")
for mc in mainClass:
    kDate = mc.text
    print(kDate)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...