数据分析实战(7):*敏*感*词*教你Python爬取新房数据
优采云 发布时间: 2022-05-01 07:22数据分析实战(7):*敏*感*词*教你Python爬取新房数据
http://www.fz0752.com/project/list.shtml?state=&key=&qy=&area=&danjia=&func=&fea=&type=&kp=&mj=&sort=&pageNO=2<br />
很显然,这是静态网页,翻页参数为「pageNO」,区域参数为「qy」,其余参数也很好理解,点击对应筛选项即可发现网页链接变化。
咱们可以通过遍历区域和页码,将新房列表的房源URL提取下来,再遍历这些URL,抓取到每个房源的详情信息。
详情页分析
选择一个新房URL,点击进去,链接如下:
http://newhouse.fz0752.com/fontHtml/html/project/00020170060.html<br />
即这个新房的id为「」,再点击详情信息,链接变为:
http://newhouse.fz0752.com/project/detail.shtml?num=20170060<br />
即这个新房的「详情信息」的id为「20170060」,我们可以大胆假设这个id就是新房id截取的一部分。多找几个新房点击尝试,很容易验证这个规律。
反爬分析
相同的ip地址频繁访问同一个网页会有被封风险,本文采用fake_useragent,将随机生成的User-Agent请求头去访问网页,将减少ip封锁的风险。
代码实现
导入爬虫相关库,定义一个主函数,构建区域列表(不同区域对应不用的区域id),遍历并用requests去请求由区域参数和页码参数拼接的URL。这里将页码设置50上限,当遍历的某个房源URL长度为0(即不存在新房数据)时,直接break,让程序进行下一个区域的遍历,直至所有数据抓取完毕,程序停止。
# -*- coding = uft-8 -*-<br /># @Time : 2020/12/21 9:29 下午<br /># @Author : J哥<br /># @File : newhouse.py<br /><br />import csv<br />import time<br />import random<br />import requests<br />import traceback<br />from lxml import etree<br />from fake_useragent import UserAgent<br /><br />def main():<br /> #46:惠城区,47:仲恺区,171:惠阳区,172:大亚湾,173:博罗县,174:惠东县,175:龙门县<br /> qy_list = [46,47,171,172,173,174,175]<br /> for qy in qy_list: #遍历区域<br /> for page in range(1,50): #遍历页数<br /> url = f'http://www.fz0752.com/project/list.shtml?state=&key=&qy={qy}&area=&danjia=&func=&fea=&type=&kp=&mj=&sort=&pageNO={page}'<br /> response = requests.request("GET", url, headers = headers,timeout = 5)<br /> print(response.status_code)<br /> if response.status_code == 200:<br /> re = response.content.decode('utf-8')<br /> print("正在提取" + str(qy) +'第' + str(page) + "页")<br /> #time.sleep(random.uniform(1, 2))<br /> print("-" * 80)<br /> # print(re)<br /> parse = etree.HTML(re)<br /> get_href(parse,qy)<br /> 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'))<br /> print(len(num))<br /> if len(num) == 0:<br /> break<br /><br />if __name__ == '__main__':<br /> ua = UserAgent(verify_ssl=False)<br /> headers = {"User-Agent": ua.random}<br /> time.sleep(random.uniform(1, 2))<br /> main()<br />
发送请求,获取新房列表网页,并解析到所有新房URL,同时将新房id替换为详情信息id。在程序运行中发现有少数新房URL不一致,因此这里做了判断,修改后可以获取完整的详情信息id,并拼接出对应的URL。
def get_href(parse,qy):<br /> items = parse.xpath('//*[@id="parent-content"]/div/div[6]/div/div[1]/div[2]/div')<br /> try:<br /> for item in items:<br /> href = ''.join(item.xpath('./div[2]/div[1]/div[1]/a/@href')).strip()<br /> print("初始href为:",href)<br /> #print(len(href))<br /> if len(href) > 25:<br /> href1 = 'http://newhouse.fz0752.com/project/detail.shtml?num=' + href[52:].replace(".html","")<br /> else:<br /> href1 = 'http://newhouse.fz0752.com/project/detail.shtml?num=' + href[15:]<br /> print("详情href为:",href1)<br /> try:<br /> get_detail(href1,qy)<br /> except:<br /> pass<br /> except Exception:<br /> print(traceback.print_exc())<br />
打印结果如下:
详情信息URL找到后,定义一个函数去请求详情页数据,同时携带qy参数,最后将其保存到csv中。
def get_detail(href1,qy):<br /> time.sleep(random.uniform(1, 2))<br /> response = requests.get(href1, headers=headers,timeout = 5)<br /> if response.status_code == 200:<br /> source = response.text<br /> html = etree.HTML(source)<br />
开始解析详情页中的各个字段,这里用到xpath进行数据解析,由于需要解析的字段太多,高达41个,限于篇幅,以下仅给出部分字段解析代码。当然,其他字段解析基本一样。
#项目状态<br />try:<br /> xmzt = html.xpath('//*[@id="parent-content"]/div/div[3]/div[3]/div[1]/div[1]/text()')[0].strip()<br />except:<br /> xmzt = None<br />#项目名称<br />try:<br /> name = html.xpath('//*[@id="parent-content"]/div/div[3]/div[3]/div[1]/h1/text()')[0].strip()<br />except:<br /> name = None<br />#项目简介<br />ps = html.xpath('//*[@id="parent-content"]/div/div[3]/div[5]/div[2]/div')<br />for p in ps:<br /> try:<br /> xmjj = p.xpath('./p[1]/text()')[0].strip()<br /> except:<br /> xmjj = None<br />infos = html.xpath('//*[@id="parent-content"]/div/div[3]/div[5]/div[1]/div/table/tbody')<br />for info in infos:<br /> #行政区域<br /> try:<br /> xzqy = info.xpath('./tr[1]/td[1]/text()')[0].strip()<br /> except:<br /> xzqy = None<br /> #物业类型<br /> try:<br /> wylx = info.xpath('./tr[2]/td[1]/text()')[0].strip()<br /> except:<br /> wylx = None<br /> #销售价格<br /> try:<br /> xsjg = info.xpath('./tr[3]/td[1]/text()')[0].strip()<br /> except:<br /> xsjg = None<br /> ······<br /> data = {<br /> 'xmzt':xmzt,<br /> 'name':name,<br /> 'xzqy':xzqy,<br /> ······<br /> 'qy':qy<br /> }<br /> print(data)<br />
解析完数据后,将其置于字典中,打印结果如下:
然后追加保存为csv:
try:<br /> with open('hz_newhouse.csv', 'a', encoding='utf_8_sig', newline='') as fp:<br /> fieldnames = ['xmzt','name','xzqy',······,'qy']<br /> writer = csv.DictWriter(fp, fieldnames = fieldnames)<br /> writer.writerow(data)<br />except Exception:<br /> print(traceback.print_exc())<br />
当然,我们也可以读取csv文件,并写入Excel:
df = pd.read_csv("newhouse.csv",names=['name','xzqy','wylx',······,'state'])<br />df = df.drop_duplicates()<br />df.to_excel("newhouse.xlsx",index=False)<br />
总结
本文基于Python爬虫技术,提供了一种更直观的抓取新房数据的方法。
不建议抓取太多,容易使得服务器负载,浅尝辄止即可。