Русский
Русский
English
Статистика
Реклама

Scala Selenium. Сколько человек в сборной имеют более одного гражданства?

Рассмотрим пример использования Selenium на Scala, отвечая на вопрос "Сколько человек в каждой футбольной сборной имеют более одного гражданства?"

За основу возьмем данные с сайта transfermarkt.com:

List of football/soccer teams

Переход на заданную страницу, если она реализует trait org.scalatestplus.selenium.Page, может осуществляться так:

import org.scalatestplus.selenium.Pageimport org.scalatestplus.selenium.WebBrowser._import org.openqa.selenium.WebDriverimplicit def webDriver: WebDriver = ??? /* from container */class RankingListPage(implicit val webDriver: WebDriver) extends Page {   val url = "https://www.transfermarkt.com/statistik/weltrangliste/statistik"}val rankingListPage = new RankingListPage()go to rankingListPage

После перехода прежде чем работать со страницей необходимо дождаться окончания отрисовки её элементов. Будем ориентироваться на кнопку Compact и дождемся, когда она станет видима.

Xpath локатор кнопки будет таким:

import org.scalatestplus.selenium.WebBrowser._val compactTab: Query = xpath("//div[.='Compact']")

Ожидание видимости элемента осуществляется так (timeout можно задать в конфиге, query - заданный элемент):

import org.openqa.selenium._import org.openqa.selenium.support.ui.WebDriverWaitimport org.openqa.selenium.support.ui.ExpectedConditionsimport org.scalatestplus.selenium.WebBrowser._import java.time.Durationdef waitVisible(query: Query, timeout: Int)(implicit webDriver: WebDriver): WebElement =    new WebDriverWait(webDriver, Duration.ofSeconds(timeout)).until(ExpectedConditions.visibilityOfElementLocated(query.by))

Рассмотрим переход на закладку Compact.

Переход на закладку будет состоять из следующих шагов:

  • Проверяем, активна ли закладка (активная закладка в данном случае в атрибуте class содержит "active").

  • Если да, то ничего не делаем переход осуществлен.

  • Если нет, то кликаем на закладку и ждём, когда закладка станет активна.

Проверить, что элемент query: Query содержит заданное значение в атрибуте class можно так:

def doesClassContain(value: String): Boolean =    (for {      element   <- find(query)      attribute <- element.attribute("class")    } yield attribute.contains(value)).contains(true)

Кликнуть на элемент можно так: clickOn(query)

Ожидание, когда атрибут class элемента будет содержать заданное значение, можно реализовать так:

def waitClassContain(value: String): Boolean =  new WebDriverWait(driver, Duration.ofSeconds(timeout)).until(ExpectedConditions.attributeContains(query.by, "class", value))

Итого:

def clickCompact(): Unit =    if (!compactTab.doesClassContain("active")) {      clickOn(compactTab)      val _ = compactTab.waitClassContain("active")    }

Теперь, когда мы находимся на закладке Compact можно начать вычисление списка всех сборных.

Для этого нужно последовательно обойти все страницы рейтинга и с каждой считать список.

Логика будет такой:

  • Проверяем, достигли ли последней страницы

  • Если нет, считываем список со страницы, переходим на следующую и возвращаемся на пункт выше

  • Если дошли до последней страницы, то считываем список с неё

Для того, чтобы проверить, достигли ли мы последней страницы, достаточно проверить, есть ли кнопка перехода на следующую страницу (см. скрин выше, css локатор li.naechste-seite > a):

val nextPageLink: Query = cssSelector("li.naechste-seite > a")def isPresent: Boolean = find(nextPageLink).isDefined

Для того, чтобы считать список стран, необходимо найти все элементы с xpath локатором //table/tbody//a[count(*)=0] и у каждого элемента считать text и значение атрибута href (или //table/tbody/tr[td[.='CONMEBOL']]//a[count(*)=0] - если интересна только одна конфедерация, например, самая маленькая - CONMEBOL(Южная Америка)):

