Относительные селекторы в Selenium?

1

Я интересно, если есть "относительные" селекторы в Selenium подобно ele.css селектора в Scrapy. Например, в Scrapy вы можете сделать это:

for li in response.css('ul.rows li p.result-info'):
    lnk = li.css('a::attr(href)').extract_first()
    prc = li.css('span.result-meta span.result-price::text').extract_first()
    sqf = li.css('span.result-meta span.housing::text').extract_first()
    loc = li.css('span.result-meta span.result-hood::text').extract_first()
    objct = {
        'lnk': lnk,
        'prc': prc,
    }
    if sqf:
        chunk = sqf.split()
        objct['sqf'] = chunk[len(chunk)-1]
    if loc:
        objct['loc'] = loc
    yield objct

Можно ли сделать что-то подобное в Селене?

Сейчас я использую следующий код, который явно создает проблемы, поскольку пути не имеют отношения к делу. Вместо того, чтобы соскабливать, скажем, все детали для каждого элемента по одному пункту за раз (например, цена, размер, цвет для элемента A, затем цена, размер, цвет для элемента B, затем цена, размер, цвет для элемента C, поэтому и т.д.), я застрял? соскабливание одной детали для всех предметов (например, цена для элемента A, элемента B и элемента C, затем размер для элемента A, элемент B, элемент C), как в следующем коде.

discoverable_cards = browser.find_elements(By.XPATH, '//div[@class="discoverableCard"]')
product_type = browser.find_elements(By.XPATH, '//div[@class="discoverableCard-body"]/div[1]/span')
titles = browser.find_elements(By.XPATH, '//div[contains(@class, "discoverableCard-title")]')
descriptions = browser.find_elements(By.XPATH, '//div[contains(@class, "discoverableCard-description")]')
categories = browser.find_elements(By.XPATH, '//div[contains(@class, "discoverableCard-category")]')
balances = browser.find_elements(By.XPATH, '//div[contains(@class, "discoverableCard-balance")]')
currencies = browser.find_elements(By.XPATH, '//div[contains(@class, "discoverableCard-currencyCode")]')
percentages = browser.find_elements(By.XPATH, '//div[contains(@class, "discoverableCard-percent")]')
statuses = browser.find_elements(By.XPATH, '//span[contains(@class, "discoverableCard-formattedDate")] | //div[contains(@class, "discoverableCard-InDemandBottomLabel")]')

Образец HTML (и пример того, что я имею в виду)

