Как извлечь цену за безопасность в виде текста с сайта через Python Selenium BeautifulSoup - PullRequest
0 голосов
/ 16 февраля 2019

Я пытаюсь просто получить цену для ценной бумаги, показанную в https://investor.vanguard.com/529-plan/profile/4514.Я запускаю этот код:

from selenium import webdriver
from bs4 import BeautifulSoup

driver = webdriver.Firefox(executable_path=r'C:\Program_Files_EllieTheGoodDog\Geckodriver\geckodriver.exe')
driver.get('https://investor.vanguard.com/529-plan/profile/4514')
html = driver.page_source
soup = BeautifulSoup(html, 'lxml')

Когда я "проверяю элемент" цены в открытом селеном Firefox, я ясно вижу это:

<span data-ng-if="!data.isLayer" data-ng-bind-html="data.value" data-ng-class="{sceIsLayer : isETF, arrange : isMutualFund, arrangeSec : isETF}" class="ng-scope ng-binding arrange">$42.91</span >

Но эти данные НЕ в моемсуп.Если я печатаю свой суп, HTML-код действительно сильно отличается от показанного на сайте.Я попробовал это, но это полностью провалилось:

myspan = soup.find_all('span', attrs={'data-ng-if': '!data.isLayer', 'data-ng-bind-html': 'data.value', 'data-ng-class': '{sceIsLayer : isETF, arrange : isMutualFund, arrangeSec : isETF}', 'class': 'ng-scope ng-binding arrange'})

Я в полном замешательстве.Если бы кто-нибудь мог указать мне правильное направление, я был бы очень признателен.Я чувствую, что что-то упустил, возможно несколько вещей ...

Ответы [ 2 ]

0 голосов
/ 16 февраля 2019

Selenium одного может быть достаточно для извлечения желаемого текста.Вам нужно вызвать WebDriverWait для visibility_of_element_located, и вы можете использовать следующее решение:

  • Кодовый блок:

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    driver = webdriver.Firefox(executable_path=r'C:\Utility\BrowserDrivers\geckodriver.exe')
    driver.get('https://investor.vanguard.com/529-plan/profile/4514')
    print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//tr[@class='ng-scope']//td[@class='ng-scope right']//span[@class='ng-scope ng-binding arrange' and @data-ng-bind-html]"))).get_attribute("innerHTML"))
    
  • Выход на консоль:

    $42.91
    
0 голосов
/ 16 февраля 2019

Нет ничего плохого в том, что вы используете атрибуты и значения data_* для выбора диапазона.На самом деле это правильный метод, упомянутый в документации . Существует 4 тега span, которые соответствуют всем атрибутам.find_all вернет все эти теги.Второй соответствует цене.

Что вы пропустили, так это то, что для загрузки интервала требуется некоторое время, а источник страницы возвращается до этого.Вы можете явно подождать этого промежутка и затем получить исходный код страницы.Здесь я использую Xpath для ожидания элемента.Вы можете получить xpath, перейдя к inspect tool -> right click element -> copy -> copy xpath

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup
driver = webdriver.Firefox()
driver.get('https://investor.vanguard.com/529-plan/profile/4514')
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH ,'/html/body/div[1]/div[3]/div[3]/div[1]/div/div[1]/div/div/div/div[2]/div/div[3]/div[1]/div/div/table/tbody/tr[1]/td[2]/div/span[1]')))
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
myspan = soup.find_all('span', attrs={'data-ng-if': '!data.isLayer', 'data-ng-bind-html': 'data.value', 'data-ng-class': '{sceIsLayer : isETF, arrange : isMutualFund, arrangeSec : isETF}', 'class': 'ng-scope ng-binding arrange'})
print(myspan)
print(myspan[1].text)

Выход

[<span class="ng-scope ng-binding arrange" data-ng-bind-html="data.value" data-ng-class="{sceIsLayer : isETF, arrange : isMutualFund, arrangeSec : isETF}" data-ng-if="!data.isLayer">Unit price as of 02/15/2019</span>, <span class="ng-scope ng-binding arrange" data-ng-bind-html="data.value" data-ng-class="{sceIsLayer : isETF, arrange : isMutualFund, arrangeSec : isETF}" data-ng-if="!data.isLayer">$42.91</span>, <span class="ng-scope ng-binding arrange" data-ng-bind-html="data.value" data-ng-class="{sceIsLayer : isETF, arrange : isMutualFund, arrangeSec : isETF}" data-ng-if="!data.isLayer">Change</span>, <span class="ng-scope ng-binding arrange" data-ng-bind-html="data.value" data-ng-class="{sceIsLayer : isETF, arrange : isMutualFund, arrangeSec : isETF}" data-ng-if="!data.isLayer"><span class="number-positive">$0.47</span> <span class="number-positive">1.11%</span></span>]
$42.91
...