本文最后更新于 2024年7月24日。
背景
最近在看二手房。
官网筛选房源
先确定自己的需求进行简单筛选
我定的需求是丰台区,因为这里便宜并且位置距离市中心近。价格两百万以下,面积四十平以上,用途是普通住宅,位置在四环内。筛选界面如下:
搜索结果按照总价排序如下:
把房源信息整理成excel
为了更加方便对比,要让关键信息一览无余才行。所以想着把筛选结果爬取出来,列出自己关注的信息。
爬取出来的效果图如下:
信息很多,为了让信息更加明了和有层次感,我简单增加了数据透视表,效果如下。
在右侧可以随时增减字段
爬取的实现过程
下面介绍一下爬取的实现过程。
首先引入需要的库
import requests
from bs4 import BeautifulSoup
import pandas as pd
import random
import time
from datetime import datetime
import re
接着获取时间戳,为了用于文件名,不是必须项
# 获取当前时间
now = datetime.now()
# 格式化为特定格式的字符串
formatted_time = now.strftime("%Y%m%d%H%M%S")
然后定义请求头
user_agents = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36",
"Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1"
]
referers = [
"https://www.google.com/",
"https://www.baidu.com/",
"https://www.bing.com/"
]
headers = {
"User-Agent": random.choice(user_agents),
"Referer": random.choice(referers)
}
这个是身份信息,为了模拟浏览器,不然很容易被服务器屏蔽,获取不到数据。
写获取单页数据的函数
def fetch_data(page_number):
url = f"https://bj.lianjia.com/ershoufang/fengtai/pg{page_number}co21sf1p1cl40630001cl40630002cl40630003ba40ea10000/"#丰台,四环内,普通住宅,40平以上,200w以下
response = requests.get(url, headers=headers)
if response.status_code != 200:
print(f"请求失败,状态码:{response.status_code}")
return []
print('response:',response)
soup = BeautifulSoup(response.text, 'html.parser')
rows = []
for house_info in soup.find_all("li", {"class": "clear LOGVIEWDATA LOGCLICKDATA"}):
row = {}
# 使用您提供的类名来获取数据
row['区域'] = house_info.find("div", {"class": "positionInfo"}).get_text() if house_info.find("div", {
"class": "positionInfo"}) else None
row['房型'] = house_info.find("div", {"class": "houseInfo"}).get_text() if house_info.find("div", {
"class": "houseInfo"}) else None
row['关注'] = house_info.find("div", {"class": "followInfo"}).get_text() if house_info.find("div", {
"class": "followInfo"}) else None
try:
row['发布时长'] = row['关注'].split('/')[1]
except:
row['发布时长'] = None
# 使用正则表达式查找所有的数字
row['关注'] = re.findall(r'\d+', row['关注'])[0]
row['单价'] = house_info.find("div", {"class": "unitPrice"}).get_text() if house_info.find("div", {
"class": "unitPrice"}) else None
row['单价'] = re.findall(r'\d+', row['单价'].replace(',', ''))[0] #.replace(',', '')用于移除数字中的千位分隔符
row['总价'] = house_info.find("div", {"class": "priceInfo"}).get_text() if house_info.find("div", {
"class": "priceInfo"}) else None
row['总价'] = re.findall(r'\d+', row['总价'])[0]
row['标题'] = house_info.find("div", {"class": "title"}).get_text() if house_info.find("div", {
"class": "title"}) else None
# 获取div标签内的a标签的href属性,确保每一步都检查None
link = None
div_title = house_info.find("div", {"class": "title"})
if div_title:
a_tag = div_title.find("a")
if a_tag:
link = a_tag.get("href")
# 将链接赋值给DataFrame的某行的'链接'列
row['链接'] = link
rows.append(row)
return rows
实现远离是爬取链接中的网页,然后用bs获取网页中我们需要的信息。
其中url内容是我们在网站中筛选后地址栏中网址简单变换后得到。
例如我筛选后的网址是
https://bj.lianjia.com/ershoufang/fengtai/co21sf1p1cl40630001cl40630002cl40630003ba40ea10000/
调整后的url:
url = f"https://bj.lianjia.com/ershoufang/fengtai/pg{page_number}co21sf1p1cl40630001cl40630002cl40630003ba40ea10000/"
变化是在原始url中增加了pg{page_number}
这个是为了爬取所符合筛选条件的页面。
主函数
# 主函数
def main():
all_data = []
for i in range(1, 6): # 爬取前10页数据作为示例
print(f"正在爬取第{i}页...")
all_data += fetch_data(i)
# 等待3秒
time.sleep(3)
# 保存数据到Excel
df = pd.DataFrame(all_data)
filename = 'lianjia_data' + formatted_time + '.xlsx'
df.to_excel(filename, index=False)
print(f"数据已保存到 {filename}")
if __name__ == "__main__":
main()
原理是调用单页爬取函数获取信息,然后整合到一起写入excel文件。
需要重点关注的是循环语句轮数:
for i in range(1, 6):
range后面括号中的1一般不用动,表示从第一页开始爬取。
后面的6就要根据实际情况进行设置了。
筛选后把网页拉到最底部看页数最大值,然后加一就是range函数第二个数字应该填写的内容。我这里一共有5页,所以填写数字6.
运行日志
保存的excel内容就是文章开头所展示的了。
高级
如果你有时间还可以更加细化,增加价格走势。
具体实现就是建一个数据库,每个房子是一个记录,记录每个日期下该房子的挂牌价,然后就能画出房价与时间的走势图了。
由于时间有限,我没有进行该项分析。
提示
我写这个程序为了方便自己更高效筛选房源,找到满意的房子。
此程序仅供个人学习使用,切忌频繁爬取给官方服务器造成压力。
一切法律后果自负。
其他
回复“房源爬取”获取完整程序文件。
最后祝大家能找到适合自己的好房子。