实战:基于链家网二手房数据解析任务
页面:https://bd.ke.com/ershoufang/
获取如下信息:
- 标题
- 位置
- 房屋信息
- 关注人数 / 发布时间
- 房屋总价
- 房屋单价
- 备注信息
1.导入库
import pandas as pd
import requests
import parsel
import re #使用正则表达式时要用到的库
import time
2.获取URL
url = 'https://bd.ke.com/ershoufang/'
3.添加headers
headers = {
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'
}
headers在下方获取:
4.发起请求
r = requests.get(url, headers=headers)
5.解析网页
html = parsel.Selector(r.text) #将其实例化成一个r.text,Selector对象为html
6.获取标题
title = html.xpath('//div[@class="info clear"]/div[@class="title"]/a/text()').extract() #.extarct()用来提取获取的标签里面的内容
print(title)
结果如下图所示:
7.获取位置
position = html.xpath('//div[@class="info clear"]//div[@class="positionInfo"]//a/text()').extract()
结果如下图所示:
8.获取房屋信息
house_info1 = html.xpath('//div[@class="info clear"]//div[@class="houseInfo"]/text()').extract()
house_info = [re.sub('\s', '', i) for i in house_info1]
house_info
这样获得的房屋信息长度是60,而其他的信息长度为30
可以使用以下的方法去除那些空行
#第一种——获取房屋信息
house_info = [re.sub('\s', '', i) for i in html.xpath('//li[@class="clear"]//div[@class="houseInfo"]/text()[2]').extract()]
house_info
结果如下图所示:
house_info = [re.search(r'houseIcon"></span>(.*?)</div>', i, re.S).group(1)
for i in html.xpath('//li[@class="clear"]//div[@class="houseInfo"]').extract()]
house_info_2 = [re.sub('\s', '', i) for i in house_info]
house_info_2
结果如下图所示:
9.获取关注信息
follow_info = [re.sub('\s', '', i) for i in html.xpath('//li[@class="clear"]//div[@class="followInfo"]/text()[2]').extract()]
结果如下图所示:
10.获取房屋总价
以下两种方法都可以
#获取房屋总价
#由于房价是由span标签和其下面的文本内容组成的,有两种方式
#第一种——将数字和单位万进行拼接
total_price = [i+'万' for i in html.xpath('//div[@class="info clear"]//div[@class="totalPrice"]/span/text()').extract()]
结果如下图所示:
#第二种——使用正则表达式
#'.'点表示匹配任意字符
#'*'星表示匹配零次或多次
#'?'问号表示非贪婪模式
total_price = [''.join(re.findall(r'<span>(.*?)</span>(.*?)</div>', i)[0])
for i in html.xpath('//div[@class="info clear"]//div[@class="totalPrice"]').extract()]
total_price
结果如下图所示:
11.获取房屋单价
unit_price = html.xpath('//div[@class="info clear"]//div[@class="unitPrice"]/span/text()').extract()
结果如下图所示:
12.获取备注信息
tag_info = [' | '.join(re.findall(r'[\u4e00-\u9fa5]+', i))
for i in html.xpath('//div[@class="info clear"]//div[@class="tag"]').extract()]
13.将上述过程封装成函数——获取1页信息
# 将上述过程封装成函数
def get_lianjia_one_page(url):
"""功能:给定链家网二手房地址,获取一页的信息"""
#添加headers
headers = {
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'
}
#发起请求
r = requests.get(url, headers=headers)
# 解析网页
html = parsel.Selector(r.text)
# 获取信息
title = html.xpath('//div[@class="info clear"]/div[@class="title"]/a/text()').extract()
position = html.xpath('//div[@class="info clear"]//div[@class="positionInfo"]//a/text()').extract()
house_info = [re.sub('\s', '', i) for i in html.xpath('//li[@class="clear"]//div[@class="houseInfo"]/text()[2]').extract()]
follow_info = [re.sub('\s', '', i) for i in html.xpath('//li[@class="clear"]//div[@class="followInfo"]/text()[2]').extract()]
total_price = [''.join(re.findall(r'<span>(.*?)</span>(.*?)</div>', i)[0])
for i in html.xpath('//div[@class="info clear"]//div[@class="totalPrice"]').extract()]
unit_price = html.xpath('//div[@class="info clear"]//div[@class="unitPrice"]/span/text()').extract()
tag_info = [' | '.join(re.findall(r'[\u4e00-\u9fa5]+', i))
for i in html.xpath('//div[@class="info clear"]//div[@class="tag"]').extract()]
# 保存信息
df_one = pd.DataFrame({
'title': title,
'position': position,
'house_info': house_info,
'follow_info': follow_info,
'total_price': total_price,
'unit_price': unit_price,
'tag_info': tag_info
})
return df_one
# 获取URL
url = 'https://bd.ke.com/ershoufang/'
# 调用上面的函数
df_one = get_lianjia_one_page(url)
df_one.head()
之前得到的是一页的数据,现在要得到多页数据
14.获取多页信息
# 多页面
def get_lianjia_100_page(city_name, page_num_all):
"""
功能:给定城市名,获取100页的信息
"""
df_all = pd.DataFrame()
# 构建URL地址
for page_num in range(page_num_all):
try:
url = 'https://{}.ke.com/ershoufang/pg{}/'.format(city_name, page_num+1)
# 调用函数
df_one = get_lianjia_one_page(url)
# 循环追加
df_all = df_all.append(df_one, ignore_index=True)
# 打印进度
print('我正在获取第{}页的信息'.format(page_num+1), end='\r')
# 休眠一秒
time.sleep(1)
except Exception as e:
break
return df_all
df_all = get_lianjia_100_page(city_name='bd', page_num_all=5)
df_all.head()