爬取网站script标签内快递服务信息的Python代码修复方案
问题背景
- 爬取目标:获取Justdial指定页面下所有快递服务商的全量关联信息,包含服务商名称、联系号码、地址、评分等字段
- 故障原因:目标数据存储在页面内嵌的script标签中,原有代码通过固定序号XPath路径
/html/head/script[9]提取内容,站点只要调整前置script标签的加载顺序,就会导致定位失效,无法拿到目标数据 - 原有问题代码:
import requests import pandas as pd import json import csv from lxml import html import re headers ={'authority': 'www.justdial.com', 'accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 ', 'accept-encoding': 'gzip, deflate, br', 'accept-language':'en-US,en;q=0.9', 'user-agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36" } produrl = 'https://www.justdial.com/Mumbai/Courier-Services-in-Mumbai-Bazar-Nalasopara-East/nct-10142628' prodresp = requests.get(produrl, headers=headers, timeout=30) prodResphtml = html.fromstring(prodresp.text) partjson = prodResphtml.xpath('/html/head/script[9]/text()') print(partjson)
修复方案
- 核心调整逻辑:放弃依赖固定序号定位script标签的不可靠方案,改为遍历页面全量script标签,通过业务数据独有的特征字符串(商户名、联系电话、
listingData字段标识)定位到存储目标数据的脚本块,再通过正则剥离JS语法、解析JSON结构提取所需字段,可适配页面常规的结构调整。 - 修复后可运行代码:
import requests import json import re from lxml import html headers ={ 'authority': 'www.justdial.com', 'accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 ', 'accept-encoding': 'gzip, deflate, br', 'accept-language':'en-US,en;q=0.9', 'user-agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36" } produrl = 'https://www.justdial.com/Mumbai/Courier-Services-in-Mumbai-Bazar-Nalasopara-East/nct-10142628' prodresp = requests.get(produrl, headers=headers, timeout=30) prodResphtml = html.fromstring(prodresp.text) # 遍历所有script标签,不再依赖固定序号 all_scripts = prodResphtml.xpath('//script/text()') target_data = None for script_content in all_scripts: if not script_content: continue # 匹配包含商户列表数据的script块,通过业务特征字段定位 if 'listingData' in script_content and 'contactNumber' in script_content: # 正则提取JSON内容,剥离JS变量定义语法 data_match = re.search(r'window\.__INITIAL_STATE__\s*=\s*({.*?});', script_content, re.S) if data_match: try: target_data = json.loads(data_match.group(1)) break except json.JSONDecodeError: continue # 提取需要的商户字段 courier_list = [] if target_data: # 从解析后的JSON结构中取商户列表 listings = target_data.get('searchResult', {}).get('listingData', []) for item in listings: courier_info = { '服务商名称': item.get('name'), '联系号码': item.get('contactNumber'), '地址': item.get('address'), '评分': item.get('rating') } courier_list.append(courier_info) # 打印结果验证 print(courier_list)
- 适配提示:
- 如果正则匹配的JS变量名和当前页面实际有差异,可以打印匹配到的script内容微调特征字段和正则规则,存储商户信息的script块一定会同时出现名称、电话、地址这类业务字段,特征辨识度很高
- 请求头里的
user-agent建议定期更新,避免被站点反爬拦截 - 提取字段时如果JSON路径有变动,可以先把解析后的
target_data完整打印出来,逐层确认字段所在位置再调整取值逻辑
内容的提问来源于stack exchange,提问作者A.D
相关产品推荐
相关产品推荐

