# -*-coding:utf8-*-
# 导入请求库
import requests
# 导入lxml 用于解析HTML网页内容
from lxml import etree
# 导入csv 用于把内容写进表格
import csv
# 定义请求地址
url = "https://cd.lianjia.com/ershoufang/"
# 定义请求头部
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/95.0.4638.69 Safari/537.36"}
# 定义实现抓取内容逻辑函数 需要传入请求地址变量 函数定义返回一个list列表
def get_data(url) -> list:
# 定义一个总数据空列表用于储存爬取的每一个房源信息内容 下面逻辑将实现每一个房源的内容组为一个列表追加到这个总列表
zong_shuju_list = []
# 定义一个变量为序号 下面会加到每一条房源数据内容列表的第一个元素中
xuhao = 1
# 链家只能爬取最高100 页 所以这里使用循环100次 从第一页开始 每次爬取一页
for i in range(1,101):
# 由于爬取多页 使用requests.Session()方法 该方法能实现上下文会话管理,不会在爬取完一页就断开连接的目标网站,
# 方便连续访问而不被网站识别为恶意访问
with requests.Session() as r:
# 开启程序除错 try 后面放 要实现的逻辑 后面一定要有except 如果实现逻辑出错 这里捕捉异常
try:
# get请求地址内容 复制给变量 datas f'pg{i}' 可以理解为 字符串内容 pg + str(i)
datas = r.get(url=url+f'pg{i}/')
# datas 转为字符串文本复制给shuju变量
shuju = datas.text
# 原地输出 正在获取第几页
print(f"\r正在获取 第{i}页 地址:{datas.url} 状态码:{datas.status_code}",end='')
# 把shuju变量转为 lxml可操作对象
obj_lxml = etree.HTML(shuju)
# 利用循环获取每一个房源数据 每页30 个
for num in range(1,31):
# 列表推导式 遍历 lxml xpth解析来的对象内容 该对象是个迭代器
fangwu_xinxi_datas =[data.text for data in obj_lxml.xpath(f"/html/body/div[4]/div[1]/ul/li[{num}]/div[1]/div[1]/a")]
# 遍历后的第一位数据元素赋值给房屋信息变量
fangwu_xinxi = fangwu_xinxi_datas[0]
# 列表推导式 遍历 lxml xpth解析来的对象内容 该对象是个迭代器
xiaoqu_dizhi_datas1 = [data.text for data in obj_lxml.xpath(f"/html/body/div[4]/div[1]/ul/li[{num}]/div[1]/div[2]/div/a[1]")]
# 列表推导式 遍历 lxml xpth解析来的对象内容 该对象是个迭代器
xiaoqu_dizhi_datas2 = [data.text for data in obj_lxml.xpath(f"/html/body/div[4]/div[1]/ul/li[{num}]/div[1]/div[2]/div/a[2]")]
# 遍历后的第一位数据元素赋值给小区地址变量
xiaoqu_dizhi = xiaoqu_dizhi_datas1[0] +'- ' + xiaoqu_dizhi_datas2[0]
# 房屋类型->装修年份数据
# 列表推导式 遍历 lxml xpth解析来的对象内容 该对象是个迭代器
fangwu_leixing_zhuangxiu_nainfen_datas1 = [data for data in obj_lxml.xpath(f"/html/body/div[4]/div[1]/ul/li[{num}]/div[1]/div[3]/div/text()")]
# 遍历后的第一位数据元素赋值给房屋装修 至 修建年份 变量 这个变量 包含多个信息 需要再提取
fangwu_leixing_zhuangxiu_nainfen_datas2 = fangwu_leixing_zhuangxiu_nainfen_datas1[0]
# 定义一个列表dingwei_1 元素有一个0用于用于下面遍历定位'|'的数量
dingwei_1 = [0]
# 定义一个变量用于把房屋类型数据 放到这里
fangwu_leixing = ''
# 遍历 fangwu_leixing_zhuangxiu_nainfen_datas2 提取房屋类型数据
for fangwu_leixing_shuju in fangwu_leixing_zhuangxiu_nainfen_datas2:
# 如果遍历得到的内容是'|'
if fangwu_leixing_shuju == "|":
# dingwei_1列表第一位元素+1
dingwei_1[0] += 1
# 否则
else:
# 如果dingwei_1 等于1
if dingwei_1[0] == 1:
# 结束遍历循环
break
# 否则
else:
# 如果fangwu_leixing_shuju不等于空
if fangwu_leixing_shuju != " ":
# fangwu_leixing等于fangwu_leixing加fangwu_leixing_shuju
fangwu_leixing += fangwu_leixing_shuju
# 定义一个列表 dingwei_2 元素用于用于下面遍历定位'|'的数量
dingwei_2 = [0]
# 定义一个变量用于储存房屋面积数据
fangwu_mianji = ''
# 遍历取得 房屋面积数据
for fangwu_mianji_shuju in fangwu_leixing_zhuangxiu_nainfen_datas2:
if fangwu_mianji_shuju == "|":
dingwei_2[0] += 1
else:
if dingwei_2[0] == 1:
if fangwu_mianji_shuju != " ":
fangwu_mianji += fangwu_mianji_shuju
else:
if dingwei_2[0] == 2:
break
# 定义一个列表 dingwei_3 用于下面遍历定位'|'的数量
dingwei_3 = [0]
# 定义一个变量 用于储存遍历取得房屋朝向数据
fangwu_chaoxiang = ''
for fangwu_chaoxiang_shuju in fangwu_leixing_zhuangxiu_nainfen_datas2:
if fangwu_chaoxiang_shuju == "|":
dingwei_3[0] += 1
else:
if dingwei_3[0] == 2:
if fangwu_chaoxiang_shuju != " ":
fangwu_chaoxiang += fangwu_chaoxiang_shuju
else:
if dingwei_3[0] == 3:
break
# 定义一个列表 dingwei_4 用于下面遍历定位'|'的数量
dingwei_4 = [0]
# 定义一个变量 用于储存遍历取得房屋装修数据
fangwu_zhuangxiu = ''
for fangwu_zhuangxiu_shuju in fangwu_leixing_zhuangxiu_nainfen_datas2:
if fangwu_zhuangxiu_shuju == "|":
dingwei_4[0] += 1
else:
if dingwei_4[0] == 3:
if fangwu_zhuangxiu_shuju != " ":
fangwu_zhuangxiu += fangwu_zhuangxiu_shuju
else:
if dingwei_4[0] == 4:
break
# 定义一个列表 dingwei_5 用于下面遍历定位'|'的数量
dingwei_5 = [0]
# 定义一个变量 用于储存遍历取得房屋所在楼层数据
fangwu_suozailouceng = ''
for fangwu_suozailouceng_shuju in fangwu_leixing_zhuangxiu_nainfen_datas2:
if fangwu_suo