我正在从网站上抓取数据。例如,ZocDoc。我试图获取所有保险提供商及其计划的清单(您可以在保险下拉列表中访问其主页上的此信息)。
当页面加载时,似乎所有数据都通过<scipt>
标记加载。查看网络选项卡时,似乎没有任何返回JSON的网络调用,包括计划名称。我可以使用以下内容获得所有保险计划(这很麻烦,但它确实有效)。
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])
在返回的HTML中没有保险计划。我也没有在网络选项卡中看到任何发送计划的请求(有一些主干文件)。一个网址看起来已编码,但我不确定是不是这样,我只是过度思考这个url。
我还尝试等待所有JS加载,因此数据使用dryscrape在DOM中,但HTML中仍然没有计划。
有没有办法收集这些信息,而无需抓取每个保险提供商的抓取工具来获取他们的计划?
答案 0 :(得分:2)
是的,保险清单深入script
标签:
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],...]
}
...
当然,您可以使用正则表达式或Javascript解析器(如slimit
(example here)深入了解Python中JavaScript代码解析的精彩世界,但这可能会减少头部的毛发。此外,结果解决方案将非常脆弱。
在这种特殊情况下,我认为selenium
是更适合。完整的工作示例 - 获得流行的保险:
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()
打印:
Aetna
Blue Cross Blue Shield
Cigna
Coventry Health Care
Medicaid
UniCare
UnitedHealthcare
请注意,在这种情况下,会使用无头PhantomJS
浏览器,但您可以使用Chrome或Firefox或其他selenium具有可用驱动程序的浏览器。