
Ao executar consultas, XPath opera em entidades como nós. Os nós são de vários tipos: elemento (nó de elemento), atributo (nó de atributo), texto (nó de texto), namespace (nó de namespace), instrução de processamento (nó de instrução executável), comentário (nó de comentário) , documento (nó do documento).
Vamos considerar como no XPATH a sequência de nós é definida, as direções de seleção e a seleção de nós com valores específicos.
Para selecionar nós, 6 tipos principais de estruturas são usados principalmente:

Além disso, ao selecionar nós, é possível usar máscaras curinga quando não sabemos que tipo de nó deve tomar.

Na linguagem XPATH, construções especiais chamadas de eixo são usadas para selecionar em relação ao nó atual.

A regra de seleção pode ser absoluta (// input [@ placeholder = "Login" - seleção começando no nó raiz] ou relativa (* @ class = "okved-table__code" - seleção relativa ao nó atual).
Construindo uma regra de seleção para cada um etapa de amostragem é realizada em relação ao nó atual e leva em consideração:
- O nome do eixo para amostrar
- Condição para selecionar um nó por nome ou posição
- Zero ou mais predicados
Em geral, a sintaxe de uma etapa de amostragem é:
axisname::nodetest[predicate]
Para selecionar nós específicos para algumas condições, parâmetros ou posições, uma ferramenta como predicados é usada. A condição do predicado está entre colchetes. Exemplos:

Além das construções de linguagem XPATH acima, ele também contém suporte para vários operadores (+, -, *, div, mod, = ,! =, And, ou, etc.), bem como mais de 200 funções integradas.
Vamos dar um exemplo prático. Precisamos fazer upload de informações sobre os períodos de uma determinada lista de pessoas. Para fazer isso, usaremos o serviço notariat.ru.
Importamos dependências.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
from multiprocessing import Pool
from retry import retry
import itertools, time, pprint, os, re, traceback, sys, datetime
import pandas as pd, numpy as np, multiprocessing as mp
Carregando dados sobre pessoas:
df_people = pd.read_excel('people.xlsx')
Extraímos informações de páginas com informações sobre pessoas.
def find_persons(driver, name, birth_date):
base_url = 'https://notariat.ru/ru-ru/help/probate-cases/'
#
driver.get(base_url)
#
driver.find_element_by_xpath('//input[@name="name"]').send_keys(name)
#
driver.find_element_by_xpath('//select[@data-placeholder=""]/following::div/a').click()
#
driver.find_element_by_xpath('//select[@data-placeholder=""]/following::div//li[@data-option-array-index={}]'.format(birth_date.day)).click()
#
driver.find_element_by_xpath('//select[@data-placeholder=""]/following::div/a').click()
#
driver.find_element_by_xpath('//select[@data-placeholder=""]/following::div//li[@data-option-array-index={}]'.format(birth_date.month)).click()
#
driver.find_element_by_xpath('//input[@placeholder=""]').send_keys(str(birth_date.year))
#
driver.find_element_by_xpath('//*[contains(., " ")]').click()
# 20 , «probate-cases__result-list»
WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CLASS_NAME, "probate-cases__result-list")))
time.sleep(2)
#
max_pages = 1
pages_counters = driver.find_elements_by_xpath('//a[@class="pagination__item-content"]')
if pages_counters:
max_pages = int(pages_counters[-1].text)
data = []
def parse_page_data():
#
lines = driver.find_elements_by_xpath('//ol[@class="probate-cases__result-list"]/li')
for line in lines:
name = ' '.join(map(lambda el: el[0].upper() + el[1:].lower(), line.find_element_by_xpath('.//h4').text.split()))
death_date = datetime.datetime.strptime(line.find_element_by_xpath('.//p').text.split(':')[-1].strip(), '%d.%m.%Y')
data.append((name, birth_date, death_date))
#
if max_pages == 1:
parse_page_data() #
else:
for page_num in range(1, max_pages + 1):
# ,
driver.find_element_by_xpath('//li[./a[@class="pagination__item-content" and text()="{}"]]'.format(page_num)).click()
time.sleep(0.2)
#
parse_page_data()
return data
Realizamos pesquisas usando o módulo de multiprocessamento para agilizar a coleta de dados.
def parse_persons(persons_data_chunk, pool_num):
# Chrome headless ( DOM notariat.ru )
chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--window-size=1920,1080")
driver = webdriver.Chrome(options=chrome_options)
driver.set_page_load_timeout(20)
data = []
print(pool_num, '')
#
for ind, (person_name, person_date) in enumerate(persons_data_chunk, start=1):
print('pool:', pool_num, ', person: ', ind, '/', len(persons_data_chunk))
try:
data.extend(find_persons(driver, person_name, person_date))
except Exception as e:
print(pool_num, 'failed to load', person_name, person_date, "error:", e)
traceback.print_exception(*sys.exc_info())
print(pool_num, 'done')
return data
def parse(people_data, parts=5):
p = mp.Pool(parts)
#
people_in_chanks = np.array_split(people_data, parts if parts < len(people_data) else 1) or []
all_data = p.starmap(parse_persons, zip(people_in_chanks, range(parts)))
out = []
for el in all_data:
out.extend(el)
return out
parsed_data = parse(people_data)
E salvamos os resultados:
df = pd.DataFrame({
'': list(map(lambda el: el[0], parsed_data)),
" ": list(map(lambda el: el[1], parsed_data)),
' ': list(map(lambda el: el[2], parsed_data))
})
df.to_excel('results.xlsx', index=False)
A figura abaixo mostra a página de busca de arquivos pessoais, que indica o nome completo, a data de nascimento, que são posteriormente procurados. Após inserir o nome completo e a data de nascimento, o algoritmo clica no botão para pesquisar um caso, após o que analisa os resultados.

Na próxima figura, vemos uma lista, cujos elementos são analisados pelo algoritmo.

O exemplo acima mostrou como você pode usar XPATH para coletar informações de páginas da web. Mas, como já mencionado, XPATH é aplicável para processar qualquer documento xml, sendo o padrão da indústria para acessar elementos xml e xhtml, transformações xslt.
Freqüentemente, a legibilidade do código afeta sua qualidade, portanto, você deve abandonar as expressões regulares ao analisar, estudar XPATH e começar a aplicá-lo em seu fluxo de trabalho. Isso tornará seu código mais fácil de entender. Você cometerá menos erros e também reduzirá o tempo de depuração.