最近在帮客户做东西时需要用到kfc的门店信息查询数据,在浏览了一圈博客之后,貌似大家都是采用
selenium + PhantomJS
这种方式抓取kfc的ajax动态网页,
其实在分析了一波该网站的请求之后,相对来说还是很简单的一个爬虫,该网站甚至没有做浏览器的验证
url = http://www.kfc.com.cn/kfccda/storelist/index.aspx
如图:
在我们查询一个城市之后发现浏览器接受了一个json文件
再来分析一下请求头
可以看到该请求是通过POST方式像服务器发起了的
然后做下面还有一个Form data,这个是前台表单提交的数据,分析到这我们不如先来尝试一下模拟提交一次表单
URL = "http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname"
params = {'cname': city,'pageSize': 10
}
html = requests.post(URL, data=params)
info = json.loads(html.text)
print(info)
运行如下:
{'Table': [{'rowcount': 43}], 'Table1': [{'rownum': 1, 'storeName': '山姆', 'addressDetail': '春城路沃尔玛一层', 'pro': 'Wi-Fi,点唱机,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 2, 'storeName': '大观', 'addressDetail': '大观街大观商业城沃尔玛1层', 'pro': 'Wi-Fi,点唱机,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 3, 'storeName': '吉大', 'addressDetail': '环城东路188号', 'pro': 'Wi-Fi,点唱机,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 4, 'storeName': '白云', 'addressDetail': '北京路延长线大白庙村家乐福超市一楼', 'pro': 'Wi-Fi,点唱机,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 5, 'storeName': '新迎', 'addressDetail': '新迎路212号好又多超市', 'pro': 'Wi-Fi,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 6, 'storeName': '青年路', 'addressDetail': '人民中路17号新西南大厦广场', 'pro': 'Wi-Fi,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 7, 'storeName': '龙泉', 'addressDetail': '龙泉路35-37号', 'pro': 'Wi-Fi,礼品卡', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 8, 'storeName': '北辰', 'addressDetail': '北京路延长线财富中心E栋', 'pro': 'Wi-Fi,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 9, 'storeName': '东寺街', 'addressDetail': '昆明东寺街中段东方广场A座一二层', 'pro': 'Wi-Fi,店内参观,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 10, 'storeName': '西山', 'addressDetail': '兴苑路城市领地花园超市一层', 'pro': 'Wi-Fi,店内参观,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 11, 'storeName': '新闻路', 'addressDetail': '新闻路337号-339号一层', 'pro': 'Wi-Fi,店内参观,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 12, 'storeName': '云大', 'addressDetail': '圆通东路佰腾数码广场一楼', 'pro': 'Wi-Fi,礼品卡', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 13, 'storeName': '正义路', 'addressDetail': '人民中路51、53号正义西街133号一层及正义坊A1栋二层', 'pro': 'Wi-Fi,点唱机,店内参观,礼品卡', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 14, 'storeName': '世纪城', 'addressDetail': '金源大道一号世纪金源购物中心一楼肯德基餐厅', 'pro': 'Wi-Fi,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 15, 'storeName': '云山路', 'addressDetail': '云山路与二环西路交叉口', 'pro': 'Wi-Fi,店内参观,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 16, 'storeName': '正大紫都城', 'addressDetail': '交菱路与二环西路交叉口正大紫都城一楼', 'pro': 'Wi-Fi,店内参观,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 17, 'storeName': '嘉年华', 'addressDetail': '烟草路嘉年华购物广场一层', 'pro': 'Wi-Fi,店内参观,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 18, 'storeName': '新南亚', 'addressDetail': '西山区滇池路南亚风情第一城A2栋一楼', 'pro': 'Wi-Fi,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 19, 'storeName': '光辉城市', 'addressDetail': '前兴路,光辉城市(沃尔玛入口)', 'pro': 'Wi-Fi,点唱机,店内参观,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 20, 'storeName': '和谐世纪', 'addressDetail': '小康大道,和谐世纪一层', 'pro': 'Wi-Fi,店内参观,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 21, 'storeName': '长水机场', 'addressDetail': '昆明长水国际机场候机楼负一楼', 'pro': '机场店,礼品卡', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 22, 'storeName': '星耀路', 'addressDetail': '星耀路星都总部基地星世界A座1-2层', 'pro': 'Wi-Fi,店内参观,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 23, 'storeName': '大屯', 'addressDetail': '安宁大屯路与珍泉交叉路口金色时代广场', 'pro': 'Wi-Fi,店内参观,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 24, 'storeName': '益龙万象城', 'addressDetail': '环城东路与白龙路交叉口益龙万象城一楼', 'pro': '店内参观,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 25, 'storeName': '新柏联', 'addressDetail': '三市街六号柏联广场商业廊一、二楼', 'pro': 'Wi-Fi,店内参观,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 26, 'storeName': '官南', 'addressDetail': '官南大道2169号大润发商业广场一楼2号商铺', 'pro': 'Wi-Fi,店内参观,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 27, 'storeName': '启鸿假日', 'addressDetail': '昆明假日城市小区一层', 'pro': 'Wi-Fi,店内参观,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 28, 'storeName': '新螺蛳湾二期', 'addressDetail': '宏仁片区昆明螺蛳湾商贸城二期5号楼F1-2', 'pro': 'Wi-Fi,店内参观', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 29, 'storeName': '前兴路万达', 'addressDetail': '前兴路万达广场二层', 'pro': 'Wi-Fi,店内参观,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 30, 'storeName': '长水机场精选', 'addressDetail': '昆明长水国际机场出发大厅区域B1-1号', 'pro': '精选店,礼品卡', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 31, 'storeName': '金方', 'addressDetail': '湖滨西路,金方扩建项目1.2层', 'pro': 'Wi-Fi,点唱机,店内参观,礼品卡', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 32, 'storeName': '海伦国际', 'addressDetail': '金源大道与广福路交汇处海伦国际', 'pro': 'Wi-Fi,店内参观,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 33, 'storeName': '美辰', 'addressDetail': '人民中路美辰百货1F肯德基', 'pro': 'Wi-Fi,点唱机,礼品卡,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 34, 'storeName': '昆明高铁到达', 'addressDetail': '昆明呈贡高铁站', 'pro': 'Wi-Fi', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 35, 'storeName': '长水机场到达精选', 'addressDetail': '昆明长水机场国际候机楼出发大厅', 'pro': '精选店', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 36, 'storeName': '机场安检内', 'addressDetail': '昆明长水国际机场安检区内', 'pro': '机场店', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 37, 'storeName': '机场精选出发浮岛F4层', 'addressDetail': '昆明长水机场出发层浮岛4F', 'pro': '精选店', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 38, 'storeName': '新顺城', 'addressDetail': '崇仁街11号一层F1-64/二层F2-12', 'pro': 'Wi-Fi,点唱机,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 39, 'storeName': '新顺城', 'addressDetail': '崇仁街11号一层F1-64/二层F2-12', 'pro': 'Wi-Fi,点唱机,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 40, 'storeName': '云投中心', 'addressDetail': '人民西路云投财富商业广场一层112号铺', 'pro': 'Wi-Fi,店内参观,生日餐会', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 41, 'storeName': '高新吾悦', 'addressDetail': '普吉街道办事处玉筇路与沙河路新城吾悦广场一层1031号商铺', 'pro': 'Wi-Fi,点唱机,店内参观,精选店', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 42, 'storeName': '昆明南站出发层', 'addressDetail': '昆明南站J20号商铺', 'pro': 'Wi-Fi,精选店', 'provinceName': '云南省', 'cityName': '昆明市'}, {'rownum': 43, 'storeName': '昆明火车站', 'addressDetail': '昆明站站房东侧一楼11号商铺', 'pro': 'Wi-Fi,点唱机,精选店', 'provinceName': '云南省', 'cityName': '昆明市'}]}
数据还算规整,只要稍作处理就可以用,
完整代码如下:
import requests
import jsonclass EasyKFC:URL = "http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname"# 得到所在城市kfc门店的数量 params:int@staticmethoddef get_num(city):""":param city:str:return:int"""params = {'cname': city,'pageSize': 0}html = requests.post(EasyKFC.URL, data=params)info = json.loads(html.text)return int(info['Table'][0]['rowcount'])# 得到所有kfc门店@staticmethoddef get_all_info(city):""":param city:str:return:dict"""params = {'cname': city,'pageSize': EasyKFC.get_num(city)}html = requests.post(EasyKFC.URL, data=params)info = json.loads(html.text)info['rowcount'] = int(info['Table'][0]['rowcount'])for i in info['Table1']:i['addressDetail'] = i['cityName'] + i['addressDetail']i['storeName'] = i['storeName'] + '餐厅'info.pop('Table')return info# 指定所在城市kfc最大获取数量 返回一个字典,@staticmethoddef get_info(city, num):""":param city:str:param num:int:return:dict"""params = {'cname': city,'pageSize': num}html = requests.post(EasyKFC.URL, data=params)info = json.loads(html.text)info['rowcount'] = int(info['Table'][0]['rowcount'])for i in info['Table1']:i['addressDetail'] = i['cityName'] + i['addressDetail']i['storeName'] = i['storeName'] + '餐厅'info.pop('Table')return info