python爬虫爬取链家二手房信息(xpath)

python爬虫爬取链家二手房信息 -- xpath

需求

将小区名称、厅室、面积、毛坯还是精装、楼层、建筑年代、板楼还是塔楼、总价和每平方米单价等信息爬取放入字典中

流程

  1. 查看想要的数据在网页源码中是否存在(确认是否为静态部分)
  2. 找网页url的规律,规律如下:
    第n页:https://sh.lianjia.com/ershoufang/pgn/
  3. 写xpath表达式
    右键查看页面元素,发现节点 <ul class=“sellListContent” log-mod=“list” 下的每一个li子节点就是一个房源的信息
    在chrome浏览器用xpath表达式匹配想要的房源信息节点
    此处表达式为://ul[@class=“sellListContent”]/li[@class=“clear LOGVIEWDATA LOGCLICKDATA”]
    返回值为:节点对象列表[li1,li2,li3…]

    1.匹配出广告等不需要的信息,用xpath表达式的条件过滤掉
    2. 页面中xpath能匹配出来,程序中不能匹配出来,属于正常现象。
    一定是浏览器自动执行了一些js(因为xpath匹配的是js渲染完之后的html代码),将页面结构做了一些调整,
    一旦出现这种情况, 查看网页响应的源码,在源码中找到关键字,截取周围源码,将源码html在线格式化后,看结构和内容,即页面中的xpath不能全信,以实际响应源码的内容为准,重写xpath表达式
  4. for循环遍历 提取每一个 li 房源数据
  5. 根据页面元素html写xpath表达式
    1. 小区名称://div[@class=“positionInfo”]/a[1]/text()

    2. 区域://div[@class="positioninfo’]/a[2]/text()

    3. 商品房信息://div[@class=“houseInfo”]/text()
      拿出来的是字符串:“户型+面积+方位+是否精装+楼层+年代+类型"
      e.g. 2室一厅 | 67.7平米 | 南北 | 毛坯 | 低楼层(共6楼) |1997年建 | 板楼
      split(’|’)之后

      1. 户型:houseinfo[0]
      2. 面积:houseinfo[1]
      3. 方位:houseinfo[2]
      4. 精装:houseinfo[3]
      5. 楼层:houseinfo[4]
      6. 年代:houseinfo[5]
      7. 类型:houseinfo[6]
    4. 总价://div[@class=“totalPrice”]/span/text()

    5. 单价://div[@class=“unitPrice”]/span/text()

详细代码

import requests
from lxml import etree
import time
import random
from fake_useragent import UserAgent

class LianjiaSpider(object):
	def __init__(self):
		self.url = 'https://sh.lianjia.com/ershoufang/pg{}/'

	def parse_html(self,url):
		headers = {'User-Agent':UserAgent().random}
		#当请求没响应时,再循环请求两次,没响应抛出异常。当响应成功,退出当前循环。继续下一页数据抓取
		for i in range(3):
			try:
				#Requests模块:向网站发请求并获取响应对象html内容,用content属性保险点,响应超时时间为3秒
				html = requests.get(url=url,headers=headers).content.decode('utf-8','ignore',timeout=3)
				self.get_data(html)
			except Exception as e:
				print('Retry')
				print(e)
		
	def get_data(self,html):
		#lxml模块:创建解析对象
		p = etree.HTML(html)
		#解析对象调用匹配房源信息的xpath表达式,返回值为节点对象列表:[li1,li2,li3]
		li_list = p.xpath('''/ul[@class="sellListContent"]/li[@class=
						"clear LOGVIEWDATA LOGCLICKDATA"]''')
		item = {}
		#for循环遍历列表,获取每一个房源信息中的每一个具体信息,放入字典
		for p in li_list:
			#注意遍历厚继续xpath,xpath表达式要以 .开头,代表在当前节点下(不在整个html下)
			#小区名
			name_list = p.xpath('.//div[@class="positioninfo']/a[1]/text()') #返回值是个列表
			#为防name_list没匹配出来,没匹配出来向数据库中存一个None
			item['name'] = name_list[0].strip() if name_list else None
			
			#区域
			region = p.xpath('.//div[@class="positioninfo']/a[2]/text()')
			item['region'] = region[0].strip() if region else None
			
			#二手房信息
			houseinfo = p.xpath('.//div[@class="houseInfo"]/text()')
			#houseinfo = [“户型+面积+方位+是否精装+楼层+年代+类型"]
			#谨慎点,如果匹配出houseinfo 就拿数据,如果为空,就直接存一个None
			if houseinfo:
				houseinfo = houseinfo[0].split('|')	#返回值是个列表
				#谨慎点,houseinfo列表里需要有7条数据,否则直接置为None
				if len(houseinfo) == 7:
					item['housetype'] = houseinfo[0].strip()
					item['area'] = houseinfo[1].strip()
					item['direction'] = houseinfo[2].strip()
					item['decoration'] = houseinfo[3].strip()
					item['level'] = houseinfo[4].strip()
					item['time'] = houseinfo[5].strip()[:-2]	#用切片取出数字,去掉最后两个汉字
					item['type'] = houseinfo[6].strip()
				else:
					item['housetype'] = item['area'] = item['direction'] = \
					item['decoration'] = item['level'] = item['time'] = item['type']  \
					= None
			else:
				item['housetype'] = item['area'] = item['direction'] =  \
     				item['decoration'] = item['level'] = item['time'] = item['type']  \
     				= None
			
			#总价
			total_list = p.xpath('.//div[@class="totalPrice"]/span/text()')
			item['total'] = total_list[0].strip() if total_list else None
			#每平米单价
			unit_list = p.xpath('.//div[@class="unitPrice"]/span/text()')
			item['unit'] = unit_list[0].strip() if unit_list else None

		print(item)

	def run(self):
		for page in range(1,101):
			url = self.url.format(page)
			self.parse_html(url)
			time.sleep(random.randint(1,2))

if __name__ == '__main__':
	spider = LianjiaSpider()
	spider.run()
  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值