2016-07-25 5 views
1

Ich mache eine Übung im Scraping Daten von einer Website. Zum Beispiel ZocDoc. Ich versuche, eine Liste aller Versicherungsanbieter und ihrer Pläne zu erhalten (Sie können diese Informationen auf ihrer Homepage im Dropdown-Menü für Versicherungen abrufen).Kratzen Webseite keine Ajax Anrufe gemacht aber Daten nicht in DOM

Es scheint, dass alle Daten über ein <scipt>-Tag geladen werden, wenn die Seite geladen wird. Wenn Sie auf der Registerkarte Netzwerk nachsehen, scheint es keine Netzwerkaufrufe zu geben, die JSON einschließlich der Plannamen zurückgeben. Ich bin in der Lage, alle Versicherungspläne mit den folgenden zu erhalten (Es ist chaotisch, aber es funktioniert).

import requests 
    from bs4 import BeautifulSoup as bs 
    resp = requests.get('https://zocdoc.com') 
    long_str = str(soup.findAll('script')[17].string) 
    pop = data.split("Popular Insurances")[1] 
    json.loads(pop[pop.find("[["):pop.find("]]")+2]) 

Im HTML-Code gibt es keine Versicherungspläne. Ich sehe auch keine Anfragen in der Netzwerk-Registerkarte, wo die Pläne zurückgeschickt werden (es gibt einige Backbone-Dateien). Eine URL sieht verschlüsselt aus, aber ich bin mir nicht sicher, dass das das ist und ich überdenke nur diese url.

Ich habe auch versucht zu warten, dass alle JS laden, so dass die Daten im DOM mit dryscrape aber immer noch keine Pläne im HTML sind.

Gibt es eine Möglichkeit, diese Informationen zu sammeln, ohne dass ein Crawler auf jeden Versicherer klicken muss, um seine Pläne zu erhalten?

+0

Die URL, die Sie gepostet haben, ist codiert und es ist einfach die Ordnungszahl des Textes, die Sie zurückbekommen, indem Sie das äußere 'eval' in der Information in ein' console.log' ändern. Das wird mehr Funktionen zurückgeben. Die letzte Zeile lautet also: console.log (eval ('String.fromCharCode (' + z + ')'));})() 'statt' eval (eval ('String.fromCharCode (' + z + ') '));})() '. –

+0

@CoryShay Danke, dass du das unterstrichen hast. Es sieht aus wie es für Cookies ist – user2954587

Antwort

2

Ja, wird die Liste der Versicherungen tief im Inneren des script Tag gehalten:

insuranceModel = new gs.CarrierGroupedSelect(gs.CarrierGroupedSelect.prototype.parse({ 
... 
primary_options: { 
     name: "Popular Insurances", 
     group: "primary", 
     options: [[300,"Aetna",2,0,1,0],[304,"Blue Cross Blue Shield",2,1,1,0],[307,"Cigna",2,0,1,0],[369,"Coventry Health Care",2,0,1,0],[358,"Medicaid",2,0,1,0],[322,"UniCare",2,0,1,0],[323,"UnitedHealthcare",2,0,1,0]] 
    }, 
    secondary_options: { 
     name: "All Insurances", 
     group: "secondary", 
     options: [[440,"1199SEIU",2,0,1,0],[876,"20/20 Eyecare Plan",2,0,1,1],...] 
    } 
... 

Sie können, natürlich, tauchen Sie ein in wunderbare Welt der JavaScript-Code in Python Parsen entweder mit regulären Ausdrücken oder Javascript-Parser wie slimit (example here), aber dies könnte zu weniger Haaren auf dem Kopf führen. Außerdem wäre die Ergebnislösung ziemlich fragil.

In diesem speziellen Fall denke ich, selenium ist ein viel besser passen. Komplettes Arbeitsbeispiel - immer die beliebten Versicherungen:

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.PhantomJS() 
driver.maximize_window() 

wait = WebDriverWait(driver, 10) 
insurance_dropdown = wait.until(EC.element_to_be_clickable((By.LINK_TEXT, "I'll choose my insurance later"))) 
insurance_dropdown.click() 

for option in driver.find_elements_by_css_selector("[data-group=primary] + .ui-gs-option-set > .ui-gs-option"): 
    print(option.get_attribute("data-value")) 

driver.close() 

Drucke:

Aetna 
Blue Cross Blue Shield 
Cigna 
Coventry Health Care 
Medicaid 
UniCare 
UnitedHealthcare 

Beachten Sie, dass in diesem Fall die Maden PhantomJS Browser verwendet wird, aber Sie verwenden können, Chrome oder Firefox oder andere Browser, die Selen haben ein verfügbarer Treiber für.

+0

Ja, ich kann die Versicherungsanbieter, aber nicht den Namen des Plans bekommen. Jeder dieser Anbieter hat auch Pläne. Das ist, was ich Probleme habe – user2954587

+0

ein Beispiel Plan ist 'ActiveCare 2' – user2954587

+0

@ user2954587 Gotcha, dies würde erfordern, klicken Sie auf die Versicherungen eins nach dem anderen und Extrahieren der Pläne, werde ich über etwas nachdenken und Sie später aktualisieren. Vielen Dank. – alecxe