有段时间 群里聊到了自如网站的价格用采集器采集不了,所以自己想看看什么原因导致的
参考链接:http://sz.ziroom.com/z/vr/61127945.html
我们查看源代码网页,发现代码中并未含有价格信息,而是通过一张随机的图片,再利用Css样式偏移组合得到价格
image.png我们查看ajax加载,发现info?id=61127945&house_id=60179749这一条加载中包含了价格的相关信息,具体如下图所示
image.png这样我们就得到了价格的坐标,所以我们可以考虑使用pytesseract来识别图片中的数字,然后根据价格索引得到价格
那么如何请求这个ajax呢? 我们观察一下请求信息
image.png我们可以通过访问网页的URL轻易获取到房间ID,那么房子的ID怎么获取呢?我们去源代码找一找
image.png如何获取这个网页呢? 没什么难度 直接get你当前访问的URL就行了
image.png我们来捋一捋我们要做的事情:
- 先get网页url,利用正则获取到房间ID和房子ID
- 根据得到的2个ID,请求ajax,得到价格图片和价格索引信息
- 利用pytesseract 识别图中数字信息,根据价格索引得到最终的房价
网页分析到这里就结束了,接下里我们看代码
image.png所需要使用的包
image.pngget当前网页,返回房间ID和房子ID
image.png根据2个ID 请求ajax,返回图片和索引
image.png核心部分,使用pytesseract,识别图片信息,并根据价格索引,返回正确的房价
我们来跑一跑这个程序试试看!
image.png程序源码:
from PIL import Image
import pytesseract
import requests
import re
import time
class ZrPrApi(object):
'''
通过给定URL,爬取自如网站房源价格
'''
# 网络请求初始化
headers = {
# 'Host': 'sz.ziroom.com',
'Referer': 'http://sz.ziroom.com',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
def get_houseID(self, url, S):
'''
根据给定的URL,解析对应的houseID和roomID
'''
res = S.get(url, headers=self.headers)
# 先判断返回状态码,既可以快速定位出错原因,又减少程序冗余运行
if res.status_code == 200:
res.encoding = 'utf-8'
# 解析url得到roomID
roomID = re.findall("/(\d+).html", url)
# 解析请求url返回的info,得到houseID
houseID = re.findall("'houseid', (.*?)]", res.text)
# 判断houseID是否有效数据
if houseID:
# 这里以字典方式返回主函数(不一定非要用字典的方式)
return dict([('roomID', roomID[0]), ('houseID', houseID[0])])
# 程序异常后,快速排错
else:
print('URL:', url)
print('roomID:', roomID)
print('houseID:', houseID)
print('网页异常,程序终止')
exit()
# 状态码异常 可以考虑使用IP代理
else:
print('get_houseID异常:%s' % res.status_code)
exit()
def get_priceImg(self, info, S):
'''
获取价格图片,准备下一步的图文识别
'''
url = 'http://sz.ziroom.com/detail/info?id=%s&house_id=%s' % (info['roomID'], info['houseID'])
# 使用requests.Session()的好处,不用关心cookies的更新问题
res = S.get(url, headers=self.headers)
res.encoding = 'utf-8'
print(res.url)
# 还是判断状态码,理由同上
if res.status_code == 200:
temp = res.json()
# 取大图URL,方便图像识别
img_url = temp['data']['price'][1]
# 取价格图片索引值
img_value = temp['data']['price'][2]
return [img_url, img_value]
else:
print('get_priceImg异常:%s' % res.status_code)
exit()
def get_price(self, imgs, S):
'''
获取价格图片,图文识别后返回房源价格
'''
data = S.get('http:' + imgs[0])
# 判断网页状态码
if data.status_code == 200:
# 利用时间戳给文件命名,非(lan)常(dao)科(jia)学(le)
filename = str(time.time()) + '.png'
with open(filename, 'wb') as f:
f.write(data.content)
# 核心科技部分:图文识别及价格索引拼接
text = pytesseract.image_to_string(Image.open(filename))
temp = []
for i in imgs[1]:
temp.append(text[i])
price = ''.join(temp)
return price
else:
print('get_price异常:%s' % data.status_code)
if __name__ == '__main__':
# 标记程序启动时间
start = time.clock()
# 使用会话,连续访问多个网页,防止网页因cookies不同而采集信息失败
S = requests.Session()
zr = ZrPrApi()
# 获取houseID,以便下一步请求价格图片地址
info = zr.get_houseID('http://sz.ziroom.com/z/vr/61127945.html', S)
# 获取图片地址,以便下一步分析价格
imgs = zr.get_priceImg(info, S)
# 图文识别,得到最终价格
print(zr.get_price(imgs, S))
# 标记程序结束时间
end = time.clock()
# 打印程序耗时
print(end - start)
下一期讲述:获取自如详情页房间配置信息提取
喜欢学习python爬虫的朋友,可以加交流群:692-858-412一起学习
喜欢我的文章可以关注我哦,别忘了点个喜欢!
网友评论
pycharm----速成手册:https://www.jianshu.com/p/5f37769e956f