Selenium+ChromeDriver爬取链家网二手房价(包括经纬度)信息

时间:2024-03-14 21:44:58

【需求】

  爬取青岛市二手房源信息,要求包括房源基本信息、小区名称、总价、单价以及房源的经纬度信息。
  根据以上需求,进入青岛市二手房首页,如图1所示,进行页面分析:
Selenium+ChromeDriver爬取链家网二手房价(包括经纬度)信息

图1

【页面分析】

  首先分析图1所示页面。可以看到青岛市二手房源共有30266条,按区分为市南、市北、李沧等10个区。同时房源列表中包含部分我们所需要的信息,但是并不完整。我们点击该房源进行详情页,如图2、图3所示。
Selenium+ChromeDriver爬取链家网二手房价(包括经纬度)信息

图2

Selenium+ChromeDriver爬取链家网二手房价(包括经纬度)信息

图3
  这里需要注意的是该房源的经纬度信息并没有直接展示出来,F12查看页面源码,找找看。能找到万事大吉,找不到很有可能就不包含经纬度信息。

  这里有一个小技巧:首先百度一下青岛市的经纬度范围(东经119°30′~121°00′,北纬35°35′~37°09′),然后我们就可以在控制台源码中Ctrl+F搜索该范围内的经度、纬度,比如依次搜索119、120、121或35、36、37,如果该页面中包含经纬度信息则一定可以搜索到。这里我搜索到“120.”时就找到了貌似经纬度的信息,如图4所示,通过在线经纬度信息查询与该网站上所示的地理位置对比,确认了该信息就是房源对应的经纬度,然后我们可以利用正则表达式进行提取。
Selenium+ChromeDriver爬取链家网二手房价(包括经纬度)信息

图4

【亟须解决的3个问题】

  上面找到了我们所需信息的页面,那每个房源详情页都对应一个URL,

  • 【问题1】如何获取所有房源的URL?

  回到青岛市二手房首页。爬虫必备【F12】一下,打开控制台。在控制台中,点击【选择元素】,选择标题时发现<a>标签中指向一个地址,如图5所示:

Selenium+ChromeDriver爬取链家网二手房价(包括经纬度)信息

图5
  然后我们打开这个地址,发现刚好是该房源的详情页 ,那么我们就可以获取每一个房源指向的详情页URL了。【问题1】也就得到了解决。

  但是当我在图1所示的青岛市二手房页面中往下拉时发现房源信息以分页的形式展示,最多分为100页,每页最多30条,如图6所示:

Selenium+ChromeDriver爬取链家网二手房价(包括经纬度)信息

图6
  也就是说不能一股脑的去爬,这样最多只能获取100*30=3000条数据。
  • 【问题2】怎么解决分页的问题获取所有房源的URL?

  通过观察网页二手房首页可以看到,所有二手房源可以按位置、按售价、按面积、按房型等进行分类,如图7所示:
Selenium+ChromeDriver爬取链家网二手房价(包括经纬度)信息

图7
  我们再点击不同区看一下对应URL:

市南:https://qd.lianjia.com/ershoufang/shinan/
市北:https://qd.lianjia.com/ershoufang/shibei/
李沧:https://qd.lianjia.com/ershoufang/licang/

  然后发现不同区的URL是有规律的,仅仅是后面拼音不一样。
  这样就可以通过不同区进行爬取。为了最大化的获取数据,同时要求每个区的房源数也不能超过3000条,如果超过3000条,则可以在按区分类的同时,再按售价(或面积、房型等)进行更细的分类,以此类推。这里由于市南、市北等几个区的二手房源超过3000,所以在按区的同时还需要再按售价进行分类爬取(因此总共应分为80类,即10个区,每个区对应8类售价)。
  我们再点击不同的售价类型:
市南&80万以下   https://qd.lianjia.com/ershoufang/shinan/p1/
市南&80-100万万以下:https://qd.lianjia.com/ershoufang/shinan/p2/
市南&100-150万万以下:https://qd.lianjia.com/ershoufang/shinan/p3/

