此篇博客为普通方式爬取安居客租房数据一共提取出1200条,但是在进行大规模的数据爬取时,不建议使用这种方式,速度太慢是最大的诟病,在进行大规模爬取时,使用分布式爬虫是第一选择

爬取过程
一、指定爬取数据
二、设置请求头防止反爬
三、分析页面并且与网页源码进行比对
四、分析页面整理数据
五、保存到excel表中
六、使用jupyternotebook进行简单的数据分析

一、指定爬取数据

需求:
提取价格、面积、详细标题、名称、具体位置、房屋结构、装修情况

二、设置请求头

这里设置请求头依然使用最常见的 user-agent和cookie值作为反爬头,但是在实际操作中,由于爬取数据太快可能会导致ip被禁,一开始我也被封过一次。。。。。奇迹的是后来隔了一天打开之后就可以畅通无阻的爬取,但是最保险的方式还是设置一个代理ip防止被封免费的代理大家可以去快代理去尝试,土豪就除外了。

三、分析页面与源码比对

通过对源码的分析,发现页面对数字进行了一个加密。如图

接下来就要对字体进行一个解密
通过查看网页得知,网页上所有的数字都进行了加密,因此提取价格以及房屋结构首先都要对数字进行解密

第一步 分析

字体加密一般都涉及到字体文件,字体文件后面一般为 woff和ttf,字体文件可以在网页源码中找到

在这里我们看到了base64说明这些字符串都是通过base64编码过,这些字符串就是字体映射的内容

第二步 创建、打开文件,查找映射关系
1.创建文件代码

