继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

利用python程序抓爬网页,获取城市楼市价格(Python学习实例二)

慕工程3455409
关注TA
已关注
手记 318
粉丝 78
获赞 293

一、本文实现目的

       通过Python语言抓取某房地产网页楼盘数据,用于后期楼盘分析。

       1、最后输出:某城市楼盘信息(即excel表格)。

       2、页面解析方法:正则表达式 + lxml第三方包

二、详细代码

       1、网页解析方法详解(本文只对使用到的两种解析方法进行讲解,别的方法后期使用时再补充)

           1)、正则表达式

                    主要原理是通过正则匹配,查询网页源代码中符合条件的数据,并把其提取出来。

                    如:下面这段代码,实现了在html这个对象(某个网页的源代码)中匹配有多少给“item-mod”字符串。

                           其中findall方法,要求匹配完html对象中的全部元素。

    h = r"item-mod" #正则代码
    h_re = re.compile(h) #生成正则
    href_all = h_re.findall(html)·

                     若需匹配字符串不确定,可以用正则表达式中的特定字符进行代替,如下面代码,通过[0-9]+代替数字进行匹配。              

    lppriceh = r"<span>[0-9]+</span>"
    lppriceh_re = re.compile(lppriceh)
    lppriceh_all = lppriceh_re.findall(html)

            2)、利用lxml包进行解析

                     该包的解析方法,类似于DOM数据的层次解析。如下图:


                     其中层次关系是如下:

                     第一层:html

                     第二层:head + body

                     第三层:head 下面(......)

                                   body 下面(div,div,......)

                     .......................

         代码:

        lpnamePath = '/html/body/div[2]/div[2]/div/div[4]/div/div/a/h3/span/text()'
        lpnameOBJ = htmlOBJ.xpath(lpnamePath)

         就是提取html -> body -> div[2](第二个div) -> div[2] ......-> span  标签中的文本。(如下图)

   

       2、xls的写入调用了,xlsxwriter第三方包进行实现


       3、完整代码如下:

import requests,re
from lxml import etree
import os
import string
import xlsxwriter

#所需抓去的网页地址
url = 'https://cd.fang.anjuke.com/loupan/all/p'

#结果xlsx保存地址
if os.path.exists(r'C:\cd\demo\result1.xlsx'):
    os.remove(r'C:\cd\demo\result1.xlsx)
wb = xlsxwriter.Workbook(r'C:\cd\demo\result1.xlsx)
sheet = wb.add_worksheet()
j=1
                         
#存储表头
name_row = [u'楼盘名',u'楼盘地址',u'楼盘状态1',u'楼盘状态2',u'楼盘价格',u'楼盘面积',u'无信息']
sheet.write(0,0,name_row[0])
sheet.write(0,1,name_row[1])
sheet.write(0,2,name_row[2])
sheet.write(0,3,name_row[3])
sheet.write(0,4,name_row[4])
sheet.write(0,5,name_row[5])
                         
for page in range(1,50):
    #获取相应的页数 并 拼接网址
    target_url = url + str(page) +'/' 
    #获取目标网址文档
    r = requests.get(target_url)
    #获取html代码
    html = r.text
    #需匹配的正则字符串
    h = r"item-mod" 
    #全文匹配
    h_re = re.compile(h) 
    href_all = h_re.findall(html)
    #获取网页中有多少个"item-mod"
    length = len(href_all)
                         
    #需对解析的网页源代码,进行utf-8格式表面,否则会乱码
    urlHTML = r.text.encode("utf-8")
    htmlOBJ = etree.HTML(urlHTML)
    
    #减5是因为"item-mod"比网页中。楼盘个数多5个,所以需要减5
    for i in range(0,length-5):
        #获取楼盘名
        lpnamePath = '/html/body/div[2]/div[2]/div/div[4]/div['+str(i+1)+']/div/a/h3/span/text()'
        lpnameOBJ = htmlOBJ.xpath(lpnamePath)
        sheet.write(j,0,lpnameOBJ[0])
                         
        #获取楼盘地址
        lpadrPath = '/html/body/div[2]/div[2]/div/div[4]/div['+str(i+1)+']/div/a[2]/span/text()'
        lpadrOBJ = htmlOBJ.xpath(lpadrPath)
        sheet.write(j,1,lpadrOBJ[0])
                         
        #获取楼盘状态
        lpztPath = '/html/body/div[2]/div[2]/div/div[4]/div['+str(i+1)+']/div/a[4]/div/i/text()'
        lpztOBJ = htmlOBJ.xpath(lpztPath)
        print len(lpztOBJ) 
        #如果部分楼盘信息为空,则显示无信息
        if len(lpztOBJ) >= 2 :
            sheet.write(j,2,lpztOBJ[0])
            sheet.write(j,3,lpztOBJ[1])            
        elif len(lpztOBJ) < 2 & len(lpztOBJ) >=1:
            sheet.write(j,2,lpztOBJ[0])
            sheet.write(j,3,name_row[6])
        else:
            sheet.write(j,2,name_row[6])
            sheet.write(j,3,name_row[6])
                         
        #获取楼盘价格
        #判断是否有价格字段
        lppricePath = '/html/body/div[2]/div[2]/div/div[4]/div['+str(i+1)+']/a[2]/p[2]/span/text()'
        lppriceOBJ = htmlOBJ.xpath(lppricePath)
        if len(lppriceOBJ) <= 0:
            lppricePath = '/html/body/div[2]/div[2]/div/div[4]/div['+str(i+1)+']/a[2]/p[1]/span/text()'
            lppriceOBJ = htmlOBJ.xpath(lppricePath) 
            if len(lppriceOBJ) <= 0:
                sheet.write(j,4,name_row[6])
            else:
                sheet.write(j,4,lppriceOBJ[0])
        else:
            sheet.write(j,4,lppriceOBJ[0])
                         
        #获取楼盘面积
        squPath = '/html/body/div[2]/div[2]/div/div[4]/div['+str(i+1)+']/div/a[3]/span/text()'
        squOBJ = htmlOBJ.xpath(squPath)
        if len(squOBJ)-1 <= 0:
            sheet.write(j,5,name_row[6])
        else:
            sheet.write(j,5,squOBJ[len(squOBJ)-1])
        j = j + 1
#关闭写入通道
wb.close()


注:

1、在xls中写入表头是,在定义中文数组的时候一定要在没有元素前加U,如下:

name_row = [u'楼盘名',u'楼盘地址',u'楼盘状态1',u'楼盘状态2',u'楼盘价格',u'楼盘面积',u'无信息']

2、因为网页页面在不断变化,可能代码在运行中报错,需要根据其报错原因进行修改。

原文出处

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP