使用Python解决清明出游选房子的住宿问题

清明节马上到了,很久没出来旅游的我早早就订了机票准备嗨皮去了微笑

然而选房子时候发现了Airbnb这个神奇的网站(我不是在打广告微笑),觉得上面房子还不错。但是!!!添加了选房条件竟然还有三百多条符合条件的信息让我这个懒的去挑选的人相当崩溃,于是就想用自己学了不到一周的Python来把这些数据爬下来,嘿嘿嘿~~~


使用的Python版本是3.6.4
编译器是Pycharm


首先打开网页选好条件之后 F12 打开 -->开发者模式-->NetWork

选第一条交易记录,将请求头以及请求参数都复制过来

headers = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'zh-CN,zh;q=0.8',
    'Cache-Control': 'max-age=0',
    'Connection': 'keep-alive',
    'Host': 'zh.airbnb.com',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/61.0.3163.79 Safari/537.36'
}

query_parameters = {
    'query': '重庆',
    'checkin': '2018-03-28',
    'checkout': '2018-03-31',
    'place_id': 'ChIJQ0_m87o0kzYRIbOI3BaGn94',
    'guests': '1',
    'adults': '2',
    'pets': 'false',
    'refinement_paths[]': '/homes',
    'allow_override[]': '',
    'ib': 'true',
    'room_types[]': 'Entire home/apt',
    'min_beds': '2',
    's_tag': 'bryg534D',
    'section_offset': '0'  # 用于分页的参数
}

注意分页的参数是根据网页上下一页的按钮找到的


之后就是正常的使用requests获取页面信息,使用BeautifulSoup来解析页面

# 获取html页面
def get_html(url):
    time_out = random.choice(range(80, 180))
    while True:
        try:
            html = requests.get(url=url, params=query_parameters, headers=headers, timeout=time_out)
            html.encoding = "utf-8"
            print(html.url)
        except socket.timeout as e:
            print('1', e)
            time.sleep(random.choice(range(8, 15)))
        except socket.error as e:
            print('2', e)
            time.sleep(random.choice(range(20, 60)))
        except http.client.BadStatusLine as e:
            print('3', e)
            time.sleep(random.choice(range(30, 80)))
        except http.client.IncompleteRead as e:
            print('4', e)
            time.sleep(random.choice(range(5, 15)))
        return html.text


# 获取房源分页的总页数
def get_pages(soup):
    li = soup.find_all('li', {'class': '_1am0dt'})  # 找到分页的li
    nums_div = li[-1].find('div', {'class': '_1bdke5s'})  # 最后一个li中的div内容就是总页数
    return nums_div.text


def get_resource(soup, result):
    details = soup.find_all('div', {'class': '_saba1yg'})  # 几室几厅
    titles = soup.find_all('div', {'class': '_1i196euk'})  # 房源标题
    prices = soup.find_all('span', {'class': '_l8zgil6'})  # 房子价格
    for i, title in enumerate(titles):
        temp = [title.text, details[i].text, prices[2 * i].text]  # 价格有两个{'class': '_l8zgil6'}的span,后面那个不用因此取偶数倍i
        result.append(temp)
    return result

之后再有一个将最终的数据写入到Excel表格中的方法(使用自带的csv库)

def write_data(data, name):
    with open(name, 'w', errors='ignore', newline='') as f:
        f_csv = csv.writer(f)
        f_csv.writerows(data)

最终就是编写main方法了  啦啦啦啦啦。。。

# 全局变量
final = []

if __name__ == '__main__':
    url = "https://zh.airbnb.com/s/%E9%87%8D%E5%BA%86/homes"    # 网站是Airbnb,准备去重庆玩发现的一个提供住宿信息的网站
    html_text = get_html(url)
    pages = get_pages(BeautifulSoup(html_text, 'lxml'))

    for i in range(0, int(pages)):  # 页数从零开始
        query_parameters['section_offset'] = str(i)  # 观察页面发现分页根据get的参数section_offset来决定
        html_text = get_html(url)   # 修改get参数后继续请求页面
        get_resource(BeautifulSoup(html_text, 'lxml'), final)   # 往final这个list中不断append数据

    write_data(final, 'file\house.csv')  # 文件保存在该目录下的file文件夹中(手动创建file文件夹)