fontdata = re.findall("charset=utf-8;base64,(.*?)'\) format",html,re.S)[0]
fontent = base64.b64decode(fontdata)
f = open("t5.woff", 'wb')
f.write(fontent)
f.close()`

fontdata为bs64编码过后的字符串

2.用TTFont打开文件并保存为xml格式

 fonts = TTFont('t5.woff')fonts.saveXML('test8.xml')

3.查看文件并找到索引关系

<cmap><tableVersion version="0"/><cmap_format_4 platformID="0" platEncID="3" language="0"><map code="0x9476" name="glyph00008"/><!-- CJK UNIFIED IDEOGRAPH-9476 --><map code="0x958f" name="glyph00003"/><!-- CJK UNIFIED IDEOGRAPH-958F --><map code="0x993c" name="glyph00002"/><!-- CJK UNIFIED IDEOGRAPH-993C --><map code="0x9a4b" name="glyph00006"/><!-- CJK UNIFIED IDEOGRAPH-9A4B --><map code="0x9e3a" name="glyph00009"/><!-- CJK UNIFIED IDEOGRAPH-9E3A --><map code="0x9ea3" name="glyph00005"/><!-- CJK UNIFIED IDEOGRAPH-9EA3 --><map code="0x9f64" name="glyph00010"/><!-- CJK UNIFIED IDEOGRAPH-9F64 --><map code="0x9f92" name="glyph00001"/><!-- CJK UNIFIED IDEOGRAPH-9F92 --><map code="0x9fa4" name="glyph00004"/><!-- CJK UNIFIED IDEOGRAPH-9FA4 --><map code="0x9fa5" name="glyph00007"/><!-- CJK UNIFIED IDEOGRAPH-9FA5 --><GlyphID id="0" name="glyph00000"/><GlyphID id="1" name="glyph00001"/><GlyphID id="2" name="glyph00002"/><GlyphID id="3" name="glyph00003"/><GlyphID id="4" name="glyph00004"/><GlyphID id="5" name="glyph00005"/><GlyphID id="6" name="glyph00006"/><GlyphID id="7" name="glyph00007"/><GlyphID id="8" name="glyph00008"/><GlyphID id="9" name="glyph00009"/><GlyphID id="10" name="glyph00010"/>

列如
&#x9fa4;
&#对应code码的0 code码为x9fa4的name为glyph00004,匹配name为glyph00004的id值为4,在去匹配网页对应的数字发现需要将id值减去1,因此在写代码时提取出name最后一个数字减去1就可以匹配到数字

字体反爬代码

fontdata = re.findall("charset=utf-8;base64,(.*?)'\) format",html,re.S)[0]fontent = base64.b64decode(fontdata)f = open("t5.woff", 'wb')f.write(fontent)f.close()fonts = TTFont('t5.woff')fonts.saveXML('test8.xml')root = et.parse('test8.xml').getroot()con = root.find('cmap').find('cmap_format_4').findall('map')for i in con:names = i.attrib['name']code = i.attrib['code'].replace('0x', '&#x') + ';'c1 = re.findall(r'\d+', names)c2 = str(int(c1[0]) - 1)content = content.replace(code, c2)return content

四、分析页面整理数据

将字体解密后通过分析页面就可以提取出价格、房屋结构和面积的数据,通过xpath定位的方式定位到每一个爬取数据的位置

def lxmldata(data):datas =etree.HTML(data)list1 = []date=datas.xpath("//div[@class='list-content']//div[@class='zu-itemmod']")for i,dates in enumerate (date):dict = {}#价格price1 = re.findall('<p><strong><b class="strongbox">(.*?)</b></strong> 元/月</p>', data, re.S)price = re.findall('<p><strong><b class="strongbox">(.*?)</b></strong> 元/月</p>', data, re.S)[i]#面积size = re.findall('<b class="strongbox" style="font-weight: normal;">(.*?)</b>', data, re.S)[2:len(price1)*3:3][i]#房屋结构fangjian1 = re.findall('<b class="strongbox" style="font-weight: normal;">(.*?)</b>', data, re.S)[0:len(price1)*3:3][i]fangjian2 = re.findall('<b class="strongbox" style="font-weight: normal;">(.*?)</b>', data, re.S)[1:len(price1)*3:3][i]#详细标题title=dates.xpath(".//div[@class='zu-info']//b/text()")#名称map = dates.xpath(".//address[@class='details-item']/a/text()")#具体位置local = dates.xpath(".//address[@class='details-item']/text()")local = [x.strip() for x in local]#装修情况zhuangxiu = dates.xpath(".//p[@class='details-item bot-tag']//span[@class='cls-1']/text()")+dates.xpath(".//p[@class='details-item bot-tag']/span[@class='cls-2']/text()")+dates.xpath(".//p[@class='details-item bot-tag']/span[@class='cls-3']/text()")dict['价格']=str(fanpa1(price,data))+'元/月'dict['面积']=str(fanpa1(size,data))+'平方米'dict["详细标题"]=title[0]dict['名称']=map[0]dict["具体位置"]=local[1]dict['房间结构']=fanpa1(fangjian1,data)+'室'+fanpa1(fangjian2,data)+'厅'if len(zhuangxiu)==3:dict["装修情况"]=zhuangxiu[0]+','+zhuangxiu[1]+','+zhuangxiu[2]elif len(zhuangxiu)==2:dict["装修情况"]=zhuangxiu[0]+','+zhuangxiu[1]else:dict["装修情况"] = zhuangxiu[0]list1.append(dict)return list1

第五步 保存到excel表
设置7个字段分别为[‘价格’,‘面积’,‘详细标题’,‘名称’,‘具体位置’,‘房间结构’,‘装修情况’]
代码如下

def save(list):filename = "C:/Users/xxx/Desktop/安居客二十页.xls"book = xlwt.Workbook()sheet1=book.add_sheet("sheet1")header = ['价格','面积','详细标题','名称','具体位置','房间大小','装修情况']for i in range(len(header)):sheet1.write(0,i,header[i])j = 1for i in list:sheet1.write(j,0,i['价格'])sheet1.write(j,1,i['面积'])sheet1.write(j,2,i['详细标题'])sheet1.write(j,3,i['名称'])sheet1.write(j,4,i['具体位置'])sheet1.write(j,5,i['房间大小'])sheet1.write(j,6,i['装修情况'])j = j+1book.save(filename)print("写入成功")

list是传入的数据,list=lxmldata

总代码

import requests
from lxml import etree
import random
import time
from selenium import webdriver
import base64
import base64
import re
import xml.etree.ElementTree as et
from fontTools.ttLib import TTFont
from fontTools.ttLib import TTFont
import xlwt
#字体反扒
def fanpa1(content,html):fontdata = re.findall("charset=utf-8;base64,(.*?)'\) format",html,re.S)[0]fontent = base64.b64decode(fontdata)f = open("t5.woff", 'wb')f.write(fontent)f.close()fonts = TTFont('t5.woff')fonts.saveXML('test8.xml')root = et.parse('test8.xml').getroot()con = root.find('cmap').find('cmap_format_4').findall('map')for i in con:names = i.attrib['name']code = i.attrib['code'].replace('0x', '&#x') + ';'c1 = re.findall(r'\d+', names)c2 = str(int(c1[0]) - 1)content = content.replace(code, c2)return content
#分析页面
def lxmldata(data):datas =etree.HTML(data)list1 = []date=datas.xpath("//div[@class='list-content']//div[@class='zu-itemmod']")for i,dates in enumerate (date):dict = {}#价格price1 = re.findall('<p><strong><b class="strongbox">(.*?)</b></strong> 元/月</p>', data, re.S)price = re.findall('<p><strong><b class="strongbox">(.*?)</b></strong> 元/月</p>', data, re.S)[i]#面积size = re.findall('<b class="strongbox" style="font-weight: normal;">(.*?)</b>', data, re.S)[2:len(price1)*3:3][i]#房屋结构fangjian1 = re.findall('<b class="strongbox" style="font-weight: normal;">(.*?)</b>', data, re.S)[0:len(price1)*3:3][i]fangjian2 = re.findall('<b class="strongbox" style="font-weight: normal;">(.*?)</b>', data, re.S)[1:len(price1)*3:3][i]#详细标题title=dates.xpath(".//div[@class='zu-info']//b/text()")#名称map = dates.xpath(".//address[@class='details-item']/a/text()")#具体位置local = dates.xpath(".//address[@class='details-item']/text()")local = [x.strip() for x in local]#装修情况zhuangxiu = dates.xpath(".//p[@class='details-item bot-tag']//span[@class='cls-1']/text()")+dates.xpath(".//p[@class='details-item bot-tag']/span[@class='cls-2']/text()")+dates.xpath(".//p[@class='details-item bot-tag']/span[@class='cls-3']/text()")dict['价格']=str(fanpa1(price,data))+'元/月'dict['面积']=str(fanpa1(size,data))+'平方米'dict["详细标题"]=title[0]dict['名称']=map[0]dict["具体位置"]=local[1]dict['房间结构']=fanpa1(fangjian1,data)+'室'+fanpa1(fangjian2,data)+'厅'if len(zhuangxiu)==3:dict["装修情况"]=zhuangxiu[0]+','+zhuangxiu[1]+','+zhuangxiu[2]elif len(zhuangxiu)==2:dict["装修情况"]=zhuangxiu[0]+','+zhuangxiu[1]else:dict["装修情况"] = zhuangxiu[0]list1.append(dict)return list1
def save(list):filename = "C:/Users/孟尚宇/Desktop/安居客二十页.xls"book = xlwt.Workbook()sheet1=book.add_sheet("sheet1")header = ['价格','面积','详细标题','名称','具体位置','房间大小','装修情况']for i in range(len(header)):sheet1.write(0,i,header[i])j = 1for i in list:sheet1.write(j,0,i['价格'])sheet1.write(j,1,i['面积'])sheet1.write(j,2,i['详细标题'])sheet1.write(j,3,i['名称'])sheet1.write(j,4,i['具体位置'])sheet1.write(j,5,i['房间大小'])sheet1.write(j,6,i['装修情况'])j = j+1book.save(filename)print("写入成功")if __name__ == '__main__':headers = {"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36","cookie":"aQQ_ajkguid=C1CC68B8-4D19-287F-3644-2D367108DEC0; id58=e87rkF/LkOJmpXJnEm4JAg==; 58tj_uuid=a6d935e2-5506-4369-9370-d4081b424818; ctid=49; _ga=GA1.2.1998955085.1607386984; _gid=GA1.2.1925540573.1607386984; new_uv=2; als=0; cmctid=2053; wmda_new_uuid=1; wmda_uuid=aa760fc62c405eecb84c273b7206beed; wmda_visited_projects=%3B6289197098934; xxzl_cid=090b7011f13f44c8b3d9271ce16587b3; xzuid=ad62da25-6302-4e3e-992e-eea22f2d9d02; lps=https%3A%2F%2Fhai.zu.anjuke.com%2Ffangyuan%2Fp2%2F%3Ffrom_price%3D0%26to_price%3D2500an%7Chttps%3A%2F%2Fcallback.58.com%2F; wmda_session_id_6289197098934=1607426591062-bdd0135e-4c1f-a60c; xzfzqtoken=lbhfULbvUI2tmDmR%2By8o2XgL%2FoD%2Fi8pTDHftNbKQZZ3J9dDc2%2BiE91mVlKbcur5Hin35brBb%2F%2FeSODvMgkQULA%3D%3D","path":"/fangyuan/p2/?from_price=0&to_price=2500an"}dict2 = []dict1 = []for i in range(20):url = "https://hai.zu.anjuke.com/fangyuan/p{}/".format(i+1)resopnse=requests.get(url=url,headers=headers).content.decode('utf-8')list=lxmldata(resopnse)dict1.append(list)print("第"+str(i)+"页数据完成")for j in dict1:for k in j:dict2.append(k)save(dict2)

第六步进行简单的数据分析

分析目标:挑选出安居客2000-4000的并且面积大于100平米的房子

第一步导入数据

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
data2=pd.read_excel(r"C:\Users\xxx\Desktop\安居客二十页.xls")

第二步 找出详细标题重复值并删掉

data2.drop_duplicates(subset=['详细标题'],inplace=True)

第三步删除存在缺失值的某行

data2.dropna(how='any',axis=0)

第四步 挑选出有电梯的房子
定义一个函数如果有电梯在’房屋结构’这一字段数据中,则返回True
之后用布尔索引挑选出数据

def home(s):if '有电梯' in s:return Trueelse:return False
data2['房屋结构']=data2['房屋结构'].map(home)
data2=data2[data2['房屋结构']==1]

第五步 找出 三室一厅 三室二厅的房子

data2=data2[(data2['房间大小']=='3室2厅') | (data2['房间大小']=='3室1厅')]

第六步对价格进行分类
对价格分类 500-1000 1000-2000 2000-3000 3000 -4000 4000+

#把字符串后的汉字去掉
data2['价格']=data2['价格'].str.split("元",expand=True).iloc[:,0]
data2['价格']=data2['价格'].astype(int)
grooups=pd.cut(data2['价格'],bins=[500,1000,2000,3000,4000,10000],labels = ['500-1000','1000-2000','2000-3000','3000-4000','4000+'])
data2['价格范围']=grooups

第七步 找出价格为2000-4000的并且面积大于100平米的房子

data2= data2[(data2['价格范围']=='2000-3000')| (data2['价格范围']=='3000-4000')]
data2['面积']=data2['面积'].str.split("平",expand=True).iloc[:,0]
data2['面积']=data2['面积'].astype(float)
groups=pd.cut(data2['面积'],bins = [0,100,100000000000000],labels=['0-100','100-'])
data2['面积范围']=groups

第八步 根据序号找出对应的数据

s=data2[data2['面积范围']=='100-'].index
data=pd.read_excel(r"C:\Users\xxx\Desktop\安居客二十页.xls")
a=list(s)
a = tuple(a)
data3=data.loc[a,:]

python爬虫爬取安居客并进行简单数据分析相关推荐

  1. python爬虫爬取安居客房源信息

    爬取安居客房源信息 Xpath插件的安装 爬取重庆花溪附近的房源信息(进入正题啦~) 梳理下逻辑 爬取数据的通用流程 代码 代码的问题 & 运行时可能出现的问题 结果 数据处理部分(写给我自己 ...

  2. 爬虫爬取安居客二手房和新房信息,你是买新房还是二手的呢?

    本文主要讲解爬取安居客买房类别中的二手房和新房,将提取的信息存储在记事本中,也可以转存CSV格式或者MongoDB中. 网站HTML信息提取比较简单,没有什么特别的地方,作为爬虫入门可以让初学者快速了 ...

  3. python爬虫爬取房源_python爬虫爬取安居客房源信息

    Xpath插件的安装 链接:https://pan.baidu.com/s/1T3V11Ev8dPODa2fCRbeuCg 提取码:qvzf 将这个安装包解压缩 打开谷歌浏览器的扩展程序 ----&g ...

  4. Python爬虫爬取博客访问量

    实现功能: 查看自己活着别人CSDN中每篇博客的访问量 语言: Python3.5 用到的库: requests re 步骤: 1.找到数据源:找到一个现实所有博客的页面,在一篇博客的右上方可以点击目 ...

  5. python爬虫爬取彩票中奖数字,简单计算概率并写入Excel文件中

    一.爬取网页数据所使用到的库 1.获取网络请求requests.BeautifulSoup2.写入excel文件openpyxl.pprint.column_index_from_string注意co ...

  6. python爬取学校题库_如何使用 Python 爬虫爬取牛客网 Java 题库?

    [原文链接]http://www.changxuan.top/?p=146 由于"打怪"失败,最近一直在牛客网上刷题复习备战春招.其中有个 Java专题复习题库,我刷着刷着就想把它 ...

  7. 如何使用 Python 爬虫爬取牛客网 Java 题库?

    [原文链接]http://www.changxuan.top/?p=146 由于"打怪"失败,最近一直在牛客网上刷题复习备战春招.其中有个 Java专题复习题库,我刷着刷着就想把它 ...

  8. Python开发爬虫之BeautifulSoup解析网页篇:爬取安居客网站上北京二手房数据

    目标:爬取安居客网站上前10页北京二手房的数据,包括二手房源的名称.价格.几室几厅.大小.建造年份.联系人.地址.标签等. 网址为:https://beijing.anjuke.com/sale/ B ...

  9. Python爬虫实战-详细讲解爬取安居客房价数据

    最近在尝试用python爬取安居客房价数据,在这里给需要的小伙伴们提供代码,并且给出一点小心得. 首先是爬取之前应该尽可能伪装成浏览器而不被识别出来是爬虫,基本的是加请求头,但是这样的纯文本数据爬取的 ...

最新文章

  1. 【力扣网练习题】合并两个有序链表
  2. 《AngularJS深度剖析与最佳实践》一第1章 从实战开始
  3. LeetCode 595 Big Countries: SQL的题
  4. python基础实例-Python入门基础知识实例,值得收藏!
  5. 改动下ICTCLAS4J 0.9.1 提供了分词速度
  6. Python 基本数据类型 (一) - 整数
  7. SQL Server Transactional Replication 中的 CommitBatchSize 和 CommitBatchThreshold 属性
  8. MySQL:too many connections
  9. gitlab 删除仓库
  10. 中国内容推荐引擎市场趋势报告、技术动态创新及市场预测
  11. linux命令行模式连接网络,在Linux环境命令行中实现Wifi 连接的方法
  12. python中定义的类的方法调用老出现missing 1 postional argument 或者self的解决办法
  13. Redis 经典 必问21问,BAT面试都会问,你会回答吗?
  14. linux渗透win7的时候显示445,Win7如何简单的关闭445端口及445端口入侵详解
  15. 3D图形学基础 基本概念
  16. proe常用c语言语句,带你轻松搞懂Proe条件语句
  17. 酷冷战神 先手致胜:腾讯ROG游戏手机6为游戏而生
  18. 特种部队小组2+蒲公英联机平台联机教程
  19. 随心下载网页中嵌套的视频(各大视频网站并不适用)
  20. 20201124 fpga程序的下载

热门文章

  1. c语言宏定义(c语言宏定义是什么意思)
  2. 阈值、阙值 有没有阀值?
  3. 我的世界服务器怎么修改id,我的世界端游怎么改名字
  4. [转帖]改变无数人人生的32句实话[ChaseDream论坛]
  5. 项目中Spring Security 整合Spring Session实现记住我功能
  6. 笔记本linux蓝牙驱动怎么安装程序,如何安装蓝牙设备的驱动程序
  7. Dubbo封装异常处理Filter报AppResponse represents an concrete business response解决方案
  8. keepalive (1)
  9. pr图形模板预设怎么使用_PR怎样安装动态图形模板?怎样调用Mogrt预设?Premiere导入MOGRTs预设完整教程...
  10. c语言如何小写转换为大写字母,c语言怎么将小写转换为大写