Python3 爬取携程网[1]: 根据好评优先顺序,获取北京五星级酒店列表

1. 项目目的

俗话说,“巧妇难为无米之炊”。在数据科学道路上,数据获取是数据利用、分析等后续工作中的重要前提。虽然说,如今有许多开源的数据集,但是,锻炼自己从浩如烟海的网络中获取原始数据的能力,对于培养数据科学的基础技能是十分重要的。

2. 需求分析

本文目的是根据好评优先顺序,爬取携程网上的北京五星级酒店列表。

3. 实验环境

  • 语言:Python 3.7
  • 操作系统:MacOS
  • 编程IDE:Pycharm
  • 浏览器:Chrome

4. 具体实现

这一部分是本文的重点,将按照基本爬虫思路进行记录。

4.1 分析页面

对于一个学生而言,拿到一道题,首先要做的工作是熟读题目、进行分析,而不是马上下笔答题。同理,爬虫之前,认真分析要爬取的页面,会使得工作事半功倍。

  1. 打开携程网.
    在页面上选择:
  • 城市:北京
  • 入住日期:2019-02-19
  • 退房日期:2019-02-20
  • 房间数:1间
  • 住客数:2人
  • 酒店级别:五星级/豪华
    如图1所示:
    《Python3 爬取携程网[1]: 根据好评优先顺序,获取北京五星级酒店列表》

图1 携程主页及酒店信息选择

  1. 分析北京五星级酒店页面
    点击图1中的“搜索”按钮,在酒店列表页面中选择好评优先排序方式。如图2所示。
    《Python3 爬取携程网[1]: 根据好评优先顺序,获取北京五星级酒店列表》

图2 北京五星级酒店列表页面

  1. 寻找页面接口
    因为每一个酒店都是可点击跳转的,即可交互,所以,为动态页面。静态页面可以直接通过页面源码,实现获取信息;动态页面需要找寻接口,然后从其接口的源码中获取信息。
    在页面空白处,点击右键,选择“检查”,可以看到页面的源码。找寻接口,必须选中第一行的“Network”选项。
    点击页面刷新按钮,即可在Filter中输入“Hotel”,选择“XHR”,即可找到页面接口。

《Python3 爬取携程网[1]: 根据好评优先顺序,获取北京五星级酒店列表》

图3 酒店列表页面接口 由图3可以看到,左部分列表中的“AjaxHotelList.aspx”就是需要的接口,在右侧的preview中,可以看到,页面上的酒店列表就存放于“hotelPositionJSON”中。这就意味着,请求这个接口,获取其响应中的hotelPositionJSON,即可获得酒店列表信息。

4.2 请求

这是一个B/S架构,如图4所示:
《Python3 爬取携程网[1]: 根据好评优先顺序,获取北京五星级酒店列表》

图4 B/S基本请求响应图 图4主要展现的是一个请求–响应关系图。Chrome浏览器向携程服务器请求接口URL,携程服务器将结果返回给浏览器进行呈现。

注:

  1. 图4主要呈现一个请求–响应关系,而不是严格的HTTPS协议握手过程。
  2. Cookie是保存在浏览器端中的,而Session保存在服务器端。

4.2.1 请求对象

请求对象,即我们需要的酒店列表接口,用URL进行表示。
five_star_urlhttp://hotels.ctrip.com/Domestic/Tool/AjaxHotelList.aspx

4.2.2 请求方法

利用Python中的requests包,进行请求。通过Chrome浏览器的开发者选项分析,该请求类型为POST型。POST型请求大多用于提交表单、上传文件等操作。

# 1. Send request.
html = requests.post(url)

4.2.3 请求头和请求体

根据计算机网络的知识,网络中以数据包的形式进行请求,这里不再赘述。
数据包包含请求头和请求内容(即请求体)。

  1. 请求头
    在爬虫过程中,若不设置请求头,频繁请求服务器,可能会造成客户端的IP被服务器端所封闭等后果,所以,需要对请求头进行伪造。
  • User-agent是一个特殊字符串,可以使服务器识别客户使用的操作系统及版本 、 浏览器及版本等信息。在做爬虫时加上此信息,可以伪装为浏览器。
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参数。

  1. 请求体
    请求体,即请求内容。在4.1中,我们讲述了要获取的页面内容,即入住时间、退房时间等,请求内容即为这一部分的代码形式。
# 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.3 响应

在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.4 保存响应结果

在4.3中,我们爬取的结果是保存在列表中的。想要以csv文件的形式进行存储,需要把借助Python中的csv模块,即可实现。

  • 首先用Numpy模块,将列表整合成矩阵的形式;
  • 其次调用csv.writer,将矩阵写入csv文件中。

注意:编码形式为“utf8-sig”,否则汉字容易出现乱码情况!

5. 完整代码及结果

5.1 完整代码

使用函数的形式,对爬取北京五星级酒店列表进行封装。

# 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)

5.2 运行结果

  1. 代码运行结果
    《Python3 爬取携程网[1]: 根据好评优先顺序,获取北京五星级酒店列表》

图5 代码运行截图

  1. 保存的csv文档结果
    《Python3 爬取携程网[1]: 根据好评优先顺序,获取北京五星级酒店列表》

图6 保存为csv文件截图

6. 总结

本文基于Python3,实现了对携程网页上,北京五星级酒店列表的爬取。未来工作是要完成对酒店具体详情信息进行爬取。
谢谢大家!

    原文作者:icmp_no_request
    原文地址: https://blog.csdn.net/pandalaiscu/article/details/87644235
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