以下是完整代码,第一次发博客,还是一个编程新手用看了没几天Python写的,感觉自己要上天了呢,哈哈哈哈。。。

# author : Josh
# coding : utf-8

import csv
import random
import time
import socket
import http.client

import requests
from bs4 import BeautifulSoup

headers = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'zh-CN,zh;q=0.8',
    'Cache-Control': 'max-age=0',
    'Connection': 'keep-alive',
    'Host': 'zh.airbnb.com',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/61.0.3163.79 Safari/537.36'
}

query_parameters = {
    'query': '重庆',
    'checkin': '2018-03-28',
    'checkout': '2018-03-31',
    'place_id': 'ChIJQ0_m87o0kzYRIbOI3BaGn94',
    'guests': '1',
    'adults': '2',
    'pets': 'false',
    'refinement_paths[]': '/homes',
    'allow_override[]': '',
    'ib': 'true',
    'room_types[]': 'Entire home/apt',
    'min_beds': '2',
    's_tag': 'bryg534D',
    'section_offset': '0'  # 用于分页的参数
}


# 获取html页面
def get_html(url):
    time_out = random.choice(range(80, 180))
    while True:
        try:
            html = requests.get(url=url, params=query_parameters, headers=headers, timeout=time_out)
            html.encoding = "utf-8"
            print(html.url)
        except socket.timeout as e:
            print('1', e)
            time.sleep(random.choice(range(8, 15)))
        except socket.error as e:
            print('2', e)
            time.sleep(random.choice(range(20, 60)))
        except http.client.BadStatusLine as e:
            print('3', e)
            time.sleep(random.choice(range(30, 80)))
        except http.client.IncompleteRead as e:
            print('4', e)
            time.sleep(random.choice(range(5, 15)))
        return html.text


# 获取房源分页的总页数
def get_pages(soup):
    li = soup.find_all('li', {'class': '_1am0dt'})  # 找到分页的li
    nums_div = li[-1].find('div', {'class': '_1bdke5s'})  # 最后一个li中的div内容就是总页数
    return nums_div.text


def get_resource(soup, result):
    details = soup.find_all('div', {'class': '_saba1yg'})  # 几室几厅
    titles = soup.find_all('div', {'class': '_1i196euk'})  # 房源标题
    prices = soup.find_all('span', {'class': '_l8zgil6'})  # 房子价格
    for i, title in enumerate(titles):
        temp = [title.text, details[i].text, prices[2 * i].text]  # 价格有两个{'class': '_l8zgil6'}的span,后面那个不用因此取偶数倍i
        result.append(temp)
    return result


def write_data(data, name):
    with open(name, 'w', errors='ignore', newline='') as f:
        f_csv = csv.writer(f)
        f_csv.writerows(data)


# 全局变量
final = []

if __name__ == '__main__':
    url = "https://zh.airbnb.com/s/%E9%87%8D%E5%BA%86/homes"    # 网站是Airbnb,准备去重庆玩发现的一个提供住宿信息的网站
    html_text = get_html(url)
    pages = get_pages(BeautifulSoup(html_text, 'lxml'))

    for i in range(0, int(pages)):  # 页数从零开始
        query_parameters['section_offset'] = str(i)  # 观察页面发现分页根据get的参数section_offset来决定
        html_text = get_html(url)   # 修改get参数后继续请求页面
        get_resource(BeautifulSoup(html_text, 'lxml'), final)   # 往final这个list中不断append数据

    write_data(final, 'file\house.csv')  # 文件保存在该目录下的file文件夹中(手动创建file文件夹)



全剧终~~

因为对Python语法都不是很熟悉的我只能边百度查资料边做笔记去写,全程耗时两个多小时,写出来运行成功那一瞬间高兴的不得了 ,哈哈哈哈。 也许这就是编程的魅力吧,加油!


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值