链家网是集房源信息搜索、产品研发、大数据处理、服务标准建立为一体的以数据驱动的全价值链房产服务平台。主营:二手房、租房、新房。通过链家网的数据可以很方便的获取商品房的市场信息
此次目的是抓取链家网广州地区二手房的数据
首先明确步骤:

  1. 分析网页
  2. 分析数据节点
  3. 编写爬虫程序
  4. 存储数据

首先分析网页
链家网网址在这 广州链家网二手房

可以看到一共有25934套房源,数据是更新的,我爬取得时候是没有这么多数据的
接下来观察网页构造

可以观察到一个网页是有30个< li >标签,一个标签对应一个房源信息,而且网页只有100页,我们通过观察发现网页的翻页只是在源地址后面加个pg的变量
但是实测将pg填101会重新跳转到第一页,所以我们一共可以观察到3000的信息,后面的无法获取,需要重新观察

通过观察发现可以按照地区的分类进去抓取数据,而且每个地区的成交数量都没有超过3000套。也就是我们可以在100页内将数据全部抓取。

通过观察发现各个房源的标签是不一样的,而且实测无法在列表页就实现数据的全部抓取,所以我们只能到房源详情页进行抓取

在这里我们确定我们要抓的数据是售价,平方单价,挂牌价,关注人数,房屋户型,所在楼层等等
那么现在爬虫思路就是

  1. 先爬取所有地区链接
  2. 根据地区链接,在各地区链接下抓取所有列表房源的url
  3. 根据抓取到的房源url进行访问抓取数据
    接下来就是代码的构建了
    首先先抓取所有地区并存储在数据库中:
import requests
from urllib.parse import urljoin
from scrapy.selector import Selector
import pymongo
from fake_useragent import UserAgentua = UserAgent()
Mymongo = pymongo.MongoClient('localhost', 27017)  # 连接本地服务
lianjia = Mymongo['lianjia']   # 链接数据库
region_url_collection = lianjia['region_url']  # 集合对象
base_url = "https://gz.lianjia.com/chengjiao/"
region_list = ['tianhe', 'yuexiu', 'liwan', 'haizhu', 'panyu', 'baiyun', 'huangpugz', 'conghua', 'zengcheng', 'huadou', 'nansha']def get_region_url():for i in range(0, len(region_list)):url = urljoin(base_url, region_list[i])  # 拼接URLresponse = requests.get(url, headers={'User-Agent': str(ua.random)}).textselector = Selector(text=response)area_url_list = selector.xpath('/html/body/div[3]/div[1]/dl[2]/dd/div/div[2]/a/@href').extract()  # 获取地址列表for url in area_url_list:region_url = urljoin(base_url, url)region_url_collection.insert_one({'region_url': region_url})  # 插入数据get_region_url()

这里需要注意的是黄埔、花都在url里面的表示不是按照拼音来的,有点坑人,我找了一会才发现原因
地区数据如下:

可以看到抓取的数据是有295个,但是实际是有重复的数据存在
例如点击越秀分类下的“同德围”会跳到白云区下面,所有后面需要进行去重处理
接下来是获取列表页中房源的地址ID

import requests
from bs4 import BeautifulSoup
import pymongo
from fake_useragent import UserAgent
import time
import pandas as pdua = UserAgent()
Mymongo = pymongo.MongoClient('localhost', 27017)
lianjia = Mymongo['lianjia']
house_id_collection = lianjia['house_id']
region_url_collection = lianjia['region_url']
missing_url_collection = lianjia['missing_url']
base_url = "https://gz.lianjia.com/chengjiao/"def get_house_id(region_url):response = requests.get(region_url, headers={'User-Agent': str(ua.random)}).textsoup = BeautifulSoup(response, 'lxml')house_num = soup.select('div.total.fl > span')# page_num = int(int(house_num[0].get_text())/30)page_num = int(int(house_num[0].get_text())/30)+1 if int(house_num[0].get_text()) > 30 else 1  # 获取页码for i in range(1, page_num+1):time.sleep(1)current_url = region_url + 'pg{}'.format(i)  # 拼接URLresponse = requests.get(current_url, headers={'User-Agent': str(ua.random)}).textsoup = BeautifulSoup(response, 'lxml')house_num_test = soup.select('div.resultDes.clear > div.total.fl > span')if int(house_num_test[0].get_text()) != 0:for house_url in soup.select("div.info > div.title > a"):house_id = house_url['href'].split('.html')[0].split('/')[-1]house_id_collection.insert_one({'house_id': house_id})else:print(current_url)# missing_url_collection.insert_one(current_url)def get_all_house_id():data = pd.DataFrame(list(region_url_collection.find()))for region_url in list(set(data['region_url'])):   # 经过观察发现有重复的地区地址,用set集合去重后再转化为listget_house_id(region_url)get_all_house_id()

这里我们使用set()集合来对整个列表进行去重,实测只有243个地区
这里的翻页我们是先抓取地区链接下的房源总数,通过一页有30套房子的模式,与30整除向上取整就可以得到页码的数量了

如图我们发现天河-车陂下的房源总数是101,所以它的页数应该是101/30+1=4,一共四页
获取到的ID如下:

接下来就是获取详细信息页的数据啦

import requests
from bs4 import BeautifulSoup
from scrapy.selector import Selector
import pymongo
from fake_useragent import UserAgent
import pandas as pd
import time
from multiprocessing import Poolua = UserAgent()
cilent = pymongo.MongoClient('localhost', 27017)  # 数据库连接
lianjia = cilent['lianjia']   # 数据库连接对象
house_info_collection = lianjia['house_info']  # 数据集合对象
house_url_collection = lianjia['house_url']
missing_house_info = lianjia['missing_house_info']
house_url_collection_success = lianjia['house_url_collection_success']
data = pd.DataFrame(list(house_url_collection.find()))  # 使用pandas的DataFrame结构提取出来
proxy = ['HTTPS://111.176.28.176:9999','HTTPS://119.101.117.114:9999','HTTPS://119.101.118.115:9999','HTTPS://119.101.116.219:9999','HTTPS://119.101.113.185:9999','HTTPS://119.101.113.25:9999','HTTPS://119.101.117.143:9999','HTTPS://114.116.10.21:3128','HTTPS://60.6.241.72:808','HTTPS://113.105.170.139:3128','HTTPS://114.99.2.201:9999','HTTPS://119.101.113.213:9999',
]def get_house_info(url):wb_data = requests.get(url, headers={'User-Agent': str(ua.random)})#  wb_data = requests.get(url, headers={'User-Agent': str(ua.random)},proxies={'https': random.choice(proxy)})if wb_data.status_code == 200:# 实测不用睡眠也可以实现抓取# time.sleep(1)  # 睡眠1秒soup = BeautifulSoup(wb_data.text, 'lxml')selector = Selector(text=wb_data.text)title = soup.select('h1')[0].get_text()  # 标题deal_date = soup.select('body > div.house-title > div > span')[0].get_text()  # 成交时间house_position = soup.select('div.myAgent > div.name > a')[0].get_text()  # 所处区域dealTotalPrice = soup.select('div.price > span > i')[0].get_text()   # 成交价格unit_price = soup.select('div.price > b')[0].get_text()  # 单价list_price = soup.select('div.info.fr > div.msg > span:nth-of-type(1) > label')[0].get_text()  # 挂牌价focus_num = soup.select('div.info.fr > div.msg > span:nth-of-type(5) > label')[0].get_text()  # 关注人数# floor = soup.select('div.base > div.content > ul > li:nth-of-type(2)')# 使用css selector会将li标签下的所有文字全都抓取过来,此处使用xpathfloor = selector.xpath('//div[@class="base"]/div[2]/ul/li[2]/text()').extract()   # 楼层house_orientation = selector.xpath('//div[@class="base"]/div[2]/ul/li[7]/text()').extract()   # 房屋朝向built_date = selector.xpath('//div[@class="base"]/div[2]/ul/li[8]/text()').extract()  # 房屋建成年限elevator = selector.xpath('//div[@class="base"]/div[2]/ul/li[14]/text()').extract()  # 有无电梯subway = '有' if soup.find_all('a', 'tag is_near_subway') else '无'data = {'house_type': title.split(' ')[1],   # 户型'area': title.split(' ')[-1].split('平')[0],   # 房屋面积'deal_date': deal_date.split(' ')[0],   # 成交日期'house_position': house_position,   # 所属区域'dealTotalPrice': dealTotalPrice,   # 成交价格'unit_price': unit_price,  # 单价'list_price': list_price,  # 挂牌价'focus_num': focus_num,   # 关注人数'floor': floor[0].split('(')[0],  # 楼层数'house_orientation': house_orientation[0].split(' ')[0],   # 房屋朝向'built_date': built_date[0],   # 建成年限'elevator': elevator[0].split(' ')[0],   # 有无电梯'subway': subway  # 有无地铁}house_info_collection.insert_one(data)house_url_collection_success.insert_one({'house_id': url})   # 收集已抓取的url,ruelse:missing_house_info.insert_one({'missing_house_url': url})  # 将抓取错误的url收集起来,如果出现错误就可以根据url重新抓取if __name__ == '__main__':pool = Pool(processes=8)pool.map(get_house_info, list(data['house_url']))  # 使用pool的map函数pool.close()  # 关闭进程池,不再接受新的进程pool.join()  # 主进程阻塞等待子进程的退出

首先考虑到网站的反爬,我们使用对各IP进行抓取,考虑到数量也很大,我们使用多进程进行爬取,IP最好是使用付费代理IP,这样子会稳些,我的IP是在西刺爬取的,具体爬取可以观看这篇文章大批量抓取西刺代理,在这里我们将IP验证地址设置为链家网,用链家网进行IP验证。获取到IP后就可以进行爬取了。
PS:我在这次爬取,虽然过滤了IP,可是爬取一阵子后IP就会挂掉,非常不友好,所以我试了不用IP,使用单个IP,然后睡眠1秒来试试网站怎么封禁IP,结果我发现我开了多线程,不设置睡眠,居然也可以将所有数据抓取下来,这里要表白链家网,不过大家还是设置睡眠吧,不要给服务器过多压力
这里我们开了8个进程,在跑数据分过程发现程序会报出如下错误

上了Google,发现因为是多进程,无法得知索引信息,也就是说不知道哪些ID已经删除了,哪些还没删除。所以其实在抓取页面的代码那里,我们应该设置每次抓取url,就将他从数据库中delete掉,之前没想到,是另外用了一个爬取成功表,每次使用所有的url减去成功的url,剩下的就是未爬取的,但错误还是会发生,后来发现是有些房子缺少数据,导致网页的构造不一样,无法获取数据

如图,暂无数据这个标签与本应该的房价在网页的结构不一样,无法判断,所以只能每次程序中断后继续跑,慢慢缩小,后面手动删除暂无数据的url,毕竟只是少数,这里就是我们获取的数据啦

其实如果没有异常页的出现,在8个进程以及没有设置睡眠的情况下,我们可以在15分钟内获取到所有数据。多进程真是个好东西。
这里是全部地址列表页删除爬取成功页的url的代码:

import pymongo
import pandas as pdcilent = pymongo.MongoClient('localhost', 27017)
lianjia = cilent['lianjia']
house_url_collection = lianjia['house_url']
house_url_collection_succcess = lianjia['house_url_collection_success']data = pd.DataFrame(list(house_url_collection_succcess.find()))
data1 = pd.DataFrame(list(house_url_collection.find()))
for url in list(data['house_id']):if url in list(data1['house_url']):house_url_collection.delete_one({'house_url': url})else:pass

至此就全部结束啦,接下来就拿着数据去分析吧。

多线程抓取链家网数据相关推荐

  1. Python爬虫攻略(2)Selenium+多线程爬取链家网二手房信息

    申明:本文对爬取的数据仅做学习使用,请勿使用爬取的数据做任何商业活动,侵删 前戏 安装Selenium: pip install selenium 如果下载速度较慢, 推荐使用国内源: pip ins ...

  2. 链家java_java爬取链家网数据

    int num = 1; String path = "D:\\房源信息.txt"; BufferedWriter bf = new BufferedWriter(new File ...

  3. 基于python多线程和Scrapy爬取链家网房价成交信息

    文章目录 知识背景 Scrapy- spider 爬虫框架 SQLite数据库 python多线程 爬取流程详解 爬取房价信息 封装数据库类,方便多线程操作 数据库插入操作 构建爬虫爬取数据 基于百度 ...

  4. python找房源_python抓取链家房源信息(二)

    试着用scrapy将之前写的抓取链家网信息的重新写了写 然后先是用了第一页的网页作为测试,调试代码,然后发现总是抓取的时候遇见了 类似于这样的问题,并且抓取不到信息 2017-03-28 17:52: ...

  5. python爬虫之scrapy初试与抓取链家成交房产记录

    接上一篇文章,本机安装好python之后和scrapy之后,我们开始学习使用scrapy创建爬虫程序. 今天先来点简单的,不那么复杂,先看看抓取链家网里面的房价信息. 首先使用CMD命令行进入F盘创建 ...

  6. Python爬虫三:抓取链家已成交二手房信息(58W数据)

    环境:Windows7+python3.6+Pycharm2017 目标:抓取链家北京地区已成交二手房信息(无需登录),如下图,户型.朝向.成交时间价格等,保存到csv.最后一共抓取约58W数据,程序 ...

  7. python 爬取链家数据_用python爬取链家网的二手房信息

    题外话:这几天用python做题,算是有头有尾地完成了.这两天会抽空把我的思路和方法,还有代码贴出来,供python的初学者参考.我python的实战经历不多,所以代码也是简单易懂的那种.当然过程中还 ...

  8. 爬取链家网二手房数据并保存到mongodb中

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 爬取链家网二手房数据并保存到mongodb中 文章目录 前言 一.爬虫的介绍 二.协程的介绍 三.css选择器 四.基于asyncio ...

  9. Scrapy实战篇(一)之爬取链家网成交房源数据(上)

    今天,我们就以链家网南京地区为例,来学习爬取链家网的成交房源数据. 这里推荐使用火狐浏览器,并且安装firebug和firepath两款插件,你会发现,这两款插件会给我们后续的数据提取带来很大的方便. ...

  10. 十七、爬虫实战,多线程抓取大搜网新车的数据

    上次爬取毛豆新车的数据 十六.爬虫实战,多线程抓取毛豆新车的数据 这次爬取大搜车卖车 爬虫实战 对于之前学的知识,作一个整合,爬取大搜车卖车信息 目标:爬取大搜车卖车信息,并写入mongodb数据库 ...

最新文章

  1. Cluster模式潜在问题及解决方案、Web服务综合解决方案
  2. django13:Session与Cookie操作
  3. void Update ( ) 更新 void FixedUpdate ( )
  4. 机器学习之 sklearn.preprocessing 模块
  5. 一个人成为废材的9大原因
  6. 前端基础:初步认识Chrome调试面板,学会简单的代码调试,必会!
  7. havlenapetr ffmpeg的移植
  8. signature=ad248ee50cb35fb429594f302bf99ddf,动态源路由协议在无线自组网中的研究与应用...
  9. python爬取学校题库_Python爬虫面试题
  10. PAT1018. Public Bike Management (30)
  11. mybatis mysql crud_mybatis实现CRUD操作(mysql数据库)(二)
  12. 计算机软件的初始密码,怎么设置电脑软件密码
  13. Vue中data数据变化 -- 页面重新渲染的问题
  14. ubuntu之使用wine微信之无法发送图片
  15. 《终身成长》读书分享(附思维导图)
  16. vue3组件之间通信(二)——子传父属性和方法
  17. 《StereoDRNet: Dilated Residual StereoNet》
  18. OI生涯回忆录(Part3:至初三NOIP发成绩)
  19. 如何从JavaScript中的数组替换元素?
  20. 用matlab实现蛇形,matlab蛇形机械手仿真建模

热门文章

  1. navicat输入法问题
  2. 南昌航空大学961数据结构真题答案
  3. Linux版QQ安装教程
  4. emouse思·睿—评论与观点整理之四
  5. 【超详细教程】告别证书,图文并茂教你免签名XX,三种方法任你选!超简单...
  6. 手机上最好用的五笔输入法_手机输入法哪家最好用?我推荐百度,不好用你打我...
  7. 拆机清灰重装系统数据恢复——心得汇总
  8. Android 获取应用签名
  9. 整理与随笔——抽象代数 第一章 群 1.1-1.2 代数体系、半群与群
  10. 发电机变压器运行状态(温度电压电流)监控系统解决方案