当前位置:   article > 正文

python爬取链家北京二手房信息(BeautifulSoup)_python爬取北京二手房

python爬取北京二手房

2022.3.21更新:本博客当时写的时候链家网页中一些属性或需要的信息名称都与参考博客不同,网站中的结构等会经常变化,因此如果直接使用本博客代码可能会导致采集不到需要信息,csv文件为空的情况,希望各位看懂本博客后再去网站根据各自需要和网站此时的设置等修改代码,爬取信息。

一、准备

使用的包有:urllib.request、bs4、pandas、numpy、re、time

urllib.request:用来打开和浏览url中内容

bs4:爬取网页

pandas:生成数据表,并保存为csv文件

numpy:循环的时候用了一下,个人感觉好像可以不用,但是没试过

re:使用正则表达式提取需要的内容

time:为了防止访问网站过于频繁报错,使用time.sleep()暂停一段时间

首先引入包

  1. from urllib.request import urlopen
  2. from bs4 import BeautifulSoup
  3. import pandas as pd
  4. import numpy as np
  5. import re
  6. import time

二、抓取数据

本博客抓取的信息有:

Direction(房屋朝向)、District(所在商业区)、Floor(楼层)、Garden(房屋所在小区)、Layout(户型)、Price(总价)、Renocation(房屋装修)、Size(面积)、Year(年份)、Id(房屋编号)

ps:本程序抓取的数据,Id由于是科学计数法在csv文件中显示,因此不可以使用(只有Id有问题),需要的朋友可以修改代码解决这个问题,结果会在最后贴出

房屋编号并不在页面中显示,而是在代码里

1、了解一下目标网站的URL结构,例如 北京东城第2页二手房房源_北京东城第2页二手房出售|买卖|交易信息(北京链家)

  • bj表示城市,北京
  • ershoufang是频道名称,二手房
  • dongcheng是城区名称,东城区
  • pg2是页面码,第二页

我们要抓取北京的二手房信息,所以前半部分(http://bj.lianjia.com/ershoufang/)是不会变的,而需要遍历城区和页数。使用两层循环,外层遍历城区,内层遍历页数。

  1. chengqu = {'dongcheng': '东城区', 'xicheng': '西城区', 'chaoyang': '朝阳区', 'haidian': '海淀区', 'fengtai': '丰台区',
  2. 'shijingshan': '石景山区','tongzhou': '通州区', 'changping': '昌平区', 'daxing': '大兴区', 'shunyi': '顺义区',
  3. 'fangshan': '房山区'}
  4. for cq in chengqu.keys():
  5. url = 'https://bj.lianjia.com/ershoufang/' + cq + '/' # 组成所选城区的URL
  6. ...
  7. for j in np.arange(1, int(total_page) + 1):
  8. page_url = url + 'pg' + str(j) # 组成所选城区页面的URL
  9. ....

2、其中,需要获取所选城区包含的总页数,提取div标签中class=page-box house-lst-page-box的第三个子标签属性page-data的值。

total_page = re.sub('\D', '', bsObj.find('div', 'page-box house-lst-page-box').contents[0].attrs['page-data'])[:-1]  # 获取所选城区总页数

3、对需要信息进行提取,此时,你需要一点点的在页面代码中去找你需要的部分,并且观察提取出来的内容的格式,转换成我们需要存储的格式

把class为houseInfo、positionInfo、totalPrice的div和class为noresultRecommend img LOGCLICKDATA的a标签提取出来,使用get_text()获取内容,然后使用split分割成list

  1. page_html = urlopen(page_url)
  2. page_bsObj = BeautifulSoup(page_html)
  3. info = page_bsObj.findAll("div", {"class": "houseInfo"})
  4. position_info = page_bsObj.findAll("div", {"class": "positionInfo"})
  5. totalprice = page_bsObj.findAll("div", {"class": "totalPrice"})
  6. idinfo = page_bsObj.findAll("a", {"class": "noresultRecommend img LOGCLICKDATA"})
  7. for i_info, i_pinfo, i_tp, i_up, i_id in zip(info, position_info, totalprice, unitprice, idinfo):
  8. i_info=i_info.get_text().split('|') #['马甸南村','2室1厅','51.1平米','西','简装']
  9. i_pinfo=i_pinfo.get_text().split('-')#['中楼层(共16层)1986年建塔楼','马甸']
  10. i_pinfo[0] = re.findall(r"\d+\.?\d*", i_pinfo[0])#[['16','1986'],'马甸']
  11. i_info[2] = re.findall(r"\d+\.?\d*",i_info[2].replace(' ',''))#['马甸南村','2室1厅',51.1,'西','简装']

统计导入list中,再生成数据表,保存为csv文件

  1. house_direction = [] # 房屋朝向Direction
  2. house_districe = [] # 房屋所在商业区Districe
  3. house_floor = [] # 房屋楼层Floor
  4. house_garden = [] # 房屋所在小区Garden
  5. house_id = [] # 房屋编号Id
  6. house_layout = [] # 房屋户型Layout
  7. t_price = [] # 房屋总价Price
  8. house_renovation = [] # 房屋装修Renovation
  9. house_size = [] # 房屋面积Size
  10. house_year = [] # 建造年份Year
  11. if len(i_info) == 5 and len(i_pinfo) == 2 and len(i_pinfo[0])==2 and ('data-housecode'in i_id.attrs):#到了后面有的没有楼层或年份,或<a>中没有data-housecode属性
  12. # 从houseinfo中获取房屋所在小区、户型、面积、朝向、装修、有无电梯各字段
  13. house_garden.append(i_info[0].replace(' ',''))
  14. house_layout.append(i_info[1].replace(' ',''))
  15. house_size.append(i_info[2])
  16. house_direction.append(i_info[3].replace(' ', ''))
  17. house_renovation.append(i_info[4].replace(' ',''))
  18. # 从positioninfo中获房屋楼层、建造年份、位置各字段
  19. house_floor.append(i_pinfo[0][0])
  20. house_year.append(i_pinfo[0][1])
  21. house_districe.append(i_pinfo[1])
  22. # 获取房屋总价和单价
  23. t_price.append(i_tp.span.string)
  24. #获取房屋id
  25. house_id.append(str(i_id.attrs['data-housecode']))
  26. # 将数据导入pandas之中生成数据表
  27. file2=open('lianjia.csv','a+',newline='')
  28. house_data = pd.DataFrame()
  29. house_data['Id'] = house_id
  30. house_data['Region'] = [chengqu[cq]] * len(house_garden)
  31. house_data['Gargen'] = house_garden
  32. house_data['District'] = house_districe
  33. house_data['Layout'] = house_layout
  34. house_data['Size'] = house_size
  35. house_data['Direction'] = house_direction
  36. house_data['Renocation'] = house_renovation
  37. house_data['Floor'] = house_floor
  38. house_data['Year'] = house_year
  39. house_data['Price'] = t_price
  40. # 将数据存入到csv中,便于后续分析
  41. house_data.to_csv(file2, header=False,encoding='gb2312',index=None)
  42. file2.close()
  43. time.sleep(60)

三、最后加上全部代码~

  1. from urllib.request import urlopen
  2. from bs4 import BeautifulSoup
  3. import pandas as pd
  4. import numpy as np
  5. import re
  6. import time
  7. chengqu = {'dongcheng': '东城区', 'xicheng': '西城区', 'chaoyang': '朝阳区', 'haidian': '海淀区', 'fengtai': '丰台区',
  8. 'shijingshan': '石景山区','tongzhou': '通州区', 'changping': '昌平区', 'daxing': '大兴区', 'shunyi': '顺义区',
  9. 'fangshan': '房山区'}
  10. for cq in chengqu.keys():
  11. url = 'https://bj.lianjia.com/ershoufang/' + cq + '/' # 组成所选城区的URL
  12. html = urlopen(url)
  13. bsObj = BeautifulSoup(html)
  14. total_page = re.sub('\D', '', bsObj.find('div', 'page-box fr').contents[0].attrs['page-data'])[:-1] # 获取所选城区总页数
  15. #print('total_page', total_page)
  16. house_direction = [] # 房屋朝向Direction
  17. house_districe = [] # 房屋所在商业区Districe
  18. # house_elevator = [] # 有无电梯Elevator
  19. house_floor = [] # 房屋楼层Floor
  20. house_garden = [] # 房屋所在小区Garden
  21. house_id = [] # 房屋编号Id
  22. house_layout = [] # 房屋户型Layout
  23. t_price = [] # 房屋总价Price
  24. house_renovation = [] # 房屋装修Renovation
  25. house_size = [] # 房屋面积Size
  26. house_year = [] # 建造年份Year
  27. for j in np.arange(1, int(total_page) + 1):
  28. print("at the ",cq," page ",j,"/",total_page)
  29. page_url = url + 'pg' + str(j) # 组成所选城区页面的URL
  30. # print (page_url)
  31. page_html = urlopen(page_url)
  32. page_bsObj = BeautifulSoup(page_html)
  33. info = page_bsObj.findAll("div", {"class": "houseInfo"})
  34. position_info = page_bsObj.findAll("div", {"class": "positionInfo"})
  35. totalprice = page_bsObj.findAll("div", {"class": "totalPrice"})
  36. unitprice = page_bsObj.findAll("div", {"class": "unitPrice"})
  37. idinfo = page_bsObj.findAll("a", {"class": "noresultRecommend img LOGCLICKDATA"})
  38. for i_info, i_pinfo, i_tp, i_up, i_id in zip(info, position_info, totalprice, unitprice, idinfo):
  39. i_info=i_info.get_text().split('|')
  40. i_pinfo=i_pinfo.get_text().split('-')
  41. i_pinfo[0] = re.findall(r"\d+\.?\d*", i_pinfo[0])
  42. i_info[2] = re.findall(r"\d+\.?\d*",i_info[2].replace(' ',''))
  43. if len(i_info) == 5 and len(i_pinfo) == 2 and len(i_pinfo[0])==2 and ('data-housecode'in i_id.attrs):
  44. # 分列houseinfo并依次获取房屋所在小区、户型、面积、朝向、装修、有无电梯各字段
  45. house_garden.append(i_info[0].replace(' ',''))
  46. house_layout.append(i_info[1].replace(' ',''))
  47. house_size.append(i_info[2])
  48. house_direction.append(i_info[3].replace(' ', ''))
  49. house_renovation.append(i_info[4].replace(' ',''))
  50. #house_elevator.append(i_info[5])
  51. # 分列positioninfo并依次获房屋楼层、建造年份、位置各字段
  52. house_floor.append(i_pinfo[0][0])
  53. house_year.append(i_pinfo[0][1])
  54. house_districe.append(i_pinfo[1])
  55. # 获取房屋总价和单价
  56. t_price.append(i_tp.span.string)
  57. #获取房屋id
  58. house_id.append(str(i_id.attrs['data-housecode']))
  59. # 将数据导入pandas之中生成数据表
  60. file2=open('lianjia.csv','a+',newline='')
  61. house_data = pd.DataFrame()
  62. house_data['Id'] = house_id
  63. house_data['Region'] = [chengqu[cq]] * len(house_garden)
  64. house_data['Gargen'] = house_garden
  65. house_data['District'] = house_districe
  66. house_data['Layout'] = house_layout
  67. house_data['Size'] = house_size
  68. house_data['Direction'] = house_direction
  69. house_data['Renocation'] = house_renovation
  70. # house_data[u'有无电梯'] = house_elevator
  71. house_data['Floor'] = house_floor
  72. house_data['Year'] = house_year
  73. house_data['Price'] = t_price
  74. # print (house_data)
  75. # 将数据存入到csv中,便于后续分析
  76. house_data.to_csv(file2, header=False,encoding='gb2312',index=None)
  77. #house_data.to_csv(file, header=True, encoding='gb2312', index=True)
  78. file2.close()
  79. time.sleep(60)

四、运行结果

由于是使用office显示的,可以改变数据格式,改变后id变为:

id变成这样也没法用,还好之后的操作中用不到id,如果有需要用id数据的,可以试一下先创建csv文件,把第一列数据格式改掉,也许就行了,或者还有更高级的方法,但是我也没有试。。。

五、参考博客:学习python抓取数据——链家北京二手房数据_ziyin_2013的博客-CSDN博客

就酱啦~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/192515
推荐阅读
相关标签
  

闽ICP备14008679号