手把手教你用Python网络爬虫爬取新房数据

项目背景

大家好,我是J哥。

新房数据,对于房地产置业者来说是买房的重要参考依据,对于房地产开发商来说,也是分析竞争对手项目的绝佳途径,对于房地产代理来说,是踩盘前的重要准备。

今天J哥以 「惠民之家」 为例,手把手教你利用Python将惠州市新房数据批量抓取下来,共采集到近千个楼盘,包含楼盘名称、销售价格、主力户型、开盘时间、容积率、绿化率等 「41个字段」。数据预览如下:

后台回复**「新房」**二字,可领取本文代码。

项目目标

惠民之家首页网址:

1http://www.fz0752.com/ 2

新房列表网址:

1http://www.fz0752.com/project/list.shtml 2

选择一个新房并点击**「详情信息」**即可找到目标字段:

项目准备

软件:Pycharm

第三方库:requests,fake_useragent,lxml

网站地址:http://www.fz0752.com/

网页分析

列表页分析

打开新房列表网页,点击**「下一页」**后,网址变成:

1http://www.fz0752.com/project/list.shtml?state=&key=&qy=&area=&danjia=&func=&fea=&type=&kp=&mj=&sort=&pageNO=2 2

很显然,这是静态网页,翻页参数为**「pageNO」,区域参数为「qy」**,其余参数也很好理解,点击对应筛选项即可发现网页链接变化。咱们可以通过遍历区域和页码,将新房列表的房源URL提取下来,再遍历这些URL,抓取到每个房源的详情信息。

详情页分析

选择一个新房URL,点击进去,链接如下:

1http://newhouse.fz0752.com/fontHtml/html/project/00020170060.html 2

即这个新房的id为**「00020170060」**,再点击详情信息,链接变为:

1http://newhouse.fz0752.com/project/detail.shtml?num=20170060 2

即这个新房的**「详情信息」的id为「20170060」**,我们可以大胆假设这个id就是新房id截取的一部分。多找几个新房点击尝试,很容易验证这个规律。

反爬分析

相同的ip地址频繁访问同一个网页会有被封风险,本文采用fake_useragent,将随机生成的User-Agent请求头去访问网页,将减少ip封锁的风险。

代码实现

导入爬虫相关库,定义一个主函数,构建区域列表(不同区域对应不用的区域id),遍历并用requests去请求由区域参数和页码参数拼接的URL。这里将页码设置50上限,当遍历的某个房源URL长度为0(即不存在新房数据)时,直接break,让程序进行下一个区域的遍历,直至所有数据抓取完毕,程序停止。

1# -*- coding = uft-8 -*- 2# @Time : 2020/12/21 9:29 下午 3# @Author : J4# @File : newhouse.py 5 6import csv 7import time 8import random 9import requests 10import traceback 11from lxml import etree 12from fake_useragent import UserAgent 13 14def main(): 15 #46:惠城区,47:仲恺区,171:惠阳区,172:大亚湾,173:博罗县,174:惠东县,175:龙门县 16 qy_list = [46,47,171,172,173,174,175] 17 for qy in qy_list: #遍历区域 18 for page in range(1,50): #遍历页数 19 url = f'http://www.fz0752.com/project/list.shtml?state=&key=&qy={qy}&area=&danjia=&func=&fea=&type=&kp=&mj=&sort=&pageNO={page}' 20 response = requests.request("GET", url, headers = headers,timeout = 5) 21 print(response.status_code) 22 if response.status_code == 200: 23 re = response.content.decode('utf-8') 24 print("正在提取" + str(qy) +'第' + str(page) + "页") 25 #time.sleep(random.uniform(1, 2)) 26 print("-" * 80) 27 # print(re) 28 parse = etree.HTML(re) 29 get_href(parse,qy) 30 num = ''.join(parse.xpath('//*[@id="parent-content"]/div/div[6]/div/div[1]/div[2]/div[1]/div[2]/div[1]/div[1]/a/@href')) 31 print(len(num)) 32 if len(num) == 0: 33 break 34 35if __name__ == '__main__': 36 ua = UserAgent(verify_ssl=False) 37 headers = {"User-Agent": ua.random} 38 time.sleep(random.uniform(1, 2)) 39 main() 40

发送请求,获取新房列表网页,并解析到所有新房URL,同时将新房id替换为详情信息id。在程序运行中发现有少数新房URL不一致,因此这里做了判断,修改后可以获取完整的详情信息id,并拼接出对应的URL。

