俗话说,“巧妇难为无米之炊”。在数据科学道路上,数据获取是数据利用、分析等后续工作中的重要前提。虽然说,如今有许多开源的数据集,但是,锻炼自己从浩如烟海的网络中获取原始数据的能力,对于培养数据科学的基础技能是十分重要的。
本文目的是根据好评优先顺序,爬取携程网上的北京五星级酒店列表。
这一部分是本文的重点,将按照基本爬虫思路进行记录。
对于一个学生而言,拿到一道题,首先要做的工作是熟读题目、进行分析,而不是马上下笔答题。同理,爬虫之前,认真分析要爬取的页面,会使得工作事半功倍。
注:
请求对象,即我们需要的酒店列表接口,用URL进行表示。
five_star_url:http://hotels.ctrip.com/Domestic/Tool/AjaxHotelList.aspx
利用Python中的requests包,进行请求。通过Chrome浏览器的开发者选项分析,该请求类型为POST型。POST型请求大多用于提交表单、上传文件等操作。
# 1. Send request.
html = requests.post(url)
根据计算机网络的知识,网络中以数据包的形式进行请求,这里不再赘述。
数据包包含请求头和请求内容(即请求体)。
headers = {
"Connection": "keep-alive",
"origin": "http://hotels.ctrip.com",
"Host": "hotels.ctrip.com",
"referer": "http://hotels.ctrip.com/hotel/beijing1",
"user-agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36",
"Content-Type":"application/x-www-form-urlencoded; charset=utf-8"
}
请求头headers主要是为了伪造user-agent参数。
# 8 pages
for page in range(1,8):
data = {
"StartTime": "2019-02-19", # The value depends on the date you want to scrap.
"DepTime": "2019-02-20",
"RoomGuestCount": "0,1,2",
"cityId": 1,
"cityPY": " beijing",
"cityCode": "010",
"cityLat": 39.9105329229,
"cityLng": 116.413784021,
"page": page,
"star": 5,
"orderby": 3
}
这里说明一下,因为北京五星级酒店有8页,所以构建一个循环,即可实现对每一页进行请求。
所以,请求的代码修改如下:
html = requests.post(url=five_star_url, headers=headers, data=data)
在4.1的第3点中,通过Chrome浏览器的开发者选项中的“网络”选项,我们获知,需要的北京五星级酒店列表在响应的hotelPositionJSON中。
获取hotelPositionJSON对象中,即可得到酒店ID、酒店名称、酒店地址、酒店评分、酒店URL。
hotel_list = html.json()["hotelPositionJSON"]
for item in hotel_list:
id.append(item['id'])
name.append(item['name'])
hotel_url.append(item['url'])
address.append(item['address'])
score.append(item['score'])
在4.3中,我们爬取的结果是保存在列表中的。想要以csv文件的形式进行存储,需要把借助Python中的csv模块,即可实现。
注意:编码形式为“utf8-sig”,否则汉字容易出现乱码情况!
使用函数的形式,对爬取北京五星级酒店列表进行封装。
# coding=utf8
import numpy as np
import pandas as pd
from bs4 import BeautifulSoup
import requests
import random
import time
import csv
import json
import re
# Pandas display option
pd.set_option('display.max_columns', 10000)
pd.set_option('display.max_rows', 10000)
pd.set_option('display.max_colwidth', 10000)
pd.set_option('display.width',1000)
# Beijing 5 star hotel list url
five_star_url = "http://hotels.ctrip.com/Domestic/Tool/AjaxHotelList.aspx"
# Save the csv file in the Data Directory
filename = "./Data/Beijing 5 star hotel list.csv"
def Scrap_hotel_lists():
"""
It aims to crawl the 5 star hotel lists in Beijing and save in a csv file.
"""
headers = {
"Connection": "keep-alive",
"origin": "http://hotels.ctrip.com",
"Host": "hotels.ctrip.com",
"referer": "http://hotels.ctrip.com/hotel/beijing1",
"user-agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36",
"Content-Type":"application/x-www-form-urlencoded; charset=utf-8"
}
id = []
name = []
hotel_url = []
address = []
score = []
# 8 pages
for page in range(1,8):
data = {
"StartTime": "2019-02-19", # The value depends on the date you want to scrap.
"DepTime": "2019-02-20",
"RoomGuestCount": "0,1,2",
"cityId": 1,
"cityPY": " beijing",
"cityCode": "010",
"cityLat": 39.9105329229,
"cityLng": 116.413784021,
"page": page,
"star": 5,
"orderby": 3
}
html = requests.post(five_star_url, headers=headers, data=data)
hotel_list = html.json()["hotelPositionJSON"]
# Get the response information
for item in hotel_list:
id.append(item['id'])
name.append(item['name'])
hotel_url.append(item['url'])
address.append(item['address'])
score.append(item['score'])
# Random sleep for some seconds.
# It helps to avoid being blocked by the server.
time.sleep(random.randint(3,5))
# Form the array
hotel_array = np.array((id, name, score, hotel_url, address)).T
list_header = ['id', 'name', 'score', 'url', 'address']
array_header = np.array((list_header))
hotellists = np.vstack((array_header, hotel_array))
with open(filename, 'w', encoding="utf-8-sig", newline="") as f:
csvwriter = csv.writer(f, dialect='excel')
csvwriter.writerows(hotellists)
if __name__ == "__main__":
# Scrap 5 star hotel list in Beijing and save as a csv file
Scrap_hotel_lists()
# Pandas read the csv file and print the DataFrame object
df = pd.read_csv(filename, encoding='utf8')
print("1. Beijing 5 Star Hotel Lists")
print(df)
本文基于Python3,实现了对携程网页上,北京五星级酒店列表的爬取。未来工作是要完成对酒店具体详情信息进行爬取。
谢谢大家!