Python爬虫如何抓取Zillow全页价格 优化代码并将结果存为列表
回答
你现在的代码拿不全房源、运行不稳定主要是几个原因:
- 写死了从
/html开始的绝对XPath路径,Zillow前端DOM层级会随页面版本、加载状态动态变化,路径里的div[5]这类固定序号很容易偏移失效 - 直接用
requests拉取的初始HTML只包含首屏渲染的10条左右房源,剩下的房源是页面滚动后JS异步加载的,初始响应里根本没有这部分内容 - 手动循环拼接
li[x]序号的写法效率低,遇到非房源的li节点还容易越界报错 - 你代码里的URL字符串末尾少了闭合引号,运行会直接报语法错误
快速优化:拿到初始页所有已渲染房源,价格存为列表
不用手动循环li序号,直接用属性定位匹配所有房源卡片节点,容错率高很多:
from bs4 import BeautifulSoup from lxml import etree import requests URL = "https://www.zillow.com/losangeles-ca/" # 补全请求头,降低被反爬拦截的概率 HEADERS = { 'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', 'Accept-Language': 'en-US,en;q=0.9', 'Referer': 'https://www.zillow.com/' } webpage = requests.get(URL, headers=HEADERS) soup = BeautifulSoup(webpage.content, "html.parser") dom = etree.HTML(str(soup)) # 直接匹配所有房源价格节点:带data-test属性的价格标签,不用写死父级层级 price_list = dom.xpath('//div[@data-test="property-card-price"]/text()') # 打印所有价格 print(price_list) for price in price_list: print(price)
这里用Zillow自带的
data-test="property-card-price"属性定位价格节点,比写死div序号稳定得多,前端小改版不会影响定位结果。
抓取全量房源(不止首屏10条)
如果要拿所有搜索结果,不要硬解析HTML,直接抓Zillow的搜索接口效率和稳定性都高很多:
- 打开浏览器开发者工具,切到Network面板筛选XHR请求,滚动页面就能找到名为
GetSearchPageState.htm的接口 - 接口直接返回结构化JSON数据,所有房源的价格、地址、面积、链接等字段都已经整理好,不需要解析DOM
- 接口单页最多返回40条房源,修改参数里的
currentPage值就能翻页拿全量数据
参考代码:
api_url = "https://www.zillow.com/search/GetSearchPageState.htm" # 参数可以直接从浏览器开发者工具里复制对应请求的参数 params = { "searchQueryState": '{"pagination":{"currentPage":1},"usersSearchTerm":"Los Angeles, CA","mapBounds":{}}', "wants": '{"cat1":["listResults"]}', "requestId": 2 } resp = requests.get(api_url, headers=HEADERS, params=params) result = resp.json() # 直接从返回的JSON里提取所有价格 all_prices = [item["unformattedPrice"] for item in result["cat1"]["searchResults"]["listResults"]] print(all_prices)
这种写法不会受前端DOM改版、懒加载的影响,爬取效率比解析HTML高很多。
小提示
- 尽量不要用从根节点开始的绝对XPath,优先用元素自带的id、data属性、class做相对定位,代码稳定性会高很多
- Zillow反爬比较严格,单IP请求频率太高很容易被封,必要的时候需要搭配代理使用
内容的提问来源于stack exchange,提问作者z0x01z
相关产品推荐
相关产品推荐

