python爬取链家二手房信息方便对比和筛选决策

本文最后更新于 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内容就是文章开头所展示的了。

高级

如果你有时间还可以更加细化,增加价格走势。
具体实现就是建一个数据库,每个房子是一个记录,记录每个日期下该房子的挂牌价,然后就能画出房价与时间的​走势图了。​
由于时间有限,我没有进行该项分析。

提示

我写这个程序为了方便自己更高效筛选房源,找到满意的房子。
此程序仅供个人学习使用,切忌频繁爬取给官方服务器造成压力。
一切法律后果自负。

其他

回复“房源爬取”获取完整程序文件。

最后祝大家能找到适合自己的好房子。