环境:Windows10+Anaconda python3.6.5+Spyder
目标:抓取链家北京地区所有房源信息。

打开链家官网 https://bj.lianjia.com/ 。粗略的浏览了一下,整个网站使用的都是静态网页,通过改变url来实现网页变动。不过网站默认只显示100页的内容,每页30条,不管那里写着多少多少条数据。

如果需要抓取所有数据,必须通过某些条件筛选。有地区、价格、朝向、楼层等,这里面我选择了地区,因为这是区分度比较明确的,如果选择其他可能会出现同样的数据,就多了一步去重的操作。而且地区就那么多,一次获取,可以同时用在在售、成交和租房。

先获取首页的地区对应的url(每一个地区都是超链接),如下图:

通过url再获取进一步区域的url,如下图:

虽然这里显示到香河,但是点击香河发现还有区域在其他的网页,这里只能将url加入一个列表,然后判断新的url是否在列表里,有就舍弃,没有则添加并获取进一步区域的信息。(而且这里还有一个很奇怪,我爬取的是北京的,所有url的host应该是bj.lianjia.com,但香河的host确是lf.lianjia.com。后面很多url都是相对路径需要手动添加host,于是又多了一步host的判断)

第一步抓取的信息如下图(这一次抓取并没有什么阻碍,全部获取到):

这里插一个经验:我看到很多人在这里直接将url设为_id ,这样可以直接达到去重的效果,但需要捕获异常,还有一种是update,效率是真的低的可怕(我更新的是几百万条的数据)。所以我觉得还是直接将url设为_id 去重好一点。(如果有更好的方法,还请留言指教)

第二次抓取的信息(小区),这一次抓取,sleep时间无论是随机2-5秒还是5秒都会在抓取几条之后返回404,这样只能使用代理和随机头信息。不过我没有代理,以前写的aiohttp测试的代理,居然不支持https的网站,http的网站一切正常(还是我大requests强大,就是有点慢),而且居然还有地区的小区数量大于3000,算了就这样吧:

第三步则抓取小区下的房源信息:
在这里房源url是有规律的,所有没有必要访问小区的url。
小区的url格式:https://bj.lianjia.com/xiaoqu/1111027378891/
二手房成交url:https://bj.lianjia.com/chengjiao/c1111027378891/
在售url:https://bj.lianjia.com/ershoufang/c1111027378891/
租房url:https://bj.lianjia.com/zufang/c1111027380887/
所以只需要正则获取后面的一串数字,然后构造就行。这样还能将chengjiao的那部分设为变量,然后三个网站只需要一个程序就行。(而且在多次尝试发现,小区的url里面可能没有成交房源的信息,但手工构造的url却能访问,也包含正常信息,这就有点坑了)

第一步代码:

date: Fri Nov 23 10:41:25 2018
python: Anaconda 3.6.5
author: kanade
email: kanade@blisst.cn
"""
import re
import requests
import pyquery
import pymongoclass Area(object):'''获取北京链家的所有地区的url'''def __init__(self):self.start_url = 'https://bj.lianjia.com/xiaoqu/'self.client = pymongo.MongoClient()self.db = self.client['lianjia']['area']self.regex = re.compile(r'\w\w\.lianjia\.com') # 提取host的正则def get_html(self, url, session):'''请求url,返回host和响应内容'''# 提取url中的host作为请求头参数host = re.search(self.regex, url).group()headers = {'Host':host,'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.61 Safari/537.36'}resp = session.get(url, headers=headers)if resp.status_code == 200:return host, resp.textdef extract_html(self, html, query_rule):'''使用pyquery提取网页中的区域和它相对应的url'''host, html = htmldoc = pyquery.PyQuery(html)items = doc(query_rule).items()for item in items:area = item.text()url = item.attr.hrefif url.startswith('/'):url = 'https://' + host + urlyield area, urldef run(self):'''运行函数,因为最多只有两页地区信息,所以只有两个循环'''session = requests.Session()html = self.get_html(self.start_url, session)self.area_url = list(self.extract_html(html, 'div[data-role="ershoufang"] a'))# 获取详细的小区信息,并存储到MongoDBfor area, url in self.area_url:html = self.get_html(url, session)xiaoqu = self.extract_html(html, 'div[data-role="ershoufang"] div:last-child a')for sub_area, sub_url in xiaoqu:d = {'area':area,'xiaoqu':sub_area,'url':sub_url}self.db.insert_one(d)#time.sleep(0.5)# html为上一次循环最后一个网页,再提取一遍地区,如果和上次相同则舍弃,否则获取小区for area_url in self.extract_html(html, 'div[data-role="ershoufang"] div:first-child a'):if area_url not in self.area_url:area, url = area_urlhtml = self.get_html(url, session)xiaoqu = self.extract_html(html, 'div[data-role="ershoufang"] div:last-child a')for sub_area, sub_url in xiaoqu:d = {'area':area,'xiaoqu':sub_area,'url':sub_url}self.db.insert_one(d)if __name__ == '__main__':a = Area()a.run()

第二步代码:

# -*- coding: utf-8 -*-
"""
date: Fri Nov 23 15:07:38 2018
python: Anaconda 3.6.5
author: kanade
email: kanade@blisst.cn
"""
import re
import time
import random
import requests
import pyquery
import pymongoclass XiaoQu(object):'''获取地区下的所有小区的url'''def __init__(self):self.client = pymongo.MongoClient()self.db_xiaoqu = self.client['lianjia']['xiaoqu']self.regex = re.compile(r'\w\w\.lianjia\.com')def random_time(self):i = random.randint(2, 4)j = random.random()return i + jdef get_html(self, url, session):host = re.search(self.regex, url).group()headers = {'Host':host,'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.61 Safari/537.36'}resp = session.get(url, headers=headers)print(resp.status_code)if resp.status_code == 200:return host, resp.textdef run_one(self, url):session = requests.Session()html = self.get_html(url, session)doc = pyquery.PyQuery(html[1])count = int(doc('.resultDes.clear h2.total span').text().strip())if count == 0:returnself.extract(html)if count % 30 == 0:count = count // 30else:count = count //30 + 1time.sleep(2)for page in range(2, count+1):if url.endswith('/'):url += 'pg' + str(page) + '/'else:url += '/pg' + str(page) + '/'html = self.get_html(url, session)self.extract(html)t = self.random_time()time.sleep(t) def run(self):    db_area = self.client['lianjia']['area']for data in db_area.find().skip(222):print(data['area'],data['xiaoqu'])self.run_one(data['url'])def extract(self, html):host, html = htmldoc = pyquery.PyQuery(html)data = []items = doc('li.xiaoquListItem').items()for item in items:name = item.find('.title a').text()url = item.find('.title a').attr.hrefif url.startswith('/'):url = 'https://' + host + urld = {'name':name,'url':url}data.append(d)self.db_xiaoqu.insert_many(data)if __name__ == '__main__':xq = XiaoQu()xq.run()

第三步代码:

# -*- coding: utf-8 -*-
"""
date: Sat Nov 24 11:10:05 2018
python: Anaconda 3.6.5
author: kanade
email: kanade@blisst.cn
"""
import time
import re
import requests
import pyquery
import pymongoclass FangYuan(object):'''从数据库拿到小区的链接,然后抓取小区的房源信息'''def __init__(self):client = pymongo.MongoClient()self.db = client['lianjia']self.regex = re.compile(r'\w\w\.lianjia\.com')def get_html(self, url, session):host = re.search(self.regex, url).group() headers = {'Host':host,'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.61 Safari/537.36'}resp = session.get(url, headers=headers)print(resp.status_code)if resp.status_code == 200:return resp.textdef run_one(self, url):host = re.search(self.regex, url).group() url_id = re.search(r'/(\d+)', url).group(1)url = 'https://' + host + '/chengjiao' + '/c' + url_id + '/'session = requests.Session()html = self.get_html(url, session)doc = pyquery.PyQuery(html)count = int(doc('.resultDes.clear .total span').text().strip())if not html or count == 0:returnself.extract(html, host)if count % 30 == 0:count = count // 30else:count = count // 30 + 1time.sleep(2)for page in range(2, count+1):url = 'https://' + host + '/chengjiao'+\'/pg'+str(page)+'c'+url_id +'/'html = self.get_html(url, session)self.extract(html, host)time.sleep(3)def run(self):for i in self.db['xiaoqu'].find():self.run_one(i['url'])def extract(self, html, host):doc = pyquery.PyQuery(html)items = doc('ul.listContent li').items()for item in items:img = item.find('.img').attr.hreftitle = item.find('.title a').text()url = item.find('.title a').attr.hreftime_ = item.find('.address .dealDate').text()price = item.find('.address .totalPrice').text()every_price = item.find('.flood unitPrice').text()describe_1 = item.find('.address .houseInfo').text()describe_2 = item.find('.flood .positionInfo').text()describe_3 = item.find('.dealHouseInfo').text()describe_4 = item.find('.dealCycleeInfo').text()describe = describe_1.strip() + '\n' +  describe_2.strip() +\'\n' + describe_3.strip() +'\n'+ describe_4.strip()if url.startswith('/'):url = 'https://' + host + urld = { 'img':img,'title':title,'url':url,'time':time_,'price':price,'every_price':every_price,'describe':describe}self.db['fangyuan'].insert_one(d)if __name__ == '__main__':fy = FangYuan()fy.run_one('https://bj.lianjia.com/xiaoqu/1111027378889/')  #fy.run()           

如果想要全部房源信息,需要加入代理。我就不加了,没加代理很快就会返回404。因为只是学习思路,这个爬虫并不成熟,没有异常处理,也没有特殊情况处理,而且爬虫还可以在宏观一点,获取每个城市的url。有能力或者需求的可以自行添加。

爬取链家所有房源信息(在售、成交、租房)相关推荐

  1. 如何高效地爬取链家的房源信息(四)

    "Python实现的链家网站的爬虫第四部分,最后一部分." 本系列文将以链家南京站为例,使用Python实现链家二手房源信息的爬虫,将数据爬取,并存入数据库中,以便使用. 本系列第 ...

  2. 如何高效地爬取链家的房源信息(三)

    "Python实现的链家网站的爬虫第三部分." 本系列文将以链家南京站为例,使用Python实现链家二手房源信息的爬虫,将数据爬取,并存入数据库中,以便使用. 本系列第一部分为基础 ...

  3. 如何高效地爬取链家的房源信息(二)

    "Python实现的链家网站的爬虫第二部分." 本系列文将以链家南京站为例,使用Python实现链家二手房源信息的爬虫,将数据爬取,并存入数据库中,以便使用. 本系列第一部分: 如 ...

  4. python+selenium爬取链家网房源信息并保存至csv

    python+selenium爬取链家网房源信息并保存至csv 抓取的信息有:房源', '详细信息', '价格','楼层', '有无电梯 import csv from selenium import ...

  5. 如何爬取链家网页房源信息

    由于个人安装的Python版本是2.7的,因此此后的相关代码也是该版本. 爬取网页所有信息  利用urllib2包来抓取网页的信息,先介绍下urllib2包的urlopen函数.  urlopen:将 ...

  6. 一、如何爬取链家网页房源信息

    由于个人安装的Python版本是2.7的,因此此后的相关代码也是该版本. 爬取网页所有信息 利用urllib2包来抓取网页的信息,先介绍下urllib2包的urlopen函数. urlopen:将网页 ...

  7. 如何高效地爬取链家的房源信息(一)

    "Python实现的链家网站的爬虫第一部分." 在之前的文章,以链家成都站为例,分析过链家网站数据的爬取,文章如下: 干货!链家二手房数据抓取及内容解析要点 但是,当时没有根据分析 ...

  8. Python爬取链家成都二手房源信息

    作者 | 旧时晚风拂晓城 编辑 | JackTian 来源 | 杰哥的IT之旅(ID:Jake_Internet) 转载请联系授权(微信ID:Hc220066) 公众号后台回复:「成都二手房数据」,获 ...

  9. Python爬取链家成都二手房源信息,异步爬虫实战项目!

    本文先熟悉并发与并行.阻塞与非阻塞.同步与异步.多线程.多线程.协程的基本概念.再实现asyncio + aiohttp爬取链家成都二手房源信息的异步爬虫,爬取效率与多线程版进行简单测试和比较. 1. ...

最新文章

  1. css如何让图片不平铺,css怎么设置图片平铺方式?
  2. Qt入门之基础篇 ( 一 ) :Qt4及Qt5的下载与安装
  3. BigDecimal运算的工具类
  4. det曲线_平面曲线的曲率的复数表示
  5. java菜单管理的实现方式_智能停车场管理系统的收费实现方式有哪些?
  6. Python 第十一篇:开发堡垒机
  7. 第一次使用Latex编辑论文,经验分享
  8. 05Oracle P6培训系列:05创建项目
  9. win10怎么更新显卡驱动_如何禁止win10自动更新显卡驱动
  10. oracle gbk 转码,oracle编码格式从utf-8转换为GBK
  11. 三、OpenDaylight应用基础开发(ODL的Hello World)
  12. Linux下的数学工具Maxima 简明教程(上)
  13. 全闪存助攻:数据存储迎来又一个“新元年”
  14. Java图形化界面编程超详细知识点(9)——Swing_树
  15. 用python玩转数据作业答案_大学mooc2020年用Python玩转数据作业答案
  16. JavaSE02(类与对象)
  17. PLS-DA中的LV(潜在变量)数量
  18. 【数据结构】带头+双向+循环链表(增、删、查、改)的实现_【附源码、图片示例】_ [初阶篇_ 复习专用]
  19. ubantu报错: 正在等待缓存锁:无法获得锁 /var/lib/dpkg/lock-frontend。锁正由进程3228(aptd)
  20. 开启从小白到精通的基于文献计量学论文写作之旅

热门文章

  1. Spring Boot 入门系列(二十八) JPA 的实体映射关系,一对一,一对多,多对多关系映射!...
  2. 永磁同步电机力矩控制(九):定子磁场中的若干相关概念
  3. ie 启用 java_无法使用带有Java的Selenium2(Webdriver)启动IE浏览器
  4. logback配置文件---logback.xml详解
  5. 关于给hexo博客增加节日气氛主题切换(包括中国春节和圣诞节)
  6. 计算机交互媒体应用范围,浅析交互媒体设计中的科技与艺术的关系
  7. 支持向量机的理解,目前看到的最通透的
  8. typec耳机知识介绍-数字耳机,模拟耳机
  9. 图形工作站安装win7+ubuntu双系统
  10. edge函数闪退 matlab,Microsoft Edge闪退怎么办?Microsoft Edge闪退解决办法