val itemLink: Query = xpath("//table/tbody//a[count(*)=0]")def items(): Seq[(String, Option[String])] =  findAll(itemLink).map(el => (el.text.trim, el.attribute("href"))).toSeq

Для перехода на следующую страницу мало кликнуть на кнопку nextPageLink, необходимо ещё дождаться, когда этот переход произойдет.

Чтобы удостовериться, что мы перешли на следующую страницу, мы можем считать номер текущей страницы (css локатор li.selected > a), а после клика на nextPageLink дождаться, когда номер текущей страницы станет на 1 больше:

val selectedPageLink: Query = cssSelector("li.selected > a")def clickNextPage(): Unit = {  val nextPage = find(selectedPageLink).map(_.text).get().toInt + 1  clickOn(nextPageLink)  val _ = webDriverWait(driver).until(ExpectedConditions.textToBe(selectedPageLink.by, nextPage.toString))}

Соединяем все воедино и получаем следующий список (на 13 марта 2021):

Теперь, когда у нас есть url страны можно составить список игроков сборной.

Эта задача ещё более простая, потому что страница сборной страны содержит практически все те же необходимые нам элементы, что и страница рейтинга сборных. Изменения будут касаться только элемента itemLink (ссылка на игрока).

Ссылка на страницу игрока - это xpath локатор //table/tbody//span[@class='hide-for-small']/a[count(*)=0]:

val itemLink: Query = xpath("//table/tbody//span[@class='hide-for-small']/a[count(*)=0]")

Осталось только определить гражданство игрока сборной, пользуясь его страницей, найденной на предыдущем этапе.

Для начала нужно перейти на закладку Profile.

Мы уже переходили на закладку на предыдущих страницах. Здесь будет то же самое, за исключением одного нюанса: если раньше у активной закладки менялся атрибут class,то теперь этот атрибут меняется не у самой ссылки, а у её родителя. Кстати, в этот раз немецкие разработчики сайта значение атрибута class активного элемента не стали переводить на английский, а оставили на немецком - "aktiv":

Создадим два элемента: ссылку и её родителя, а затем определим переход на закладку так:

val profileTab: Query  = xpath("//li[@id='profile']")val profileLink: Query = xpath("//li[@id='profile']/a")def clickProfile(): Unit =   if (!profileTab.doesClassContain("aktiv")) {    clickOn(profileLink)    val _ = profileTab.waitClassContain("aktiv")  }

Теперь осталось только определить гражданство. Для этого возьмем элемент img из строки Citizenship: и считаем её атрибут title:

val citizenshipImg: Query = xpath("//th[.='Citizenship:']/following-sibling::td/img")def citizenship(): Seq[String] = findAll(citizenshipImg).flatMap(_.attribute("title")).toSeq

Вот и все, все страницы заполнены, осталось только написать автотест и тогда получим следующий результат.

Results (for Russia, Ukraine and Belarus)

Country name

%

Foreigners

Russia

11% (3/28)

(Brazil (1) -> (Mrio Fernandes), Kyrgyzstan (1) -> (Ilzat Akhmetov), Germany (1) -> (Roman Neustdter))

Ukraine

9% (3/33)

(Brazil (2) -> (Marlos, Jnior Moraes), Hungary (1) -> (Igor Kharatin))

Belarus

4% (1/25)

(Cameroon (1) -> (Maks Ebong))

В наших сборных только 3 натурализованных игрока (и все из Бразилии). Остальные родились в СССР.

Results (for CONMEBOL)

Country name

%

Foreigners

Brazil

36% (9/25)

(Spain (3) -> (Casemiro, Bruno Guimares, Vincius Jnior), Italy (1) -> (Alex Telles), France (1) -> (Thiago Silva), Portugal (4) -> (Ederson, Marquinhos, Allan, Lucas Paquet))

Argentina

57% (13/23)

(Spain (2) -> (Gonzalo Montiel, Lionel Messi), Italy (11) -> (Lucas Martnez Quarta, Wlter Kannemann, Nicols Tagliafico, Guido Rodrguez, Rodrigo de Paul, Giovani Lo Celso, Nicols Domnguez, ngel Di Mara, Joaqun Correa, Papu Gmez, Lucas Alario))

