对长沙房地产数据的挖掘与分析【一】

今天我们来讲一个新专题:爬取链家网”长沙小区房地产数据,并对长沙房地产信息做数据挖掘与分析

这个专题标题有点长,暂时就简略为:对长沙房地产数据的挖掘与分析。

这个专题将包含以下几个内容:

  • 如何抓取网页源码

  • 如何解析数据元素

  • 如何使用MongoDB存储数据内容

  • 如何将数据做进一步的分析,得出一些有意思的结论。

今天我们就讲一讲对长沙房地产数据的挖掘与分析【一】,今天的内容不多,主要包含:

  • 安装MongoDB数据库。

  • 预习一下Http协议工作原理及requests,正则表达式re和MongoDB库。

  • 抓取长沙小区2500多个小区的小区名称及对应的小区链接。

一、安装MongoDB和数据库可视化软件

1.1. 安装MongoDB

首先安装MongoDB数据库,我建议安装2.6版本,网上下载mongoDB2.6安装。安装的具体步骤可以参照下面这个视频。

定向爬虫:MongoDB 与 Scrapy

这个视频是以一种批处理的方式启动MongoDB,省去了繁杂的代码启动服务,可以参考一下哦。

1.2. 安装数据库可视化软件。

推荐安装MongoVUE,具体请到官网或其它网站下载。MongoVUE有很多功能,我主要用它来查看数据,并且导出xls数据文件,十分方便。

当然,还可以下载另外一款MongoDB数据库可视化软件:NoSQL Manager for MongoDB,也蛮方便的。

二、熟悉HTTP协议工作原理及requests,正则表达式re和pymongo库

2.1 熟悉HTTP协议工作原理

抓取网页源码很简单,但是在这之前我们应该熟悉一下http的工作原理。

简言之就是三次握手四次挥手,建立TCP需要三次握手才能建立,而断开连接则需要四次握手。

(1)客户端连接到Web服务器

一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。

(2)发送HTTP请求

通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。

(3)服务器接受请求并返回HTTP响应

Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。

(4)释放连接TCP连接

Web服务器主动关闭TCP套接字,释放TCP连接;客户端被动关闭TCP套接字,释放TCP连接。

(5)客户端浏览器解析HTML内容

客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。

完成(5)后整个html内容就会被客户端浏览器读取,这是B/S架构。当然,还有C/S架构,有兴趣的也可以了解一下。

爬虫就是要模拟浏览器,发消息头,建立TCP连接,所以,整个过程越是将浏览器模拟的真实,服务器端能判断出来是Robot的概率越小,爬取的成功率就越高。

2.2 预习requests库

本次爬虫,我们不打算用urllib,urllib2这两个自带的库,而是采用这个requests这个库爬取。requests是个绝佳的库,安装pip,通过pip install requests安装这个库函数。剩余的网上多查看一下这个库的教程文档。希望大家可以预先了解它,并且能熟练掌握它。

2.3 预习re库

正则表达式re功能强大,执行效率高,具体请参考:

Python正则表达式指南

主要用到的:

《对长沙房地产数据的挖掘与分析【一】》
《对长沙房地产数据的挖掘与分析【一】》
《对长沙房地产数据的挖掘与分析【一】》
《对长沙房地产数据的挖掘与分析【一】》
2.4 预习pymongo库

pymongo是python操作MongoDB数据库的一个非常常用的模块。

一般可以用:

import pymongo
client = MongoClient('localhost','27017')#数据库地址及端口号
dbName = 'lianjia'

#数据库名称
dbTable = 'xiaoqu'
#表的名称
tab = client[dbName][dbTable]
#连接数据库

具体pymongo的介绍可参考:

Python 操作 MongoDB

三、抓取长沙小区2500多个小区的小区名称及对应的小区链接

由于要爬取长沙2500多个小区,其中包括各种信息,包括小区名称,建成时间,物业费,小区经纬度,小区所在市区,楼栋数,总户数等一系列的数据。为防止爬取有误。为保险起见,一般来说,我会分拆为多个小节。比如,我可以先将小区名称以及该小区对应的网址入库。这样,下次我就可以不用从一级网址入口,直接从二级网址,即每个小区链接入口爬取就可以了。这样做的优点时,可随时暂停或终止爬取,不需重复劳动,避免不可控因素。

先上本小节python爬虫代码(采用的是python2.7):

主代码:

# _*_coding:utf-8_*_
import time
import requests
from pub_fuc import re_fuc
from pymongo import MongoClient
import sys
reload(sys)
sys.setdefaultencoding( "utf-8" )

client = MongoClient()
dbName = 'lianjia'
dbTable = 'xiaoqu'
tab = client[dbName][dbTable]

def getresp(req, retries = 2):
    try:
        headers = {
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
            'Accept-Encoding': 'gzip, deflate, sdch',
            'Accept-Language': 'zh-CN,zh;q=0.8',
            'Cache-Control': 'max-age=0',
            'Connection': 'keep-alive',
            'Host': 'cs.lianjia.com',
            'Upgrade-Insecure-Requests': '1',
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36',
        }
        ses = requests.session()
        ses.get('http://cs.lianjia.com/xiaoqu/rs/')
        html = ses.post(req, headers=headers)
        data = html.text.encode('iso8859-1').decode('utf-8')
    except Exception, what:
        print what, req
        if retries > 0:
            return getresp(req, retries - 1)
        else:
            print 'GET Failed', req
            return ''
    return data

main_url = 'http://cs.lianjia.com/xiaoqu/rs/'
cont = getresp(main_url)

rel = [r'<div class="info"><div class="title"><a href="(.*?)" target="_blank" data-bl="list" data-log_index=".*?data-el="xiaoqu">(.*?)</a>']
xiaoqu = re_fuc(cont, rel, 'choice_route')
for x in xiaoqu:
    key = {'xiaoqu':x[1], 'url':x[0]}
    tab.insert(key)
print '第1页爬取成功!'

for i in xrange(2, 82, 1):
    print '开始爬取第%s页'%(str(i))
    main_url= 'http://cs.lianjia.com/xiaoqu/pg%s/'%(str(i))
    cont = getresp(main_url)
    rel = [r'<div class="info"><div class="title"><a href="(.*?)" target="_blank" data-bl="list" data-log_index=".*?data-el="xiaoqu">(.*?)</a>']
    xiaoqu = re_fuc(cont, rel, 'choice_route')
    for x in xiaoqu:
        #print x[0],x[1]
        key = {'xiaoqu':x[1], 'url':x[0]}
        tab.insert(key)
    print '第%s页爬取成功!' % (str(i))
    time.sleep(1)

re_fuc.py代码:

#-*-coding:utf8-*-
import re

def re_fuc(cont,rel_list,id_data):
    for rel in rel_list:
        try:
            c = re.compile(rel)
            ret = re.findall(c, cont)
            if ret:
                return ret
            else:
                pass
        except:
            pass

    return None

本次代码没有什么难度(嘿嘿,我也写不出有难度的代码出来哟~),简单解释一下:

  1. getresp函数是重试函数,就是一次请求不成功后,再次请求。默认请求次数为2次。
  2. 加入了headers,headers是模拟浏览器发消息头,相信预习了http的三次握手过程之后,对这个应该是有了解的。

  3. 用了正则表达式。正则表达式需要了解贪婪模式和非贪婪模式。以及. * ?三个字符含义。正则表达式执行效率比较高。对于html的元素提取,我们以后还会讲到lxml。

  4. MongoDB的字典插入。

  5. re_fuc.py代码就是对网页元素的匹配做了一次封装。

爬取完成的TABLE表应该是这样的:

《对长沙房地产数据的挖掘与分析【一】》
《对长沙房地产数据的挖掘与分析【一】》

学完本节,你应该掌握:

  • 安装MongoDB数据库。

  • 了解Http协议工作原理及requests,re及pymongo模块。

  • 能自己动手抓取简单的html源码,能够提取出简单的元素并能存储进数据库。

留个问题,如果中途因为某种原因爬虫被迫终止了,是否又要删数据,重新抓取呢?如果不需要,代码上应该怎么自动去重呢?

注:如何实现增量式抓取,如何设计良好的数据库,做到实时更新,快速化判重并减少冗余数据存储是爬虫非常重要的技能。

下一讲讲述:对长沙房地产数据的挖掘与分析【二】。下一节,我们将对这些网址做二次入口爬取。另本专题全部章节将于微信公众号【一只IT汪】首发,欢迎大家的关注,谢谢!

一只IT汪】公众号刚开通,暂时没有多少内容,但以后会有更多惊喜哟~ 公众号回复您的暂时是微信机器人,别被微信机器人调戏了哈~

本系列教程将不定期更新,敬请关注 :)

如果喜欢,请一定记得点赞哟~ 你的赞就是我更新的动力~ o(*≧▽≦)ツ

    原文作者:蚍蜉撼大树
    原文地址: https://zhuanlan.zhihu.com/p/23114562
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