如何用Python模拟滚动抓取JustDial数据?或解析其加载API?
解决JustDial滚动加载数据及API无页码参数的爬取问题
一、模拟页面滚动加载(Selenium方案)
JustDial的列表是滚动到底部才加载新数据,用Selenium可以模拟这个操作,直到没有新数据出来为止:
- 初始化浏览器驱动,打开目标页面
- 循环滚动到页面底部,等待加载完成后对比当前记录数和之前的记录数,直到两者一致(说明没有新数据了)
from selenium import webdriver from selenium.webdriver.common.by import By import time driver = webdriver.Chrome() driver.get("https://www.justdial.com/Mumbai/General-Physician-Doctors/nct-10892680") prev_item_count = 0 while True: # 滚动到页面最底部 driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") # 等3秒让数据加载(也可以用WebDriverWait等新元素出现,更稳妥) time.sleep(3) # 统计当前加载的条目数(JustDial的医生条目一般带cntanr类,自己核对下页面元素) current_items = driver.find_elements(By.CLASS_NAME, "cntanr") current_count = len(current_items) if current_count == prev_item_count: # 没新数据了,退出循环 break prev_item_count = current_count # 拿到完整页面源码,用BeautifulSoup解析 page_html = driver.page_source # 后续用BeautifulSoup处理page_html即可... driver.quit()
二、直接调用API接口(更高效的方案)
你发现的那个POST请求才是加载数据的核心,比模拟滚动效率高多了。虽然没看到页码参数,但这类接口一般用最后一条数据的标识来分页,比如last_val或者类似的参数,步骤如下:
1. 抓包分析请求参数
打开浏览器Network面板,刷新页面后找到那个POST请求,查看它的Payload(请求体)和返回的JSON:
- 第一次请求的Payload里会有
city、search、nct这些基础参数 - 返回的JSON里会包含当前页的数据,还有一个用于下一页的标记(比如
last_val,具体看返回结构)
2. 循环请求API
把第一次的请求参数拿来,每次请求后更新分页标记,直到返回的数据为空:
import requests import time api_url = "https://www.justdial.com/api/resultsPageListing?searchReferer=gen" # 从浏览器Network面板复制请求头,Cookie和User-Agent必须带,不然会被拦截 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36", "Cookie": "这里复制你浏览器里的Cookie内容", "Content-Type": "application/x-www-form-urlencoded" } # 初始请求参数,从Payload里复制 payload = { "city": "Mumbai", "search": "General Physician Doctors", "nct": "10892680", "pg": "1", "sortby": "popularity" # 其他参数按实际抓包结果补充 } all_doctors = [] while True: resp = requests.post(api_url, headers=headers, data=payload) resp_data = resp.json() # 提取当前页的医生数据(具体字段看返回的JSON结构) current_page_data = resp_data.get("data", []) if not current_page_data: break all_doctors.extend(current_page_data) # 获取下一页需要的标记,比如last_val next_mark = resp_data.get("last_val") if not next_mark: break # 更新payload里的分页标记 payload["last_val"] = next_mark # 有些接口需要自增pg参数,看情况加:payload["pg"] = str(int(payload["pg"]) + 1) # 加个延迟,避免被封 time.sleep(2) # 处理爬取到的数据 for doc in all_doctors: print(f"医生姓名:{doc.get('name')},地址:{doc.get('address')}")
三、注意点
- 反爬:JustDial有反爬机制,频繁请求容易被封IP,建议用代理或者控制请求间隔
- 合法性:确保爬取行为符合网站的robots.txt和当地法律法规
内容的提问来源于stack exchange,提问作者juan
相关产品推荐
相关产品推荐

