一、找到存放数据的文件,分析其url
首先打开美团酒店部分页面,审查元素network里面的xhr部分,会发现一个HotelSearch******的文件如下图选中点开的部分:
发现所在页面的酒店存在此文件里,然后找出此文件的Headers,如下图:
Request URL很长,分析其组成发现:
前半部分是固定的,一直到uuid部分,uuid为Query String Parameters部分参数,刷新几次发现,uuid前半部分不变,@之后的部分会有变化,猜测此为时间戳,实践证明确实如此,我需要爬取西安的数据,因此cityid是固定的,观察发现offset为每页第一个商家的编号,每页20个商家,因此limit=20,startDay,endDay的含义显而易见,按照默认顺序因此sort=defaults,切换限制条件发现Query String Parameters部分X-FOR-WITH部分参数不变,由此构成url最后一部分,其中部分‘+’,‘=’符号需要修改,具体修改规则我目前还不了解,但是这部分不变,我就可以直接粘贴url过来用。
二、获取各个商圈id
不选择任何限制条件的情况下,美团酒店部分只显示51页数据,因此需要分区域获取,可以选择行政区/商圈、地铁站、高校、车站/机场、旅游景点、医院等,为了不漏掉部分酒店,选择拿到这些分类的所有id,以下是这部分程序
import requests
from lxml import html
import random
import json
import csv
from bs4 import BeautifulSoup
with open(r'C:\Users\Hanju\Desktop\美团西安酒店.csv',"w", newline='',encoding='UTF-8') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(['网站名','品类','商家名称','地址'])
url='http://hotel.meituan.com/xian/'
User_Agent_List = [
'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; LCTE; rv:11.0) like Gecko',
'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; LCTE; rv:11.0) like Gecko',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',
'Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5',
'Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5',
'Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5',
'Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1',
'MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1',
'Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; HTC; Titan)',
'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
]
headers={'User-Agent':random.choice(User_Agent_List)}
page = requests.get(url=url,headers=headers)
html=page.text
text=html.encode('ISO-8859-1').decode('utf-8')
bf=BeautifulSoup(text,'lxml')
tag=bf.find_all('script')
content=str(tag[1])[252:-15]
result=json.loads(content)
location=result['location']['columns']
#行政划分/商圈
arealist=[]
for item in location[1]['items']:
area=item['items']
for subarea in area:
arealist.append(subarea['id'])
#地铁线
linelist=[]
for item in location[2]['items'][1:]:
area=item['items']
for subarea in area:
linelist.append(subarea['id'])
#高校
collegelist=[]
for item in location[3]['items']:
group=item['items']
for college in group:
collegelist.append(college['id'])
#车站/机场
airportRailwaylist=[]
for item in location[4]['items']:
airportRailwaylist.append((item['id']))
#旅游景点
scenicSpotlist=[]
for item in location[5]['items']:
group=item['items']
for spot in group:
scenicSpotlist.append((spot['id']))
#医院
hospitallist=[]
for item in location[6]['items']:
group=item['items']
for hospital in group:
hospitallist.append(hospital['id'])
print(arealist)
print(linelist)
print(collegelist)
print(airportRailwaylist)
print(scenicSpotlist)
print(hospitallist)
运行结果将各个列表打印出来,如下
[113, 6835, 7137, 900, 8976, 897, 898, 899, 908, 7402, 7404, 8974, 8975, 9012, 15634, 15639, 15642, 15643, 15664, 15667, 15784, 15785, 116, 907, 910, 1099, 4763, 6836, 7403, 8977, 8978, 8979, 8984, 15630, 15632, 15635, 15640, 15641, 119, 8980, 8983, 8991, 15629, 15631, 15633, 15636, 15637, 15638, 15646, 15647, 115, 8981, 903, 7479, 7405, 904, 905, 906, 6839, 7408, 7480, 8982, 14024, 14025, 117, 909, 7407, 7478, 7477, 7406, 8950, 7140, 8951, 8952, 7141, 7138, 9309, 9477, 13026, 25592, 37367, 114, 7476, 7142, 901, 6838, 902, 7143, 8985, 14026, 18674, 36710, 37380, 4251, 7398, 7399, 7400, 7401, 14199, 16010, 16013, 25659, 4253, 8986, 8987, 8989, 8990, 17228, 235, 7145, 7146, 7147, 7148, 15644, 15645, 15665, 15666, 15668, 4257, 16938, 25170, 25171, 7149, 25713, 25715, 25717, 25719, 25721, 4254, 23761, 23762, 23763, 4255, 22410, 22416, 118, 4256, 22405, 22408, 26289, 26295, 33947]
[87, 1742, 1747, 1748, 1740, 1756, 1749, 1743, 1751, 1752, 1754, 1758, 1755, 1741, 1750, 1746, 1745, 1757, 1744, 1753, 51, 1737, 1736, 1739, 1738, 1183, 1182, 1181, 1180, 1179, 1178, 1177, 1176, 1175, 1174, 1173, 1172, 1171, 1170, 1169, 1168, 1167, 156, 4261, 4238, 4241, 4259, 4255, 4253, 4249, 4251, 4257, 4245, 4250, 4258, 4240, 4244, 4243, 4247, 4242, 4236, 4248, 4239, 4260, 4254, 4256, 4237, 4246, 4252]
[4964, 4946, 5911, 5912, 5913, 5914, 5915, 4937, 4938, 4940, 4941, 4942, 4944, 4945, 4948, 4949, 4954, 4955, 4958, 4971, 4980]
[101, 102, 103]
[9778, 843, 845, 847, 848, 851, 860, 863, 864, 871, 872, 27508, 9775, 31363, 20730, 20732, 844, 858, 29062, 29119, 9773, 9776, 27506, 9772, 9774, 9777, 20731, 10494, 10496, 841, 850, 854, 27487, 866, 27492, 869, 29061, 10355, 10356, 853, 857, 27483, 861, 865, 867, 868]
[20718, 20723, 20728, 25535, 25548, 25551, 25553, 24149, 24150, 20706, 27449, 25533, 25537, 25539, 25540, 25541, 25544, 25546, 25549, 25552]
下面按照url组成规则,按照列表遍历,代码如下:
import requests
from lxml import html
import random
import json
import time
import csv
with open(r'C:\Users\Hanju\Desktop\美团西安酒店.csv',"w", newline='',encoding='UTF-8') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(['网站名','品类','商家名称','地址'])
AreaList=[113, 6835, 7137, 900, 8976, 897, 898, 899, 908, 7402, 7404, 8974, 8975, 9012, 15634, 15639, 15642, 15643, 15664, 15667, 15784, 15785, 116, 907, 910, 1099, 4763, 6836, 7403, 8977, 8978, 8979, 8984, 15630, 15632, 15635, 15640, 15641, 119, 8980, 8983, 8991, 15629, 15631, 15633, 15636, 15637, 15638, 15646, 15647, 115, 8981, 903, 7479, 7405, 904, 905, 906, 6839, 7408, 7480, 8982, 14024, 14025, 117, 909, 7407, 7478, 7477, 7406, 8950, 7140, 8951, 8952, 7141, 7138, 9309, 9477, 13026, 25592, 37367, 114, 7476, 7142, 901, 6838, 902, 7143, 8985, 14026, 18674, 36710, 37380, 4251, 7398, 7399, 7400, 7401, 14199, 16010, 16013, 25659, 4253, 8986, 8987, 8989, 8990, 17228, 235, 7145, 7146, 7147, 7148, 15644, 15645, 15665, 15666, 15668, 4257, 16938, 25170, 25171, 7149, 25713, 25715, 25717, 25719, 25721, 4254, 23761, 23762, 23763, 4255, 22410, 22416, 118, 4256, 22405, 22408, 26289, 26295, 33947]
linelist=[87, 1742, 1747, 1748, 1740, 1756, 1749, 1743, 1751, 1752, 1754, 1758, 1755, 1741, 1750, 1746, 1745, 1757, 1744, 1753, 51, 1737, 1736, 1739, 1738, 1183, 1182, 1181, 1180, 1179, 1178, 1177, 1176, 1175, 1174, 1173, 1172, 1171, 1170, 1169, 1168, 1167, 156, 4261, 4238, 4241, 4259, 4255, 4253, 4249, 4251, 4257, 4245, 4250, 4258, 4240, 4244, 4243, 4247, 4242, 4236, 4248, 4239, 4260, 4254, 4256, 4237, 4246, 4252]
collegelist=[4964, 4946, 5911, 5912, 5913, 5914, 5915, 4937, 4938, 4940, 4941, 4942, 4944, 4945, 4948, 4949, 4954, 4955, 4958, 4971, 4980]
airportRailwaylist=[101, 102, 103]
scenicSpotlist=[9778, 843, 845, 847, 848, 851, 860, 863, 864, 871, 872, 27508, 9775, 31363, 20730, 20732, 844, 858, 29062, 29119, 9773, 9776, 27506, 9772, 9774, 9777, 20731, 10494, 10496, 841, 850, 854, 27487, 866, 27492, 869, 29061, 10355, 10356, 853, 857, 27483, 861, 865, 867, 868]
hospitallist=[20718, 20723, 20728, 25535, 25548, 25551, 25553, 24149, 24150, 20706, 27449, 25533, 25537, 25539, 25540, 25541, 25544, 25546, 25549, 25552]
Classlist=['areaId','stationId','college','airportRailway','scenicSpot','hospital'] (按照不同分类爬取url包含部分字段不同,所以增加此列表)
List=[]
List.append(AreaList)
List.append(linelist)
List.append(collegelist)
List.append(airportRailwaylist)
List.append(scenicSpotlist)
List.append(hospitallist)
for i in range(6):
class_=Classlist[i]
for area in List[i]:
for j in range(1,51):
t = time.time()
url='https://ihotel.meituan.com/hbsearch/HotelSearch?utm_medium=pc&version_name=999.9&cateId=20&attr_28=129&uuid=65E4A4E1481DEB3C239CDBA5375883CCF0C2146B51BFFFE54C22EF25CBD163E7%40'+str(int(round(t*1000)))+'&cityId=42&offset='+str(i*20)+'&limit=20&startDay=20180622&endDay=20180622&q=&sort=defaults&'+class_+'='+str(area)+'&X-FOR-WITH=WP7OFM8BmAyEL3fwC1hndfJ8RQ9wvfF06ulowvEq%2FE618PEzTt99YDqwbv58Iv257lSroAb6wLUFiYrkczFTgE2Cfv2X93DXMuCAWKEPpr7fzIbbtrBGLHadYR4vFYiWlrvb3Lr%2FPi%2BoS3Gs92mFZA%3D%3D'
User_Agent_List = [
'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; LCTE; rv:11.0) like Gecko',
'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; LCTE; rv:11.0) like Gecko',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',
'Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5',
'Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5',
'Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5',
'Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1',
'MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1',
'Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; HTC; Titan)',
'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50'
]
headers={'User-Agent':random.choice(User_Agent_List)}
page = requests.get(url=url, headers=headers)
html=page.text
result=json.loads(html)
result1=result['data']
result11=result1['searchresult']
if result11:
print(class_+':'+str(area))
for item in result11:
Info_List=[]
Info_List.append('美团')
Info_List.append('酒店')
Info_List.append(item['name'])
Info_List.append(item['addr'])
writer.writerow(Info_List)
time.sleep(random.choice(range(1,4)))(随机休眠)
else:
break
print("Done")
下面是部分运行结果:
areaId:113
areaId:113
areaId:113
areaId:113
以下是写入文件的部分数据:
网站名,品类,商家名称,地址
美团,酒店,锦江之星(西安东门店),碑林区柿园路163号(帝标大厦旁,近兴庆宫公园、陕西省电力公司对面)
美团,酒店,如家酒店(西安南门地铁站碑林博物馆店),碑林区文艺北路甲字1号(文昌门外十字东南角)
美团,酒店,富海明都酒店(明城墙南门店),碑林区环城南路与文艺北路十字西南角(文昌门外,地铁2号线永宁门站D2出口东行500米)
美团,酒店,钟楼天成酒店(地铁站回民街中心店),莲湖区钟楼北大街西华门十字西南角宏府嘉会公寓C座7F(回民小吃街东100米,地铁二号线钟楼站A口50米)
美团,酒店,派酒店(西安碑林博物馆和平门店),碑林区环城南路东段100号(和平门向东300米路南)
美团,酒店,铜川办事处招待所(西京医院康复路地铁口店),新城区兴庆路11号(西京医院对面路东50米)
美团,酒店,布丁酒店(西安钟楼中心店),碑林区东大街354号(端履门十字)
美团,酒店,卡森酒店(钟鼓楼永兴坊店),碑林区建国路88号新兴大厦 (吴铭火锅隔壁)
美团,酒店,星愉时尚连锁酒店(西安李家村万达广场店),碑林区明胜街9号(李家村万达广场西门向西100米紫玉兰亭旁)
美团,酒店,布丁酒店(西安大雁塔建筑科技大学店),碑林区太乙路23号(太乙路十字向南200米路东,中铁中学对面)
美团,酒店,宏源酒店(钟楼东大街店),新城区西一路与尚德路交汇处西20米(西一路116号)
美团,酒店,布丁酒店(西安钟鼓楼东大街万达广场店),碑林区东大街132号(大差市十字向东100米路南玄风桥北巷内)
美团,酒店,国展商务酒店,碑林区长安北路14号省体育场内东南(近省体育局)
美团,酒店,7天连锁酒店(西安小雁塔南稍门机场大巴店),碑林区友谊西路46号南稍门十字向西200米(南稍门地铁站A口向西200米,天源浴场正对面)
美团,酒店,小米时尚酒店(李家村万达店),碑林区雁塔北路1号(李家村十字东北角)
美团,酒店,万谛美途酒店,碑林区文艺南路39号
美团,酒店,柠檬•漫莎酒店(西安钟楼店),碑林区东大街与端履门交汇处西南角(钟楼、回民街东800米)
美团,酒店,西安十间酒店(小雁塔店),碑林区朱雀大街北段72号合能朱阙2号楼1单元1710室
美团,酒店,斯特威新概念酒店,碑林区东大街与端履门交汇处向南100米云龙大厦
美团,酒店,申鹏商务酒店(西安钟楼东大街店),碑林区东大街132号(大差市十字南100米,距永兴坊1000米)
美团,酒店,锦江之星(西安东门店),碑林区柿园路163号(帝标大厦旁,近兴庆宫公园、陕西省电力公司对面)
美团,酒店,如家酒店(西安南门地铁站碑林博物馆店),碑林区文艺北路甲字1号(文昌门外十字东南角)
美团,酒店,富海明都酒店(明城墙南门店),碑林区环城南路与文艺北路十字西南角(文昌门外,地铁2号线永宁门站D2出口东行500米)
美团,酒店,钟楼天成酒店(地铁站回民街中心店),莲湖区钟楼北大街西华门十字西南角宏府嘉会公寓C座7F(回民小吃街东100米,地铁二号线钟楼站A口50米)
美团,酒店,派酒店(西安碑林博物馆和平门店),碑林区环城南路东段100号(和平门向东300米路南)
美团,酒店,铜川办事处招待所(西京医院康复路地铁口店),新城区兴庆路11号(西京医院对面路东50米)
美团,酒店,布丁酒店(西安钟楼中心店),碑林区东大街354号(端履门十字)
美团,酒店,卡森酒店(钟鼓楼永兴坊店),碑林区建国路88号新兴大厦 (吴铭火锅隔壁)
美团,酒店,星愉时尚连锁酒店(西安李家村万达广场店),碑林区明胜街9号(李家村万达广场西门向西100米紫玉兰亭旁)
美团,酒店,布丁酒店(西安大雁塔建筑科技大学店),碑林区太乙路23号(太乙路十字向南200米路东,中铁中学对面)
美团,酒店,宏源酒店(钟楼东大街店),新城区西一路与尚德路交汇处西20米(西一路116号)
美团,酒店,布丁酒店(西安钟鼓楼东大街万达广场店),碑林区东大街132号(大差市十字向东100米路南玄风桥北巷内)
美团,酒店,国展商务酒店,碑林区长安北路14号省体育场内东南(近省体育局)
美团,酒店,7天连锁酒店(西安小雁塔南稍门机场大巴店),碑林区友谊西路46号南稍门十字向西200米(南稍门地铁站A口向西200米,天源浴场正对面)
美团,酒店,小米时尚酒店(李家村万达店),碑林区雁塔北路1号(李家村十字东北角)
美团,酒店,万谛美途酒店,碑林区文艺南路39号
美团,酒店,柠檬•漫莎酒店(西安钟楼店),碑林区东大街与端履门交汇处西南角(钟楼、回民街东800米)
美团,酒店,西安十间酒店(小雁塔店),碑林区朱雀大街北段72号合能朱阙2号楼1单元1710室
美团,酒店,斯特威新概念酒店,碑林区东大街与端履门交汇处向南100米云龙大厦
结束……