<discoverable-card ng-repeat="campaign in campaigns track by campaign.clickthroughUrl" ng-click="cardClick()" gogo-test="card_1" lazy-load-image="true" discoverable="campaign" iggref="pica" class="ng-scope ng-isolate-scope"><div class="discoverableCard">
  <a in-view="$inview &amp;&amp; trackImpression()" ng-click="clickDiscoverable($event)" href="/projects/tastetro-spice-system-vegan/coming_soon/pica" gogo-test="card">
    <div class="discoverableCard-image lazyloaded" ng-class="{'lazyload': lazyLoadImage}" id="discoverableCard-image" data-bgset="https://c1.iggcdn.com/indiegogo-media-prod-cld/image/upload/c_fill,f_auto,h_273,w_273/cvuilsvvspmvmxhdynup.jpg" style="background-image: url(&quot;https://c1.iggcdn.com/indiegogo-media-prod-cld/image/upload/c_fill,f_auto,h_273,w_273/cvuilsvvspmvmxhdynup.jpg&quot;);">
    <picture style="display: none;"><source data-srcset="https://c1.iggcdn.com/indiegogo-media-prod-cld/image/upload/c_fill,f_auto,h_273,w_273/cvuilsvvspmvmxhdynup.jpg" sizes="273px" srcset="https://c1.iggcdn.com/indiegogo-media-prod-cld/image/upload/c_fill,f_auto,h_273,w_273/cvuilsvvspmvmxhdynup.jpg"><img alt="" class="lazyautosizes lazyloaded" data-sizes="auto" data-parent-fit="cover" sizes="273px"></picture></div>
    <div class="discoverableCard-body">
      <!-- ngIf: viewModel.isCampaign() --><div ng-if="viewModel.isCampaign()" class="discoverableCard-type discoverableCard-type--crowdfunding ng-scope">
           <span class="discoverableCard-type--crowdfundingLabel ng-binding" ng-bind="i18n.t('discoverable_card.type_label_campaign')">Funding</span>
           <!-- ngIf: !user && viewModel.isSaveForLaterCompatible() --><div user-auth-modal="" ng-if="!user &amp;&amp; viewModel.isSaveForLaterCompatible()" ng-click="toggleSavedForLater($event)" banner="i18n.t('discoverable_card.auth_modal_banner')" class="ng-scope ng-isolate-scope"><span class="campaignLoginModal" ng-click="openModal()" ng-transclude="">
             <span class="iggPopoverHtml ng-binding ng-scope ng-isolate-scope" ng-class="{ 'entreTooltip' : entre }" ng-bind-html="trustedHtml" igg-popover="" placement="top" aria-label="Save for later" role="img" aria-disabled="false" html="<svg><use xlink:href='#icon-icon-follow'></use></svg>"><svg><use xlink:href="#icon-icon-follow"></use></svg></span>
           </span><user-auth-modal banner="banner" status="status" class="ng-isolate-scope"></user-auth-modal></div><!-- end ngIf: !user && viewModel.isSaveForLaterCompatible() -->
           <!-- ngIf: user && viewModel.isSaveForLaterCompatible() && !viewModel.isSavedForLater() -->
           <!-- ngIf: user && viewModel.isSaveForLaterCompatible() && viewModel.isSavedForLater() -->
      </div><!-- end ngIf: viewModel.isCampaign() -->
      <!-- ngIf: viewModel.isProduct() -->
      <!-- ngIf: viewModel.isOffering() -->
      <div class="discoverableCard-title ng-binding discoverableCard-lineClamp2" ng-class="::viewModel.titleClampClass()" gogo-test="title" ng-bind="::viewModel.discoverable.title">TasteTro Spice System</div>
      <div class="discoverableCard-description ng-binding discoverableCard-lineClamp3" ng-class="viewModel.descriptionClampClass()" ng-bind="::viewModel.discoverable.tagline">An intelligent spice rack that delivers mouthwatering spice blends at the touch of a button.</div>
      <!-- ngIf: viewModel.isOffering() -->
      <div class="discoverableCard-category ng-binding" gogo-test="category" ng-click="clickCategory($event)" ng-bind="::viewModel.discoverable.category">Food &amp; Beverages</div>
      <!-- ngIf: viewModel.showCrowdFundingProgress() -->
      <!-- ngIf: viewModel.isStandardCampaign() -->
      <!-- ngIf: viewModel.isInDemandCampaign() -->
      <!-- ngIf: viewModel.isPreLaunchCampaign() --><div ng-if="viewModel.isPreLaunchCampaign()" class="discoverableCard-preLaunchBulletPoint ng-binding ng-scope" ng-bind="::viewModel.discoverable.bulletPoint">Register to get access to TasteTro secret perks!</div><!-- end ngIf: viewModel.isPreLaunchCampaign() -->
      <!-- ngIf: viewModel.isPreLaunchCampaign() --><div ng-if="viewModel.isPreLaunchCampaign()" class="discoverableCard-LaunchingSoon ng-scope">
        <svg-icon icon="icon-rocket" class="ng-isolate-scope"><svg class="iconLaunchingRocket" aria-label="Rocket Icon" role="img" aria-disabled="false">
  <use xlink:href="#icon-rocket"></use>
</svg>
</svg-icon>
        <span class="discoverableCard-LaunchingSoonLabel ng-binding" ng-bind="::i18n.t('discoverable_card.launching_soon_label')">Launching Soon</span>
      </div><!-- end ngIf: viewModel.isPreLaunchCampaign() -->
      <!-- ngIf: viewModel.isProduct() -->
      <!-- ngIf: viewModel.isOffering() -->
    </div>
    <!-- ngIf: viewModel.isOffering() -->
  </a>
</div>
</discoverable-card>

В приведенном выше примере то, что я хотел бы сделать, это, скажем, выбрать discoverable-card (т. discoverable_card = browser.find_elements(By.XPATH, '//discoverable-card'), а затем сделать следующие варианты: dc_child = discoverable_card.find_elements(By.XPATH, 'relative/path/to/child').

Теги:
xpath
scrapy
selenium
css-selectors

1 ответ

1
Лучший ответ

Вы можете просто выбрать элемент child/descendant из уже определенного элемента, как показано ниже:

discoverable_cards = browser.find_elements(By.XPATH, '//discoverable-card')
for card in discoverable_cards:
    dc_child = card.find_element(By.XPATH, './relative/path/to/child')

Обратите внимание, что вы должны указать точку в начале дочернего (./)/потокового (.//) локатора для указания текущего элемента card

  • 0
    потому что . выбирает текущий узел, правильно? какой смысл использовать .// когда вы могли бы просто сослаться на это с card ?
  • 0
    Если использовать любой другой селектор, то да, он будет работать так же, как card.find_element() , но в случае XPath вам также следует указать точку, указывающую на контекст
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню