使用python3抓取链家二手房数据

发表于:2018-4-23 10:05

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:秋水天    来源:掘金中国

  有小伙伴说想拿链家二手房信息做数据分析,让帮忙抓点数据。并没有搞过,网上搜了一些资料试了一下,感觉不难可以搞,下面小结一下。
  工具
  python的三方库:
  BeautifulSoup(用于解析数据)
  pandas(用于处理数据,存储成Excel)
  requests (用于发送请求)
  三方库库的安装也比较简单,直接使用 pip install 相应的库名 即可:
  pip install pandas
  pip install requests
  pip install beautifulsoup4
  思路
  抓包基本的意思就是用代码模拟用户的请求,然后解析相应的网页内容,择取出需要的信息即可。
  简单看了一下链家的网页结构,是比较整齐的。这种就是深圳二手房列表分页的链接:
  https://sz.lianjia.com/ershoufang/pg1
  https://sz.lianjia.com/ershoufang/pg2
  ...
  https://sz.lianjia.com/ershoufang/pg99
  https://sz.lianjia.com/ershoufang/pg100
  可以请求一下这个链接,然后解析返回结果,可以抓取到每一个房子详情页面的链接。我这边是通过正则匹配的方式解析的(详情参考源码中catchHouseList函数)。解析的结果大概像这样子:
  https://sz.lianjia.com/ershoufang/105101151981.html
  https://sz.lianjia.com/ershoufang/105101102328.html
  https://sz.lianjia.com/ershoufang/105100779210.html
  https://sz.lianjia.com/ershoufang/105101254525.html
  https://sz.lianjia.com/ershoufang/105101201989.html
  https://sz.lianjia.com/ershoufang/105101262457.html
  获取详情链接之后,再请求这个详情链接,可以获得到详情信息。把获取到的详情信息通过 BeautifulSoup 解析,就能得到你要的数据。
  最后,把这个数据通过 pandas 写入到Excel中即可(参考appendToXlsx函数)。写的时候是append的方式。
  注意的是因为大部分网站对于链接访问都有一些限制,诸如访问太频繁了,服务器可能认为这个请求不正常,不会返回正确结果。因此每次请求一个网页之后,会等一会儿再请求下一个网页。不至于被服务器拒绝。
  # 我这里设置为3秒
  time.sleep(3)
  源码
  下面是我的源码,应该安装完相应的三方库,在python环境运行下面的代码即可:
  import requests
  from bs4 import BeautifulSoup
  import sys
  import os
  import time
  import pandas as pd
  import numpy as np
  from parsel import Selector
  import re
  headers = {
          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 BIDUBrowser/8.7 Safari/537.36'
      }
  def catchHouseList(url):
      resp = requests.get(url, headers=headers, stream=True)
      if resp.status_code == 200:
          reg = re.compile('<li.*?class="clear">.*?<a.*?class="img.*?".*?href="(.*?)"')
          urls = re.findall(reg, resp.text)
          return urls
      return []
  def catchHouseDetail(url):
      resp = requests.get(url, headers=headers)
      print(url)
      if resp.status_code == 200:
          info = {}
          soup = BeautifulSoup(resp.text, 'html.parser')
          info['标题'] = soup.select('.main')[0].text
          info['总价'] = soup.select('.total')[0].text
          info['总价单位'] = soup.select('.unit')[0].text
          info['每平方售价'] = soup.select('.unitPriceValue')[0].text
          # p = soup.select('.tax')
          # info['参考总价'] = soup.select('.tax')[0].text
          info['建造时间'] = soup.select('.subInfo')[2].text
          info['小区名称'] = soup.select('.info')[0].text
          info['所在区域'] = soup.select('.info a')[0].text + ':' + soup.select('.info a')[1].text
          info['链家编号'] = str(url)[34:].rsplit('.html')[0]
          info['房屋户型'] = str(soup.select('.content')[2].select('.label')[0].next_sibling)
          info['所在楼层'] = soup.select('.content')[2].select('.label')[1].next_sibling
          info['建筑面积'] = soup.select('.content')[2].select('.label')[2].next_sibling
          info['户型结构'] = soup.select('.content')[2].select('.label')[3].next_sibling
          info['套内面积'] = soup.select('.content')[2].select('.label')[4].next_sibling
          info['建筑类型'] = soup.select('.content')[2].select('.label')[5].next_sibling
          info['房屋朝向'] = soup.select('.content')[2].select('.label')[6].next_sibling
          info['建筑结构'] = soup.select('.content')[2].select('.label')[7].next_sibling
          info['装修情况'] = soup.select('.content')[2].select('.label')[8].next_sibling
          info['梯户比例'] = soup.select('.content')[2].select('.label')[9].next_sibling
          info['供暖方式'] = soup.select('.content')[2].select('.label')[10].next_sibling
          info['配备电梯'] = soup.select('.content')[2].select('.label')[11].next_sibling
        #  info['产权年限'] = str(soup.select('.content')[2].select('.label')[12].next_sibling)
          return info
      pass
  def appendToXlsx(info):
      fileName = './链家二手房.xlsx'
      dfNew = pd.DataFrame([info])
      if(os.path.exists(fileName)):
          sheet = pd.read_excel(fileName)
          dfOld = pd.DataFrame(sheet)
          df = pd.concat([dfOld, dfNew])
          df.to_excel(fileName)
      else:
          dfNew.to_excel(fileName)
  def catch():
      pages = ['https://sz.lianjia.com/ershoufang/pg{}/'.format(x) for x in range(1, 1001)]
      for page in pages:
          print(page)
          houseListURLs = catchHouseList(page)
          for houseDetailUrl in houseListURLs:
              try:
                  info = catchHouseDetail(houseDetailUrl)
                  appendToXlsx(info)
              except:
                  pass
              time.sleep(3)
      pass
  if __name__ == '__main__':
      catch()
      
  瞎墨迹
  虽然技术含量并不高,只是涉及到一些三方工具的使用。不过实践的过程中还是遇到一些问题,诸如对pandas的使用,因为从未接触过,就折腾了很久。大概很多看起来很简单的东西,真正弄起来的时候,依旧有预料不到的问题。
  其次是抓包这件事,技术上觉得并不奇特(当然有些网站的抓包还是有难度的),但是小伙伴需要这个,也许一件事情并不仅仅从技术上考量其价值。



上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号