市北&80万以下:https://qd.lianjia.com/ershoufang/shibei/p1/
市北&80-100万万以下:https://qd.lianjia.com/ershoufang/shibei /p2/
市北&100-150万万以下:https://qd.lianjia.com/ershoufang/shibei /p3/

  这里发现同时按区和售价分类的URL也存在一定规律,即在按区分类的基础上添加页码p1表示第1也,p2表示第2页…….,因此同时按区和售价爬取是一个不错的方法。那么【问题2】也就得到了解决。
  有了获取某一页某一房源详情页URL的方法和获取同时按区和售价分类后的URL,就可以从每个分类后的URL中的每一页中依次获取所有房源详情页URL,但是这里需要解决每个分类后的URL中的分页问题。

  • 【问题3】怎么解决分类后的分页的问题而获取所有房源的URL?

  下面我们同时选择市南区和100-150万,页面列出了339条数据,被分为12页。
  然后我们一直单击下一页,观察URL的变化:
第1页:https://qd.lianjia.com/ershoufang/shinan/p3/
第2页:https://qd.lianjia.com/ershoufang/shinan/pg2p3/
第3页:https://qd.lianjia.com/ershoufang/shinan/pg3p3/

  这里我们发现同样存在规律,URL中p3表示第3类售价,即100-150万,除了第一页, pg2、pg3表示页码,通过这个规律我们就可以通过代码构造不同区不同售价不同页码的URL。那么【问题3】也就得到了解决。
  综上分析我们可以构造不同区不同售价不同页码上的所有房源详情页的URL,然后通过请求并解析该URL获取我们所需爬取的信息。

【撸起袖子开始干】

  爬虫框架:这里我采用自己比较熟悉的Selenium进行爬取,使用lxml库进行Html解析,另外需要chromedriver.exe自动化加载页面。
  需要的第三方python库:selenium、lxml、xlrd、xlwt
另外下载chromedriver.exe时要求chromedriver与所使用的谷歌浏览器版本对应,其对应关系及下载地址参考:Chrome与ChromeDriver版本对应参照表及下载地址

【爬取五部曲】

  下面直接贴代码,代码不难,具体自己看

【一步曲:获取不同区的URL】

def get_range_url():
#声明list用于存储不同区的url
    range_urls={}
    driver=get_chromedriver()
    driver.get(city_url)
    html = driver.page_source
    selector = etree.HTML(html)
    #获取青岛不同区对应的URL
    for i in range(0,10):#青岛市分为10个区
        a_href=str(selector.xpath('//*[@class="position"]/dl[2]/dd/div[1]/div/a['+str(i+1)+']/@href')[0])#标签索引从1开始
        rangename=str(selector.xpath('//*[@class="position"]/dl[2]/dd/div[1]/div/a['+str(i+1)+']/text()')[0])
        range_url='https://qd.lianjia.com'+a_href
        range_urls[rangename]=range_url
    return range_urls

【二步曲:获取不同区不同售价的URL】

#根据已获取的不同区的URL,获取不同区不同售价的URL
def get_range_price_url():
#获取不同区的URL
range_urls=get_range_url()
    #声明字典用于存储不同区不同售价的URL,key为每个区名,value为该区对应的8个售价的url
range_price_urls={}
    for key in range_urls:
        range_url=range_urls[key]
        part_range_price_url=[]
        for i in range(1,9):#按售价分为8个区间,依次在按区的URL后增加p1/,p2/,...p8/
            range_price_url=range_url+'p'+str(i)+'/'
            part_range_price_url.append(range_price_url)
        range_price_urls[key]=part_range_price_url
    return range_price_urls

【三步曲:获取不同区不同售价不同页的URL】

#根据已获取的不同区不同售价的URL,获取不同区不同售价不同页的URL,并将url写入excel中
def get_range_price_page_url():
#获取不同区不同售价的URL列表集合
    range_price_urls=get_range_price_url()
#声明字典用于存储不同区不同售价不同页的url,key为区名, value为每个区对应的不同售价不同页的url的list集合
    range_price_page_urls={}
    #创建workbook(即excel文件)
    workbook = xlwt.Workbook(encoding='utf-8')
    #创建g工作簿(即表)
    worksheet = workbook.add_sheet('Sheet1')
    count=0
    for key in range_price_urls:
        try:
            driver = get_chromedriver()
        except Exception:
            driver = get_chromedriver()
        part_range_price_urls=range_price_urls[key]
        for part_range_price_url in part_range_price_urls:
            #请求URL获取该页面中房源的个数,从而计算有多少页
            try:
                driver.get(part_range_price_url)
            except Exception:
                driver.get(part_range_price_url)
            #等待2秒,以便浏览器加载所有资源,受网速影响如果网站需要加载资源较多可能加载不完全
            time.sleep(2)
            html = driver.page_source
            selector = etree.HTML(html)
#根据不同区不同售价url页面中的总房源数(每页30天,最后一页不足30条)计算有多少页
            house_count=selector.xpath('//*[@class="resultDes clear"]/h2/span/text()')
            yushu = int(house_count[0]) % 30
            page_count = 0
            if (yushu is 0):
                page_count = int(int(house_count[0]) / 30)
            else:
                page_count = int(int(house_count[0]) / 30) + 1
            #part_range_price_page_urls=[]
            #构造不同区不同售价不同页码的URL
            for i in range(0,page_count):
                range_price_page_url=''
                if (i is 0):
                    range_price_page_url=part_range_price_url
                else:
                    list_ss = part_range_price_url.split('/')
                    url_priceId = list_ss[5]
                    range_price_page_url = part_range_price_url.replace(url_priceId, 'pg' + str(i + 1) + url_priceId)
                #part_range_price_page_urls.append(range_price_page_url)
                #将每页的URL写如excel文件中
                worksheet.write(count,0, key)#第一列写入区
                worksheet.write(count,1, range_price_page_url)#第二列写入url
                count+=1
                print(str(count))
        driver.quit()
    workbook.save('range_price_page_urls.xls')
    print('OK')

  该函数运行结果将生成range_price_page_urls.xls文件,该文件中包含结果如图8所示:

Selenium+ChromeDriver爬取链家网二手房价(包括经纬度)信息

图8

【四步曲:获取每个房源详情页的URL】

  该步骤首先读取步骤三中生成的excel文件,获取不同区不同售价不同页的URL,并依次请求每个URL,然后在请求页面中获取每页中房源的详情页,每页均按30个来处理,注意这里需要捕获异常,不满30个的情况将会出现IndexError,然后我们break即可。

def get_finall_urls():
    #读取get_range_price_page_url()生成的excel文件:range_price_page_urls.xls
    data = xlrd.open_workbook('range_price_page_urls.xls')
    table = data.sheets()[0]  # 通过索引顺序获取表
    #获取行数
    row_count=table.nrows
    driver = get_chromedriver()
    # 创建workbook(即excel文件)
    workbook = xlwt.Workbook(encoding='utf-8')
    # 创建g工作簿(即表)
    worksheet = workbook.add_sheet('Sheet1')
    count = 0
    for i in range(0,row_count):
        # 读取区名和url后发现该值形如:text:'区名'、text:'url',但excel文件中仅显示的为区名和url(这里原因我暂时没有仔细考虑)
        # 所以就用一个正则直接把区名和url给提取出来
        pattern = re.compile("text:'" + '(.*?)' + "'", re.S)
        rangename_temp=str(table.cell(i,0))
        rangename= pattern.findall(rangename_temp)[0]
        url_temp=str(table.cell(i,1))
        url = pattern.findall(url_temp)[0]
        try:
            driver.get(url)
        except Exception:
            driver.get(url)
        time.sleep(2)
        html = driver.page_source
        selector = etree.HTML(html)
        for j in range(0,30):
            try:
                finall_url = selector.xpath('//*[@class="sellListContent"]/li[' + str(j + 1) + ']/a/@href')[0]  # 某一个房源的详情页
            except Exception:
                break
            worksheet.write(count, 0,rangename)  # 第一列写入区
            worksheet.write(count, 1,finall_url)  # 第二列写入url
            count+=1
            print(str(count)+'/30266')
    driver.quit()
    workbook.save('finall_urls.xls')
    print('OK')

  该函数运行结果将生成finall_urls.xls 文件,如图9所示包含30192条房源详情页的URL,和30266条相差73条原因可能是网络请求超时跳过了。
Selenium+ChromeDriver爬取链家网二手房价(包括经纬度)信息

图9

【终曲:爬取每个房源的信息】

#爬取每一个房源详情页中的信息
def get_house_info():
    # 读取get_finall_urls()生成的excel文件:finall_urls.xls
    data = xlrd.open_workbook('finall_urls.xls')
    table = data.sheets()[0]  # 通过索引顺序获取表
    # 获取行数
    row_count = table.nrows
    # 启动一个driver
    driver = get_chromedriver()
    f = open("qingdao.txt", 'w', encoding='utf-8')
    for i in range(0,row_count):
        #这里同样会出现get_finall_urls()函数中的问题,处理方法与其一样
        pattern = re.compile("text:'" + '(.*?)' + "'", re.S)
        rangename_temp=str(table.cell(i,0))
        rangename=pattern.findall(rangename_temp)[0]
        url_temp=str(table.cell(i,1))
        url=pattern.findall(url_temp)[0]
        try:
            driver.get(url)
        except Exception:
            driver.get(url)
        time.sleep(2)
        # 获取房源详情页面
        html=driver.page_source
        # 解析详情页  获取所需信息
        selector = etree.HTML(html)
        try:
            #获取总价
            total_price=selector.xpath('//*[@class="total"]/text()')[0]
            #获取单价
            unit_price=selector.xpath('//*[@class="unitPriceValue"]/text()')[0]
            #获取小区名称
            apartment_name = selector.xpath('//*[@class="communityName"]/a[1]/text()')[0]
            # 获取所在区域
            inrange= selector.xpath('//*[@class="info"]/a[2]/text()')[0]
            # 通过正则表达式匹配获取经纬度信息
            pattern = re.compile("resblockPosition:'" + '(.*?)' + "',", re.S)
            pos = pattern.findall(html)[0]
            lon=pos.split(',')[0]
            lat=pos.split(',')[1]
            #获取基本信息 ,包括以下13个基本属性
            #1.房屋户型
            house_type=selector.xpath('//*[@class="base"]/div[2]/ul/li[1]/text()')
            #2所在楼层
            floor=selector.xpath('//*[@class="base"]/div[2]/ul/li[2]/text()')[0]
            # 3建筑面积
            out_area = selector.xpath('//*[@class="base"]/div[2]/ul/li[3]/text()')[0]
            # 4户型结构
            house_stru = selector.xpath('//*[@class="base"]/div[2]/ul/li[4]/text()')[0]
            # 5套内面积
            in_area = selector.xpath('//*[@class="base"]/div[2]/ul/li[5]/text()')[0]
            # 6建筑类型
            build_type = selector.xpath('//*[@class="base"]/div[2]/ul/li[6]/text()')[0]
            # 7房屋朝向
            house_direc = selector.xpath('//*[@class="base"]/div[2]/ul/li[7]/text()')[0]
            # 8建筑结构
            bulid_stru = selector.xpath('//*[@class="base"]/div[2]/ul/li[8]/text()')[0]
            # 9装修情况
            decorate = selector.xpath('//*[@class="base"]/div[2]/ul/li[9]/text()')[0]
            # 10梯户比例
            ratio = selector.xpath('//*[@class="base"]/div[2]/ul/li[10]/text()')[0]
            # 11供暖方式
            heating = selector.xpath('//*[@class="base"]/div[2]/ul/li[11]/text()')[0]
            # 12配备电梯
            elevator = selector.xpath('//*[@class="base"]/div[2]/ul/li[12]/text()')[0]
            # 13产权年限
            age_limit = selector.xpath('//*[@class="base"]/div[2]/ul/li[13]/text()')[0]
             #获取交易属性 ,包括以下8个
            #1.挂牌时间
            pull_time=selector.xpath('//*[@class="transaction"]/div[2]/ul/li[1]/span[2]/text()')[0]
            #2交易权属
            deal_owner=selector.xpath('//*[@class="transaction"]/div[2]/ul/li[2]/span[2]/text()')[0]
            # 3上次交易
            lasttime = selector.xpath('//*[@class="transaction"]/div[2]/ul/li[3]/span[2]/text()')[0]
            # 4房屋用途
            house_use = selector.xpath('//*[@class="transaction"]/div[2]/ul/li[4]/span[2]/text()')[0]
            # 5房屋年限
            house_age = selector.xpath('//*[@class="transaction"]/div[2]/ul/li[5]/span[2]/text()')[0]
            # 6产权所属
            right_owner = selector.xpath('//*[@class="transaction"]/div[2]/ul/li[6]/span[2]/text()')[0]
            # 7抵押信息,这里存在换行符和空格,需要处理
            pledge_info = selector.xpath('//*[@class="transaction"]/div[2]/ul/li[7]/span[2]/text()')[0].replace('\n','').replace(' ','')
            # 8房本备件
            house_part = selector.xpath('//*[@class="transaction"]/div[2]/ul/li[8]/span[2]/text()')[0]
        except Exception:
            continue
            #将获取的所有信息写入文本文件中
        f.write("%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%s"%(
            total_price,unit_price,apartment_name,inrange,lon,lat,house_type,floor,out_area,house_stru,in_area,
            build_type,house_direc,bulid_stru,decorate,ratio,heating,elevator,age_limit,pull_time,deal_owner,
            lasttime,house_use,house_age,right_owner,pledge_info,house_part
        ))
        f.write('\n')
        print(str(i+1))
    f.close()
    print('OK')

【爬虫结果查看及数据可视化】

【数据查看】
  最终爬取28869条数据,不足30192的原因可能是网络异常或者获取相关信息不存在抛出异常时给跳过了,如下图10所示。

Selenium+ChromeDriver爬取链家网二手房价(包括经纬度)信息

图10
注意事项:在爬取的过程中,可能会因为网络波动(或其它原因)致使chromedriver请求数据时出现请求超时的错误而终止程序,如图11所示,我使用异常捕获根本没用,这里有哪位大神有好的解决办法可以告诉我一下,另外据说scrapy-splash不错,比selenium快,有时间我会学习一下。如果程序终止,如图12所示,更改红框处URL的起止索引继续往下爬取即可。

Selenium+ChromeDriver爬取链家网二手房价(包括经纬度)信息

图11

Selenium+ChromeDriver爬取链家网二手房价(包括经纬度)信息

图12

【数据可视化】
  将txt文本以@符号进行分割转为excel文件(保存为.xls的excel文件,因为【添加XY数据】只能识别.xls格式的excel文件,且经度、纬度两列单元格的格式需要为数值类型,为了数据的精确度小数点应设置为7位或以上),然后使用ArcGIS中的【添加XY数据】添加二手房源数据,并将其导出为shp格式。最后通过分级设色将房价分为10类,可视化结果如图13所示。

Selenium+ChromeDriver爬取链家网二手房价(包括经纬度)信息

图13
  另外我用同样的方法爬取了成都市的二手房信息,可视化结果如图14所示。

Selenium+ChromeDriver爬取链家网二手房价(包括经纬度)信息

图14

【完整代码】

import xlrd
import xlwt
from lxml import etree
from selenium import webdriver
import re
import time
city_url='https://qd.lianjia.com/ershoufang/'
#实例化chromedriver
def get_chromedriver():
    #设置参数
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('--headless')#控制是否显示浏览器,注释将显示
    #chrome_options.add_argument("--start-maximized")#控制浏览器运行时的窗口大小
    chrome_options.add_argument('--disable-gpu')
    driverpath = "E:\chromedriver.exe"#下载的chromedriver.exe的全路径
    #创建谷歌浏览器驱动对象,用于后续操作浏览器
    chromedriver = webdriver.Chrome(executable_path=driverpath, chrome_options=chrome_options)
    return chromedriver
#获取不同区的URL,参数为城市二手房首页的url,青岛的为:https://qd.lianjia.com/ershoufang/
def get_range_url():
    # 声明list用于存储不同区的url
    range_urls={}
    driver=get_chromedriver()
    driver.get(city_url)
    html = driver.page_source
    selector = etree.HTML(html)
    #获取青岛不同区对应的URL
    for i in range(0,10):#青岛市分为10个区
        a_href=str(selector.xpath('//*[@class="position"]/dl[2]/dd/div[1]/div/a['+str(i+1)+']/@href')[0])#标签索引从1开始
        rangename=str(selector.xpath('//*[@class="position"]/dl[2]/dd/div[1]/div/a['+str(i+1)+']/text()')[0])
        range_url='https://qd.lianjia.com'+a_href
        range_urls[rangename]=range_url
    return range_urls
#根据已获取的不同区的URL,获取不同区不同售价的URL
def get_range_price_url():
    # 获取不同区的URL
    range_urls = get_range_url()
    # 声明字典用于存储不同区不同售价的URL,key为每个区名,value为该区对应的8个售价的url
    range_price_urls={}
    for key in range_urls:
        range_url=range_urls[key]
        part_range_price_url=[]
        for i in range(1,9):#按售价分为8个区间,依次在按区的URL后增加p1/,p2/,...p8/
            range_price_url=range_url+'p'+str(i)+'/'
            part_range_price_url.append(range_price_url)
        range_price_urls[key]=part_range_price_url
    return range_price_urls
#根据已获取的不同区不同售价的URL,获取不同区不同售价不同页的URL,并将url写入excel中
def get_range_price_page_url():
    range_price_urls=get_range_price_url()
    range_price_page_urls={}
    #创建workbook(即excel文件)
    workbook = xlwt.Workbook(encoding='utf-8')
    #创建g工作簿(即表)
    worksheet = workbook.add_sheet('Sheet1')
    count=0
    for key in range_price_urls:
        try:
            driver = get_chromedriver()
        except Exception:
            driver = get_chromedriver()
        part_range_price_urls=range_price_urls[key]
        for part_range_price_url in part_range_price_urls:
            #请求URL获取该页面中房源的个数,从而计算有多少页
            try:
                driver.get(part_range_price_url)
            except Exception:
                driver.get(part_range_price_url)
            #等待2秒,以便浏览器加载所有资源,受网速影响如果网站需要加载资源较多可能加载不完全
            time.sleep(2)
            html = driver.page_source
            selector = etree.HTML(html)
            #根据不同区不同售价url页面中的总房源数(每页30天,最后一页不足30条)计算有多少页
            house_count=selector.xpath('//*[@class="resultDes clear"]/h2/span/text()')
            yushu = int(house_count[0]) % 30
            #page_count = 0
            if (yushu is 0):
                page_count = int(int(house_count[0]) / 30)
            else:
                page_count = int(int(house_count[0]) / 30) + 1
            #part_range_price_page_urls=[]
            #构造不同区不同售价不同页码的URL
            for i in range(0,page_count):
                #range_price_page_url=''
                if (i is 0):
                    range_price_page_url=part_range_price_url
                else:
                    list_ss = part_range_price_url.split('/')
                    url_priceId = list_ss[5]
                    range_price_page_url = part_range_price_url.replace(url_priceId, 'pg' + str(i + 1) + url_priceId)
                #part_range_price_page_urls.append(range_price_page_url)
                #将每页的URL写如excel文件中
                worksheet.write(count,0,key)#第一列写入区
                worksheet.write(count,1,range_price_page_url)#第二列写入url
                count+=1
                print(str(count))
        driver.quit()
    workbook.save('range_price_page_urls.xls')
    print('OK')
#获取每一个房源详情页的url
def get_finall_urls():
    #读取get_range_price_page_url()生成的excel文件:range_price_page_urls.xls
    data = xlrd.open_workbook('range_price_page_urls.xls')
    table = data.sheets()[0]  # 通过索引顺序获取表
    #获取行数
    row_count=table.nrows
    driver = get_chromedriver()
    # 创建workbook(即excel文件)
    workbook = xlwt.Workbook(encoding='utf-8')
    # 创建g工作簿(即表)
    worksheet = workbook.add_sheet('Sheet1')
    count = 0
    for i in range(0,row_count):
        # 读取区名和url后发现该值形如:text:'区名'、text:'url',但excel文件中仅显示的为区名和url(这里原因我暂时没有仔细考虑,可能是编码不一致的问题)
        # 所以就用一个正则直接把区名和url给提取出来
        pattern = re.compile("text:'" + '(.*?)' + "'", re.S)
        rangename_temp=str(table.cell(i,0))
        rangename= pattern.findall(rangename_temp)[0]
        url_temp=str(table.cell(i,1))
        url = pattern.findall(url_temp)[0]
        try:
            driver.get(url)
        except Exception:
            driver.get(url)
        time.sleep(2)
        html = driver.page_source
        selector = etree.HTML(html)
        for j in range(0,30):
            try:
                finall_url = selector.xpath('//*[@class="sellListContent"]/li[' + str(j + 1) + ']/a/@href')[0]  # 某一个房源的详情页
            except Exception:
                break
            worksheet.write(count, 0,rangename)  # 第一列写入区
            worksheet.write(count, 1,finall_url)  # 第二列写入url
            count+=1
            print(str(count)+'/30266')
    driver.quit()
    workbook.save('finall_urls.xls')
    print('OK')
