Python爬虫抓取透明房产网房源信息

闲来无事,想看看成都透明房产网(esf.cdfgj.gov.cn)的房源信息。
成都透明房产网的主办单位是成都房地产信息档案中心(成都市城乡房产管理局直属单位),运营机构和技术支持是成都房联电子信息有限公司。成都透明房产网是房管局的公示平台,其产权性质、备案价格等信息相对可靠,但更新较慢。

可以看到,网页代码的结构还是比较简单,哪些信息是有价值的呢?
最有价值的肯定是房源的均价和总价了,其他信息比如区位、面积等其次。
下面直接开干,爬虫的大概思路是,先获取总页码,开多线程,取出页码获取房源,存储。
以下为主要部分源码:

#获取成都透明房产网信息
def get_cdfgj(page):
    url = "http://esf.cdfgj.gov.cn/search"
    querystring = {"page":page}
    headers = {
        'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        'Accept-Encoding': "gzip, deflate",
        'Accept-Language': "zh-CN,zh;q=0.9,zh-TW;q=0.8",
        'Cache-Control': "no-cache",
        'Connection': "keep-alive",
        'Host': "esf.cdfgj.gov.cn",
        'Upgrade-Insecure-Requests': "1",
        'User-Agent': random.choice(USER_AGENTS),
        'page': str(page),
        }
    try:
        response = requests.request("GET", url, headers=headers, params=querystring)
    except:
        print('无法打开链接')
        return []
    response.encoding = response.apparent_encoding  # 编码
    soup = BeautifulSoup(response.text, "lxml")  # BeautifulSoup解析
    list = soup.find(attrs={'class': 'pan-con'})  # 这是房价部分
    pan_item=list.find_all(attrs={'class': 'pan-item'})
    return_info=[]#返回数据,当前页的所有房产信息
    for i in pan_item:#遍历
        tit=i.find('h2').text.strip()#标题
        print('正在处理:',tit)
        a=i.find('a').get('href')#链接
        nr=i.find(attrs={'class': 'p_hx'}).text
        nr=re.sub('\s', '', nr) #内容
        hprice = i.find(attrs={'class': 'h-price'}).text.strip()  # 均价
        zprice = i.find(attrs={'class': 'total-price'}).text.strip()  # 总价
        try:
            hprice=float(hprice.replace('元/平',''))#去掉字符「元/平」,str数据转换成float
        except:
            pass
        try:
            zprice=float(zprice.replace('万',''))#去掉字符「万」,str数据转换成float
        except:
            pass
        yhy=i.find(attrs={'class': 'yhy'}).text.strip()#核验否
        ynum=i.find(attrs={'class': 'ynum'}).text.strip()#编号
        return_info.append({'标题':tit,'url':a,'内容':nr,'均价':hprice,'总价':zprice,'核验':yhy,'编号':ynum})
    return return_info#返回格式化的数据,「return_info」类型为 list,遍历后得到dict数据,可直接入库
#获取总页码
def get_page():
    url = "http://esf.cdfgj.gov.cn/search"
    querystring = {"page": 1}
    headers = {
        'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        'Accept-Encoding': "gzip, deflate",
        'Accept-Language': "zh-CN,zh;q=0.9,zh-TW;q=0.8",
        'Cache-Control': "no-cache",
        'Connection': "keep-alive",
        'Cookie': "route=ef54ba21a4071e92ee57efe2b12729b8; JSESSIONID=Agx9VFNi1QAK06+DmDSvTzZi.undefined",
        'Host': "esf.cdfgj.gov.cn",
        'Upgrade-Insecure-Requests': "1",
        'User-Agent': random.choice(USER_AGENTS),
        'page': str(1)
    }
    try:
        response = requests.request("GET", url, headers=headers, params=querystring)
    except:
        print('无法打开链接')
        return 0
    response.encoding = response.apparent_encoding  # 编码
    soup = BeautifulSoup(response.text, "lxml")  # 解析
    list = soup.find(attrs={'class': 'pages'})  # 房价部分
    a=list.find_all('a')
    try:
        page=int(a[-2].text.strip())
    except:
        print('页码获取失败')
        return 0
    return page
#多线程,各线程从GlobalQueue中取出页码,再爬取
class myThread (threading.Thread):
    def __init__(self, threadID):
        threading.Thread.__init__(self)
        self.threadID = threadID
    def run(self):
        while not GlobalQueue.empty():
            p=GlobalQueue.get()#取出一页,去获取信息
            print('线程:',self.threadID,'正在处理页码:',p,'\n')
            info=get_cdfgj(p)#返回的是一个 list,遍历直接入库
            for i in info:
                if i['编号'] not in bh:#去重,该房源编号不存在于数据库
                    i.update({'记录时间': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())})#增加记录时间
                    db.insert(i)#写入数据库
                else:
                    print(i['编号'],'该编号房源已存在')
if __name__ == '__main__':
    page=get_page()#获得总页码
    for i in range(page):#把所有页码装入队列
        GlobalQueue.put(i)
    print(page,'页装入完毕\n')
    conn = MongoClient('127.0.0.1', 27017)
    db = conn.cdfgj_gov_cn_fangjia  # 连接mydb数据库,没有则自动创建
    today = time.strftime("%Y%m%d")  # 获取当前日期
    db = db[today]  # 以当前日期命名集合
    bh=[]#房源编号,防重复插入
    for i in db.find():
        bh.append(i['编号'])
    print('编码获取完毕,表内有',len(bh),'条数据')
    thread = []#多线程
    for i in range(20):
        thread.append(myThread(i))
    for i in range(20):
        thread[i].start()

数据结果如下:

注:爬虫数据全部来源于公开页面。本文内容仅作学习研究之用,任何单位或个人不得用于非法用途。