Uruguay

51,5% (18/35)

(Spain (7) -> (Jos Mara Gimnez, Sebastin Coates, Diego Godn, Agustn Oliveros, Damin Surez, Lucas Torreira, Federico Valverde), Paraguay (1) -> (Rodrigo Muoz), Italy (10) -> (Fernando Muslera, Martn Campaa, Sergio Rochet, Matas Via, Franco Pizzichillo, Nahitan Nndez, Matas Vecino, Giorgian de Arrascaeta, Diego Rossi, Cristhian Stuani))

Colombia

22% (6/27)

(Spain (4) -> (Jeison Murillo, Johan Mojica, James Rodrguez, Luis Surez), Argentina (1) -> (Frank Fabra), England (1) -> (Steven Alzate))

Chile

21% (5/24)

(Haiti (1) -> (Jean Beausejour), Spain (3) -> (Claudio Bravo, Gary Medel, Fabin Orellana), Italy (1) -> (Luis Jimnez))

Peru

33% (12/36)

(Venezuela (1) -> (Carlos Ascues), Spain (3) -> (Alexander Callens, Cristian Benavente, Sergio Pea), Uruguay (1) -> (Gabriel Costa), Italy (2) -> (Luis Abram, Gianluca Lapadula), Netherlands (1) -> (Renato Tapia), Switzerland (1) -> (Jean-Pierre Rhyner), Portugal (1) -> (Andr Carrillo), Croatia (1) -> (Ral Ruidaz), Lebanon (1) -> (Matas Succar))

Venezuela

25% (7/28)

(Spain (4) -> (Roberto Rosales, Juanpi Aor, Darwin Machs, Fernando Aristeguieta), Switzerland (1) -> (Rolf Feltscher), England (1) -> (Luis Del Pino Mago), Colombia (1) -> (Jan Hurtado))

Paraguay

21% (7/33)

(Spain (1) -> (Antonio Sanabria), Argentina (4) -> (Santiago Arzamendia, Gastn Gimnez, Andrs Cubas, Ral Bobadilla), Italy (2) -> (Antony Silva, Ivn Piris))

Ecuador

12% (4/33)

(Spain (3) -> (Erick Ferigra, Pervis Estupin, Leonardo Campana), Argentina (1) -> (Hernn Galndez))

Bolivia

25% (7/28)

(United States (2) -> (Adrin Jusino, Antonio Bustamante), Spain (1) -> (Jaume Cullar), Argentina (1) -> (Carlos Lampe), Brazil (1) -> (Marcelo Moreno), Switzerland (1) -> (Boris Cespedes), Portugal (1) -> (Erwin Snchez))

А вот в Южной Америке людей с двойным гражданством довольно много. Впрочем, это неудивительно: в чемпионатах Евросоюза жесткий лимит на легионеров (в заявке только 3 игрока с гражданством не ЕС), поэтому южноамериканцам, чтобы попасть в Европу, приходится либо пытаться получить гражданство бывшей митрополии (Бразилия -> Португалия, остальные -> Испания), либо искать среди своих предков итальянцев. Второе не так сложно, как кажется. Во время Второй Мировой войны Южная Америка хоть и была на бумаге нейтральной, по факту разделилась на два лагеря: Бразилия -> союзники, Аргентина + Уругвай -> фашисты. Поэтому неудивительно, что после 1945 года многие итальянцы в поисках лучшей жизни иммигрировали из разрушенной фашисткой Италии в симпатизировавшим ей Аргентине и Уругваю. Поэтому современному аргентинцу или уругвайцу получить гражданство Италии не сложнее, чем человеку по фамилии Зильберман - гражданство Израиля - кто-нибудь среди предков нужной национальности да найдётся!

Source code

Источник: habr.com
К списку статей
Опубликовано: 27.03.2021 12:17:15
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Scala

Браузеры

Тестирование веб-сервисов

Selenium-webdriver

Selenium

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru