Соскоб с помощью Selenium и Xpath - PullRequest
0 голосов
/ 24 апреля 2020

Я новичок в Xpath. Я пытаюсь очистить сайт, чтобы получить название и ценность каждого элемента. В моем сценарии python selenium я локально извлек основную часть веб-страницы в html_content следующим образом.

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.chrome.options import Options
from selenium.common.exceptions import NoSuchElementException
dirinstall="C:\\Program Files (x86)\\www\mm\\"
chrome_driver = dirinstall+"\\Webdriver\\chromedriver.exe"
options = Options()
driver = webdriver.Chrome(chrome_driver, options=options)
html_content = """
<html class="ng-scope">
<head data-meta-tags="">
    <title> Stock NYSE </title>
    <ui-layout class="ng-isolate-scope">
        <div data-ng-include="" src="layoutCtrl.template" class="ng-scope">
            <app-root class="ng-scope" _nghost-rqp-c0="" ng-version="8.2.14"></app-root>
            <div ng-class="{'demo-mode': $root.session.user.portfolio.account.type === 'Demo' }" class="ng-scope">
                <div ng-view="" ng-class="layoutCtrl.isBannerShown ? 'banner-shown' : ''" class="main-app-view ng-scope" role="main">
                    <et-discovery-markets-results class="ng-scope" _nghost-rqp-c42="" ng-version="8.2.14">
                        <div _ngcontent-rqp-c42="" class="discover main-content no-footer" ui-fun-scroll="{'class': 'minimize', 'classEl': '.user-head-wrapper, .table-discover', 'scrollContainer': '.table-discover', 'setClassAtScroll': 200 }">
                            <div _ngcontent-rqp-c42="" automation-id="discover-market-results-wrapp" class="table-discover markets-table">
                                <et-discovery-markets-results-list _ngcontent-rqp-c42="" automation-id="discover-market-results-sub-view-list" _nghost-rqp-c44="" class="ng-star-inserted">
                                    <div _ngcontent-rqp-c44="" class="market-list list-view" data-etoro-locale-ns="discoverMarketResultsList">
                                        <et-instrument-mobile-row _ngcontent-rqp-c44="" automation-id="discover-market-results-row" _nghost-rqp-c18="" class="ng-star-inserted">
                                            <et-instrument-trading-mobile-row _ngcontent-rqp-c18="" automation-id="watchlist-grid-instruments-list" _nghost-rqp-c47="" class="ng-star-inserted">
                                                <div _ngcontent-rqp-c47="" class="row-wrap">
                                                    <div _ngcontent-rqp-c47="" automation-id="watchlist-item-list-wrapp-instrument" class="instrument-cell name-cell">
                                                        <div _ngcontent-rqp-c47="" class="avatar-img-wrap"> </div>
                                                        <div _ngcontent-rqp-c47="" automation-id="watchlist-item-grid-wrapp-instrument-info" class="avatar-info">
                                                            <div _ngcontent-rqp-c47="" automation-id="watchlist-item-grid-instrument-name" class="symbol">A</div>
                                                            <div _ngcontent-rqp-c47="" automation-id="watchlist-item-grid-instrument-full-name" class="name positive"> 0.68 (0.90%) </div>
                                                        </div>
                                                    </div>
                                                    <et-buy-sell-buttons _ngcontent-rqp-c47="" automation-id="watchlist-item-grid-instrument-buy-sell-container" class="instrument-cell buy-sell-buttons" _nghost-rqp-c24="">
                                                        <et-buy-sell-button _ngcontent-rqp-c24="" _nghost-rqp-c27="">
                                                            <div _ngcontent-rqp-c27="" class="prices no-label positive-change" automation-id="buy-sell-button-container-sell">
                                                                <div _ngcontent-rqp-c27="" class="trade-button-title">S</div>
                                                                <div _ngcontent-rqp-c27="" automation-id="buy-sell-button-rate-value" class="price">75.<span class="after-decimal">85</span></div>
                                                            </div>
                                                        </et-buy-sell-button>
                                                        <div _ngcontent-rqp-c24="" class="space-gap"></div>
                                                        <et-buy-sell-button _ngcontent-rqp-c24="" _nghost-rqp-c27="">
                                                            <div _ngcontent-rqp-c27="" class="prices no-label negative-change" automation-id="buy-sell-button-container-buy">
                                                                <div _ngcontent-rqp-c27="" class="trade-button-title">B</div>
                                                                <div _ngcontent-rqp-c27="" automation-id="buy-sell-button-rate-value" class="price">76.<span class="after-decimal">03</span></div>
                                                            </div>
                                                        </et-buy-sell-button>
                                                    </et-buy-sell-buttons>
                                                </div>
                                                <et-trade-item-card-action _ngcontent-rqp-c18="" _nghost-rqp-c15="">
                                                </et-trade-item-card-action>
                                            </et-instrument-trading-mobile-row>
                                        </et-instrument-mobile-row>
                                        <et-instrument-mobile-row _ngcontent-rqp-c44="" automation-id="discover-market-results-row" _nghost-rqp-c18="" class="ng-star-inserted">
                                            <et-instrument-trading-mobile-row _ngcontent-rqp-c18="" automation-id="watchlist-grid-instruments-list" _nghost-rqp-c47="" class="ng-star-inserted">
                                                <div _ngcontent-rqp-c47="" class="row-wrap">
                                                    <div _ngcontent-rqp-c47="" automation-id="watchlist-item-list-wrapp-instrument" class="instrument-cell name-cell">
                                                        <div _ngcontent-rqp-c47="" class="avatar-img-wrap"> </div>
                                                        <div _ngcontent-rqp-c47="" automation-id="watchlist-item-grid-wrapp-instrument-info" class="avatar-info">
                                                            <div _ngcontent-rqp-c47="" automation-id="watchlist-item-grid-instrument-name" class="symbol">AA</div>
                                                            <div _ngcontent-rqp-c47="" automation-id="watchlist-item-grid-instrument-full-name" class="name negative"> -0.11 (-1.46%) </div>
                                                        </div>
                                                    </div>
                                                    <et-buy-sell-buttons _ngcontent-rqp-c47="" automation-id="watchlist-item-grid-instrument-buy-sell-container" class="instrument-cell buy-sell-buttons" _nghost-rqp-c24="">
                                                        <et-buy-sell-button _ngcontent-rqp-c24="" _nghost-rqp-c27="">
                                                            <div _ngcontent-rqp-c27="" class="prices no-label negative-change" automation-id="buy-sell-button-container-sell">
                                                                <div _ngcontent-rqp-c27="" class="trade-button-title">S</div>
                                                                <div _ngcontent-rqp-c27="" automation-id="buy-sell-button-rate-value" class="price">7.<span class="after-decimal">44</span></div>
                                                            </div>
                                                        </et-buy-sell-button>
                                                        <div _ngcontent-rqp-c24="" class="space-gap"></div>
                                                        <et-buy-sell-button _ngcontent-rqp-c24="" _nghost-rqp-c27="">
                                                            <div _ngcontent-rqp-c27="" class="prices no-label negative-change" automation-id="buy-sell-button-container-buy">
                                                                <div _ngcontent-rqp-c27="" class="trade-button-title">B</div>
                                                                <div _ngcontent-rqp-c27="" automation-id="buy-sell-button-rate-value" class="price">7.<span class="after-decimal">47</span></div>
                                                            </div>
                                                        </et-buy-sell-button>
                                                    </et-buy-sell-buttons>
                                                </div>
                                                <et-trade-item-card-action _ngcontent-rqp-c18="" _nghost-rqp-c15="">
                                                </et-trade-item-card-action>
                                            </et-instrument-trading-mobile-row>
                                        </et-instrument-mobile-row>
                                    </div>
                                </et-discovery-markets-results-list>
                            </div>
                        </div>
                    </et-discovery-markets-results>
                </div>
            </div>
        </div>
    </ui-layout>
    </body>

</html>
"""

driver.get("data:text/html;charset=utf-8,{html_content}".format(html_content=html_content))
#results = driver.find_elements_by_xpath("//*[@class='ng-star-inserted']")
results = driver.find_elements_by_xpath("//*[et-instrument-mobile-row and @class='ng-star-inserted']")
print('Number of results', len(results))

Я не знаю, почему, если я ищу 'et-instrument-mobile- row 'Я получаю только 1 элемент вместо 2, и если я ищу и' et-instrument-mobile-row ', и' ng-star-вставлен ', я получаю 0 элементов. Глядя на пример, моя цель - получить символ и текущую стоимость покупки / продажи (цена и после десятичного числа).

Что-то вроде:

[A, 75.85, 76.03]

[AA, 7.44, 7.47]

Может ли кто-нибудь мне помочь? Спасибо!

1 Ответ

0 голосов
/ 24 апреля 2020

Похоже, что у вас может быть какое-то искаженное HTML, а Selenium не знает, как его проанализировать. Я заметил эту строку:

 <div _ngcontent-rqp-c47="" class="avatar-img-wrap"><img _ngcontent-rqp-c47="" automation-id="watchlist-item-grid-instrument-avatar" class="avatar-img" src="https://etoro-cdn.etorostatic.com/market-avatars/a/150x150.png" alt="Agilent Technologies Inc">

Этот тег <img> не закрыт. Вы можете видеть, что здесь также запутывается подсветка синтаксиса.

В противном случае искомый XPath выглядит в целом правильно.

Редактировать: посмотрел на это поближе. Ваше имя атрибута должно быть там, где *. Вот ваш XPath:

"//et-instrument-mobile-row[@class='ng-star-inserted']"

Редактировать 2: У Аскера был дополнительный вопрос о том, как искать в том, что они нашли с XPath выше.

Чтобы найти больше элементов в этих элементах, просматривая документацию , каждый Selenium WebElement предоставляет свой собственный find_element метод. Затем вы можете использовать их для дальнейшего поиска в тех элементах, которые мы только что нашли (обязательно используйте .// здесь, в ваших XPath-файлах, поскольку вам нужно только пройти по этому указанному c содержимому элемента - другие find_elements не имеют этого предупреждения) ,

После того, как вы определили элементы, содержащие символы и цены, вы можете просто ссылаться на атрибут text этих элементов. Давайте рассмотрим более простой пример:

<div class="a">
  <div class="b" id="1">B</div>
  <div class="c" id="2">2</div>
  <div class="d" id="3">22</div>
</div>

Предположим, мы уже нашли здесь root div и сохранили его в переменной с именем element. Тогда:

symbol = element.find_element_by_xpath(".//*[@class='b']").text
integral = element.find_element_by_xpath(".//*[@class='c']").text
fractional = element.find_element_by_xpath(".//*[@class='d']").text

Как правило, если вы можете выполнять поиск с помощью чего-то другого, кроме XPath, это будет проще для всех, кто в нем участвует. Вот более типичный способ сделать это sh с именами классов:

symbol = element.find_element_by_class_name("b").text
integral = element.find_element_by_class_name("c").text
fractional = element.find_element_by_class_name("d").text

Редактировать 3: Примечание автора

После драгоценной помощи @ Сначала я углубился, чтобы получить символ и различные цены для продажи / покупки следующим образом:

for element in results:
    symbol = element.find_element_by_xpath(".//*[@class='symbol']").text
    print(str(symbol))
    sell = element.find_element_by_xpath(".//et-buy-sell-buttons//et-buy-sell-button//div[@automation-id='buy-sell-button-container-sell']")
    sell_integral = sell.find_element_by_xpath(".//*[@class='price']").text
    sell_fractional = sell.find_element_by_xpath(".//*[@class='after-decimal']").text
    print(str(sell_integral)+':'+str(sell_fractional))
    buy = element.find_element_by_xpath(".//et-buy-sell-buttons//et-buy-sell-button//div[@automation-id='buy-sell-button-container-buy']")
    buy_integral = buy.find_element_by_xpath(".//*[@class='price']").text
    buy_fractional = buy.find_element_by_xpath(".//*[@class='after-decimal']").text
    print(str(buy_integral)+':'+str(buy_fractional))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...