刚开始接触Python的时候,我就已经被Python深深吸引了。Python吸引我的不仅仅是写网络爬虫,还有数据分析。我可以用图形化的方式呈现大量数据,更直观地解读数据。数据分析的前提是有数据可以分析。如果没有数据怎么办?首先,你可以去一些数据网站下载相关数据,但数据内容不一定是你想要的。二是自己爬取一些网站数据。今天就爬取全国所有的必胜客餐厅信息,用于后续的数据分析。01抓取目标我们要抓取的目标是必胜客中国。打开必胜客中国首页,进入“餐厅查询”页面。我们要抓取的数据内容包括城市、餐厅名称、餐厅地址和餐厅联系电话。因为我在页面看到一张地图,页面肯定有餐厅地址的经纬度。所以餐厅的经纬度也是我们需要爬取的数据。至于全国有必胜客餐厅的城市名单,我们可以通过“切换城市”页面获取。02分析目标页面在写爬虫程序之前,我先对页面进行简单的分析,然后具体说明爬虫思路。而分析页面结构往往会有一些意想不到的收获。我们使用浏览器的开发者工具对页面结构进行简单的分析。我们可以在StoreList页面中找到我们需要的数据。这决定了用于数据提取的XPath语法。StoreList页面的Response内容比较长。先不着急关闭页面,我们往下看,看看还有没有其他内容可以使用。***,我们找到调用获取餐厅列表信息的JavaScript函数的代码。我们搜索GetStoreList函数,看看浏览器是如何获取餐厅列表信息的。从代码中我们可以了解到,该页面使用Ajax获取数据。页面以POST方式请求地址http://www.pizzahut.com.cn/StoreList/Index。同时请求中还携带了参数pageIndex和pageSize。03爬虫思路经过一些页面结构分析,我们明确了爬虫的思路。首先,我们先获取城市信息。然后将其作为参数构建HTTP请求访问必胜客服务器获取当前城市所有餐厅数据。为了方便爬取数据,我把所有的城市都写进了cities.txt。当我们要爬取数据时,我们会从文件中读取城市信息。爬取思路好像没什么问题,但是还有一个问题没有解决。每次我们打开必胜客官网,页面都会自动定位到我们每次所在的城市。如果不能解决城市定位问题,只能抓取一个城市数据。那么,我们再浏览一下主页,看看能不能找到一些有用的信息。最后我们发现页面的cookies中有一个iplocation字段。我解码Url并得到像Shenzhen|0|0这样的信息。看到这个信息,我恍然大悟。原来必胜客网站使用我们的IP地址来设置初始城市信息。如果能伪造iplocation字段信息,就可以随意修改城市。04代码实现的第一步是从文件中读取城市信息。#全国有必胜客餐厅的城市,我把城市放在文件里,一共380个城市cities=[]defget_cities():"""从文件中获取城市"""file_name='cities.txt'withopen(file_name,'r',encoding='UTF-8-sig')asfile:forlineinfile:city=line.replace('','')cities.append(city)第二步遍历城市列表依次将各个城市作为Parameter,构造Cookies的iplocation字段。#依次遍历所有城市的餐厅forcityincities:restaurants=get_stores(city,count)results[city]=restaurantscount+=1time.sleep(2)然后,我们携带Cookie以POST方式请求必胜客服务器。***然后提取返回的页面数据。defget_stores(city,count):"""根据城市获取餐厅信息"""session=requests.Session()#urlencoding[city|0|0]city_urlencode=quote(city+'|0|0')#用于存储主页的cookiescookies=requests.cookies.RequestsCookieJar()headers={'User-agent':'Mozilla/5.0(WindowsNT6.3;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/55.0.2883.87UBrowser/6.2.3964.2Safari/537.36','accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8','Host':'www.pizzahut.com.cn','Cache-Control':'max-age=0','Connection':'keep-alive',}print('=============',count,'city:',city,'============')resp_from_index=session.get('http://www.pizzahut.com.cn/',headers=headers)#print(resp_from_index.cookies)#然后将原始cookies的iplocation字段设置为你要抓取的城市。cookies.set('AlteonP',resp_from_index.cookies['AlteonP'],domain='www.pizzahut.com.cn')cookies.set('iplocation',city_urlencode,domain='www.pizzahut.com.cn')#print(cookies)page=1restaurants=[]whileTrue:data={'pageIndex':page,'pageSize':"50",}response=session.post('http://www.pizzahut.com.cn/StoreList/Index',headers=headers,data=data,cookies=cookies)html=etree.HTML(response.text)#获取餐厅列表所在的div标签divs=html.xpath("//div[@class='re_RNew']")temp_items=[]fordivindivs:item={}content=div.xpath('./@onclick')[0]#ClickStore('22.538912,114.09803|城市广场|深南中路中信城市广场二楼|0755-25942012','GZH519')#过滤掉括号和后面的内容content=content.split('('')[1].split(')')[0].split('','')[0]iflen(content.split('|'))==4:item['coordinate']=content.split('|')[0]item['restaurant_name']=content.split('|')[1]+'餐厅'item['地址']=content.split('|')[2]item['phone']=content.split('|')[3]else:item['餐厅名称']=content.split('|')[0]+'餐厅'item['地址']=content.split('|')[1]item['phone']=content.split('|')[2]print(item)temp_items.append(item)ifnottemp_items:breakrestaurants+=temp_itemspage+=1time.sleep(5)returnrestaurants第三步把城市和所有餐厅城市等信息写入Json文件withopen('results.json','w',encoding='UTF-8')asfile:file.write(json.dumps(results,indent=4,ensure_ascii=false))05爬取结果程序运行结束后,会在当前目录下生成一个名为“results.json”的文件。完整代码参见GitHub:https://github.com/monkey-soft/SchweizerMesser/tree/master/Pizzahut作者简介:极客猴,热衷于Python,目前擅长使用Python制作网络爬虫和Django框架。
