# -*- coding: utf-8 -*-
# File  : 7链家抓取--抓取经纪人信息.py
# Author: HuXianyong
# Date  : 2018-08-30 15:41

from urllib import request
from time import sleep
from lxml import etree

'''
在开始之前我们应该先查看下我们每次打开下一页链家网页的时候他的url上面有什么变化
我们每每点击下一页的时候他的url也对应的加上了page+n
还有就是referer也变化了,变成了我们的上一页
因此我们就需要对着这个变化来对url和referer做处理才能实现多页爬取数据
别的网页也应是有规律的
我们就用这个规律来做就好了

我们就只需要改变url和referer就好,其他的和单页抓取数据一样的

这里增加了地域的房屋,我们通过观察几页的url上面的改变,url都是由
链家域名+地域+页数来组成的,我们因此拼接出url

'''
#我这里定义这个函数是抓取但也数据的,上个函数的循环把要抓取的页数传递到这里来
#我就抓取他给我传过来的那一页就行
def urlOPen(area,num):
    page=int(num)
    print(page,num)

    #如果是第一页他的url就是当前页referer是什么都行,只要链家的就行
    if page == 1 :
        referer=url = "https://bj.lianjia.com/zufang/%s/"%area

    #第二页他的rferer是和第一页的referer和url是一样的,url的page变成了第二页
    elif page == 2:
        url = "https://bj.lianjia.com/zufang/%s/pg%s/"%(area,page)
        referer = "https://bj.lianjia.com/zufang/%s/pg1/"%area
    else:
        url = "https://bj.lianjia.com/zufang/%s/pg%s/" % (area,page)
        referer = "https://bj.lianjia.com/zufang/%s/pg%s/"%(area,int(page-1))

    headers = {
        #rerferer 的意思是引应用的上个页面是什么,这个的作用是防盗链,有的网站会用这个来判断是否是盗链过来的
        #如果没有加这个,有的网页会打不开,加这个养成一个良好的习惯
        "Referer": referer,
        #user-agent的意思很明显就是客户端的用户信息,包括系统版本,浏览器等的信息
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
        #可能还有别的信息需要加在头上,就看个人的需要了
    }
    # print(url)
    req = request.Request(url=url,headers=headers)
    #这里的urlopen打开的是一个对象
    try:
        response = request.urlopen(req)
        #对爬取到的网页信息进行读取和解码
        result = response.read().decode("utf-8")
        #用xpath构建html匹配的对象
        html = etree.HTML(result)

        grap_data(url,html)

    except Exception as e:
        print('*'*60+"打开失败的url为:%s\n失败的报错为:%s\n"%(url,e)+'*'*60)

#获取当前匹配条的房屋信息
def house_data(url,house_info,house_base,times):
    house = house_base.xpath('div[@class="info-panel"]')[0]
    # 获取房屋的名字
    house_name = house.xpath('h2/a')[0]
    # 获取房屋的地址
    house_addr = house.xpath('div/div[@class="where"]/a/span[@class="region"]')[0]
    # 获取房屋的大小
    house_size = house.xpath('div/div/span[@class="meters"]')[0]
    # 获取房屋的价格
    house_price = house.xpath('div/div[@class="price"]/span[@class="num"]')[0]
    # 获取房屋的链接
    house_link = house.xpath('h2/a/@href')[0]
    # print(house_link)
    # 接收房屋的经纪人和经纪人的电话
    broker_name, broker_phone = grap_broker(house_link, url)
    house_dict = {
        "房屋的地址": house_addr.text.strip(),
        "房屋的名字": house_name.text.strip(),
        "房子的大小": house_size.text.strip(),
        "房子的价格": house_price.text.strip(),
        "经纪人电话": broker_phone,
        "经纪人名字": broker_name
    }
    house_info.append(house_dict)
    # print(
    #     "这是第%s间房==房屋的地址 :%s, 房屋的名字 :%s, 房子的大小 :%s, 房子的价格 :%s, 经纪人电话 :%s, 经纪人名字 :%s"%(times,house_addr.text.strip(),house_name.text.strip(),house_size.text.strip(), house_price.text.strip(),broker_phone,broker_name)
    # )
    # 这里可以加入字典,当然也是可以写入数据库里面的
    sleep(0.5)
    print('这是第%s间房 '%times+str(house_dict))

#循环获取当页的数据房屋的信息
def grap_data(url,html):
    #定义一个接收房源信息的列表
    house_info = []
    times=1
    #循环查询每页房屋信息

    #定义一个网页元素的房屋列表,如果是按照panel这个来看的话可能会出错
    house_num = html.xpath('//ul[@id="house-lst"]/li')
    for house_base in house_num:

        try:
            house_data(url,house_info,house_base,times)
            times += 1
        except Exception as xpathError:
            #print(xpathError,"xpathError")
            print(str(times)+'*'*60+'这里是xpath匹配报错,报错为%s'%xpathError+'*'*60)

#定义一个第二次打开网页的函数,来调出我们需要的经纪人信息
def grap_broker(house_link,url):

        # 到此我们可以抓去除房屋的外联
        # 但是这个不是我们需要的,我们需要的是经纪人的信息,我们因此需要打开这个网页来回获取到我们想要的信息

        # 打开网页
        link_headers = {
            "Referer": url,
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
        }
        link_req = request.Request(url=house_link, headers=link_headers)
        link_response = request.urlopen(link_req)
        link_result = link_response.read().decode("utf-8")

        link_html = etree.HTML(link_result)
        #刚开始在这里卡住了好半天,原因是因为没有经纪人信息,所以报错了
        #因此这里需要加个异常处理,来处理没有经纪人的的情况
        try:
            #获取经纪人的电话号码和用户名
            broker_phone = link_html.xpath('//div[@class="brokerInfoText"]/div[@class="phone"]')[0].text.strip()
            broker_name = link_html.xpath('//div[@class="brokerInfo"]/div/div[@class="brokerName"]/a')[0].text
            #print(broker_name.text)
        except Exception :
            #没有经纪人的,使用固定的经纪人和电话号码
            broker_name = "客服"
            broker_phone = "10109666"
        return broker_name,broker_phone
#这里定义的是需要爬取的是哪一些的数据
def start(area,page):
    for num in range(1,int(page+1)):
        print("-"*70+'这个是%s第%s页的数据'%(area,num)+'-'*70)
        #调用爬取数据的函数
        urlOPen(area,num)

if __name__ == "__main__":
    start('changping',5)