清明节马上到了,很久没出来旅游的我早早就订了机票准备嗨皮去了
然而选房子时候发现了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语法都不是很熟悉的我只能边百度查资料边做笔记去写,全程耗时两个多小时,写出来运行成功那一瞬间高兴的不得了 ,哈哈哈哈。 也许这就是编程的魅力吧,加油!