1def get_href(parse,qy): 2 items = parse.xpath('//*[@id="parent-content"]/div/div[6]/div/div[1]/div[2]/div') 3 try: 4 for item in items: 5 href = ''.join(item.xpath('./div[2]/div[1]/div[1]/a/@href')).strip() 6 print("初始href为:",href) 7 #print(len(href)) 8 if len(href) > 25: 9 href1 = 'http://newhouse.fz0752.com/project/detail.shtml?num=' + href[52:].replace(".html","") 10 else: 11 href1 = 'http://newhouse.fz0752.com/project/detail.shtml?num=' + href[15:] 12 print("详情href为:",href1) 13 try: 14 get_detail(href1,qy) 15 except: 16 pass 17 except Exception: 18 print(traceback.print_exc()) 19

打印结果如下:

详情信息URL找到后,定义一个函数去请求详情页数据,同时携带qy参数,最后将其保存到csv中。

1def get_detail(href1,qy): 2 time.sleep(random.uniform(1, 2)) 3 response = requests.get(href1, headers=headers,timeout = 5) 4 if response.status_code == 200: 5 source = response.text 6 html = etree.HTML(source) 7

开始解析详情页中的各个字段,这里用到xpath进行数据解析,由于需要解析的字段太多,高达41个,限于篇幅,以下仅给出部分字段解析代码。当然,其他字段解析基本一样。

1#项目状态 2try: 3 xmzt = html.xpath('//*[@id="parent-content"]/div/div[3]/div[3]/div[1]/div[1]/text()')[0].strip() 4except: 5 xmzt = None 6#项目名称 7try: 8 name = html.xpath('//*[@id="parent-content"]/div/div[3]/div[3]/div[1]/h1/text()')[0].strip() 9except: 10 name = None 11#项目简介 12ps = html.xpath('//*[@id="parent-content"]/div/div[3]/div[5]/div[2]/div') 13for p in ps: 14 try: 15 xmjj = p.xpath('./p[1]/text()')[0].strip() 16 except: 17 xmjj = None 18infos = html.xpath('//*[@id="parent-content"]/div/div[3]/div[5]/div[1]/div/table/tbody') 19for info in infos: 20 #行政区域 21 try: 22 xzqy = info.xpath('./tr[1]/td[1]/text()')[0].strip() 23 except: 24 xzqy = None 25 #物业类型 26 try: 27 wylx = info.xpath('./tr[2]/td[1]/text()')[0].strip() 28 except: 29 wylx = None 30 #销售价格 31 try: 32 xsjg = info.xpath('./tr[3]/td[1]/text()')[0].strip() 33 except: 34 xsjg = None 35 ······ 36 data = { 37 'xmzt':xmzt, 38 'name':name, 39 'xzqy':xzqy, 40 ······ 41 'qy':qy 42 } 43 print(data) 44

解析完数据后,将其置于字典中,打印结果如下:然后追加保存为csv:

1try: 2 with open('hz_newhouse.csv', 'a', encoding='utf_8_sig', newline='') as fp: 3 fieldnames = ['xmzt','name','xzqy',······,'qy'] 4 writer = csv.DictWriter(fp, fieldnames = fieldnames) 5 writer.writerow(data) 6except Exception: 7 print(traceback.print_exc()) 8

当然,我们也可以读取csv文件,并写入Excel:

1df = pd.read_csv("newhouse.csv",names=['name','xzqy','wylx',······,'state']) 2df = df.drop_duplicates() 3df.to_excel("newhouse.xlsx",index=False) 4

总结

  1. 本文基于Python爬虫技术,提供了一种更直观的抓取新房数据的方法。

  2. 不建议抓取太多,容易使得服务器负载,浅尝辄止即可。

  3. 如需本文完整代码,后台回复**「新房」**两个字即可获取。

-------------------********************************** End **********-------------**-----********-**********************************

往期精彩文章推荐:

  1. 反爬虫策略手把手教你使用FastAPI来限制接口的访问速率


  2. 一篇文章带你解锁Python库中操作系统级别模块psutil


  3. 盘点5种基于Python生成的个性化语音方法


欢迎各位大佬点击链接加入群聊【helloworld开发者社区】:https://jq.qq.com/?_wv=1027&k=mBlk6nzX进群交流IT技术热点。

本文转自 https://mp.weixin.qq.com/s/8xrV4JlgaUnbyp4bNYvZ-w,如有侵权,请联系删除。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

50 行代码教你爬取猫眼电影 TOP100 榜所有信息

对于Python初学者来说,爬虫技能是应该是最好入门,也是最能够有让自己有成就感的,今天,恋习Python的手把手系列,手把手教你入门Python爬虫,爬取猫眼电影TOP100榜信息,将涉及到基础爬虫架构中的HTML下载器、HTML解析器、数据存储器三大模块:HTML下载器:利用requests模块下载HTML网页;HTML解析器:利用re正则表达