#爬取每一个房源详情页中的信息
def get_house_info():
    # 读取get_finall_urls()生成的excel文件:finall_urls.xls
    data = xlrd.open_workbook('finall_urls.xls')
    table = data.sheets()[0]  # 通过索引顺序获取表
    # 获取行数
    row_count = table.nrows
    # 启动一个driver
    driver = get_chromedriver()
    f = open("qingdao34"
             ".txt", 'w', encoding='utf-8')
    for i in range(0,row_count):
        #这里同样会出现get_finall_urls()函数中的问题,处理方法与其一样
        pattern = re.compile("text:'" + '(.*?)' + "'", re.S)
        rangename_temp=str(table.cell(i,0))
        rangename=pattern.findall(rangename_temp)[0]
        url_temp=str(table.cell(i,1))
        url=pattern.findall(url_temp)[0]
        try:
            driver.get(url)
        except Exception:
            driver.get(url)
        time.sleep(2)
        # 获取房源详情页面
        html=driver.page_source
        # 解析详情页  获取所需信息
        selector = etree.HTML(html)
        try:
            #获取总价
            total_price=selector.xpath('//*[@class="total"]/text()')[0]
            #获取单价
            unit_price=selector.xpath('//*[@class="unitPriceValue"]/text()')[0]
            #获取小区名称
            apartment_name = selector.xpath('//*[@class="communityName"]/a[1]/text()')[0]
            # 获取所在区域
            inrange= selector.xpath('//*[@class="info"]/a[2]/text()')[0]
            # 通过正则表达式匹配获取经纬度信息
            pattern = re.compile("resblockPosition:'" + '(.*?)' + "',", re.S)
            pos = pattern.findall(html)[0]
            lon=pos.split(',')[0]
            lat=pos.split(',')[1]
            #获取基本信息 ,包括以下13个基本属性
            #1.房屋户型
            house_type=selector.xpath('//*[@class="base"]/div[2]/ul/li[1]/text()')
            #2所在楼层
            floor=selector.xpath('//*[@class="base"]/div[2]/ul/li[2]/text()')[0]
            # 3建筑面积
            out_area = selector.xpath('//*[@class="base"]/div[2]/ul/li[3]/text()')[0]
            # 4户型结构
            house_stru = selector.xpath('//*[@class="base"]/div[2]/ul/li[4]/text()')[0]
            # 5套内面积
            in_area = selector.xpath('//*[@class="base"]/div[2]/ul/li[5]/text()')[0]
            # 6建筑类型
            build_type = selector.xpath('//*[@class="base"]/div[2]/ul/li[6]/text()')[0]
            # 7房屋朝向
            house_direc = selector.xpath('//*[@class="base"]/div[2]/ul/li[7]/text()')[0]
            # 8建筑结构
            bulid_stru = selector.xpath('//*[@class="base"]/div[2]/ul/li[8]/text()')[0]
            # 9装修情况
            decorate = selector.xpath('//*[@class="base"]/div[2]/ul/li[9]/text()')[0]
            # 10梯户比例
            ratio = selector.xpath('//*[@class="base"]/div[2]/ul/li[10]/text()')[0]
            # 11供暖方式
            heating = selector.xpath('//*[@class="base"]/div[2]/ul/li[11]/text()')[0]
            # 12配备电梯
            elevator = selector.xpath('//*[@class="base"]/div[2]/ul/li[12]/text()')[0]
            # 13产权年限
            age_limit = selector.xpath('//*[@class="base"]/div[2]/ul/li[13]/text()')[0]
             #获取交易属性 ,包括以下8个
            #1.挂牌时间
            pull_time=selector.xpath('//*[@class="transaction"]/div[2]/ul/li[1]/span[2]/text()')[0]
            #2交易权属
            deal_owner=selector.xpath('//*[@class="transaction"]/div[2]/ul/li[2]/span[2]/text()')[0]
            # 3上次交易
            lasttime = selector.xpath('//*[@class="transaction"]/div[2]/ul/li[3]/span[2]/text()')[0]
            # 4房屋用途
            house_use = selector.xpath('//*[@class="transaction"]/div[2]/ul/li[4]/span[2]/text()')[0]
            # 5房屋年限
            house_age = selector.xpath('//*[@class="transaction"]/div[2]/ul/li[5]/span[2]/text()')[0]
            # 6产权所属
            right_owner = selector.xpath('//*[@class="transaction"]/div[2]/ul/li[6]/span[2]/text()')[0]
            # 7抵押信息,这里存在换行符和空格,需要处理
            pledge_info = selector.xpath('//*[@class="transaction"]/div[2]/ul/li[7]/span[2]/text()')[0].replace('\n','').replace(' ','')
            # 8房本备件
            house_part = selector.xpath('//*[@class="transaction"]/div[2]/ul/li[8]/span[2]/text()')[0]
        except Exception:
            continue
            #将获取的所有信息写入文本文件中
        f.write("%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%[email protected]%s"%(
            total_price,unit_price,apartment_name,inrange,lon,lat,house_type,floor,out_area,house_stru,in_area,
            build_type,house_direc,bulid_stru,decorate,ratio,heating,elevator,age_limit,pull_time,deal_owner,
            lasttime,house_use,house_age,right_owner,pledge_info,house_part
        ))
        f.write('\n')
        print(str(i+1))
    f.close()
    print('OK')
def main():
    #get_range_price_page_url()#调用一次即可,生成的excel文件range_price_page_urls.xls,将在get_finall_urls()中使用
    #get_finall_urls()#调用一次即可,生成的excel文件finall_urls.xls,将在get_house_info()中使用
    get_house_info()
if __name__=='__main__':
    main()