Использование селена и python для извлечения данных, когда они появляются после наведения курсора мыши - PullRequest
0 голосов
/ 19 июня 2020

Привет, ребята, это мой первый вопрос. Я пытаюсь извлечь данные с веб-сайта. Но проблема в том, что он появляется только тогда, когда я наводю на него указатель мыши. сайт к данным http://insideairbnb.com/melbourne/. Я хочу извлечь коэффициент занятости для каждого списка из панели, которая появляется, когда я наводю указатель мыши на точки на карте. Я пытаюсь использовать код @frianH из этого сообщения stackoverflow Очистить веб-сайт с помощью события Dynami c mouseover . Я новичок ie в извлечении данных с использованием селена. Я знаю о пакете bs4. Мне не удалось найти правильный xpath для выполнения задачи. Заранее спасибо. мой код до сих пор

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver import ActionChains
from selenium import webdriver

chrome_options = webdriver.ChromeOptions()
browser = webdriver.Chrome(options=chrome_options, executable_path='C:\\Users\\Kunal\\chromedriver.exe')
browser.get('http://insideairbnb.com/melbourne/')
browser.maximize_window()

#wait all circle
elements = WebDriverWait(browser, 20).until(EC.visibility_of_all_elements_located((By.XPATH, '//*[@id="map"]/div[1]/div[2]/div[2]/svg')))
table = browser.find_element_by_class_name('leaflet-zoom-animated')

#move perform -> to table
browser.execute_script("arguments[0].scrollIntoView(true);", table)

data = []
for circle in elements:
    #move perform -> to each circle
    ActionChains(browser).move_to_element(circle).perform()
    # wait change mouseover effect
    mouseover = WebDriverWait(browser, 30).until(EC.visibility_of_element_located((By.XPATH, '//*[@id="neighbourhoodBoundaries"]')))
    data.append(mouseover.text)

print(data[0])

спасибо в adnvace

1 Ответ

0 голосов
/ 19 июня 2020

Итак, я проверил эту страницу несколько раз, и она кажется довольно устойчивой к собственным методам селена, поэтому нам придется полагаться на javascript. Вот полный код:

from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver import ActionChains
from selenium import webdriver

chrome_options = webdriver.ChromeOptions()
browser = webdriver.Chrome(options=chrome_options, executable_path='chromedriver.exe')
browser.get('http://insideairbnb.com/melbourne/')
browser.maximize_window()

# Set up a 30 seconds webdriver wait
explicit_wait30 = WebDriverWait(browser, 30)

try:
    # Wait for all circles to load
    circles = explicit_wait30.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, 'svg.leaflet-zoom-animated > g:nth-child(2) > circle')))
except TimeoutException:
    browser.refresh()

data = []
for circle in circles:
    # Execute mouseover on the element
    browser.execute_script("const mouseoverEvent = new Event('mouseover');arguments[0].dispatchEvent(mouseoverEvent)", circle)
    # Wait for the data to appear
    listing = explicit_wait30.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#listingHover')))
    # listing now contains the full element list - you can parse this yourself and add the necessary data to `data`
    .......
    # Close the listing
    browser.execute_script("arguments[0].click()", listing.find_element_by_tag_name('button'))

Я также использую селекторы css вместо XPATH. Вот как работает поток:

circles = explicit_wait30.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, 'svg.leaflet-zoom-animated > g:nth-child(2) > circle')))

Он ожидает, пока все круги будут присутствовать, и извлекает их в circles.

Имейте в виду, что страница очень медленно загружает круги, поэтому я установил блок try/except для автоматического обновления sh страницы, если она не загружается в течение 30 секунд. Не стесняйтесь изменять это, как хотите.

Теперь нам нужно пройти l oop по всем кругам -

for circle in circles:

Далее имитируется событие mouseover на круге, мы ' Я буду использовать javascript для этого

Вот как будет выглядеть javascript (обратите внимание, что circle относится к элементу, который мы передадим из селена)

const mouseoverEvent = new Event('mouseover');
circle.dispatchEvent(mouseoverEvent)

Вот как скрипт выполняется через селен -

browser.execute_script("const mouseoverEvent = new Event('mouseover');arguments[0].dispatchEvent(mouseoverEvent)", circle)

Теперь нам нужно дождаться появления списка-

listing = explicit_wait30.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#listingHover')))

Теперь у вас listing, элемент, который также содержит много других элементов, теперь вы можете легко извлечь каждый элемент, как хотите, и сохранить их внутри data.

Если вы не заботитесь об извлечении каждого элемента по-разному, просто выполните .text on listing приведет к примерно такому результату -

'Tanya\n(No other listings)\n23127829\nSerene room for a single person or a couple.\nGreater Dandenong\nPrivate room\n$37 income/month (est.)\n$46 /night\n4 night minimum\n10 nights/year (est.)\n2.7% occupancy rate (est.)\n0.1 reviews/month\n1 reviews\nlast: 20/02/2018\nLOW availability\n0 days/year (0%)\nclick listing on map to "pin" details'

Вот и все, затем вы можете добавить результат в data, и все готово!

...