爬虫系列之链家的信息爬取及数据分析

关于链家的数据爬取和分析

已经实现

 1.房屋数据爬取并下载
 2.房屋按区域分析
 3.房屋按经纪人分析
 4.前十经纪人
 5.经纪人最有可能的位置分析
 6.实现以地区划分房屋
 目前存在的问题:
 1.多线程下载的时候会出现个别文件不继续写入了(已经解决)
 2.未考虑经纪人重名问题
 3.查询中发现不是每次都能 get 到 url 的数据,具体原因可能跟header有关,或者网站反扒(已经解决,手机端的header有时候访问pc端会出现None的情况)
 4.守护线程那里应该出问题了,如果有文件储存完成,其他就不运行了(已经解决,多线程下还要有主程序运行,否则会出现问题)
 5.json.dumps(dict)方法取出的字符串类型,二进制的,decode不好用,怎么解决
  (已经解决json.dumps(content, ensure_ascii=False)保持原有的编码)
  1 # -*- coding: utf-8 -*-
  2 # @Time :2018/5/1   23:39
  3 # @Author : ELEVEN
  4 # @File : _链家_数据分析_修改.py
  5 # @Software: PyCharm
  6
  7 import time
  8 from lxml import etree
  9 from urllib import request
 10 import threading
 11 import os
 12 import json
 13 import random
 14
 15 ‘‘‘
 16 已经实现
 17 1.房屋数据爬取并下载
 18 2.房屋按区域分析
 19 3.房屋按经纪人分析
 20 4.前十经纪人
 21 5.经纪人最有可能的位置分析
 22 6.实现以地区划分房屋
 23 目前存在的问题:
 24 1.多线程下载的时候会出现个别文件不继续写入了(已经解决)
 25 2.未考虑经纪人重名问题
 26 3.查询中发现不是每次都能 get 到 url 的数据,具体原因可能跟header有关,或者网站反扒(已经解决,手机端的header有时候访问pc端会出现None的情况)
 27 4.守护线程那里应该出问题了,如果有文件储存完成,其他就不运行了(已经解决,多线程下还要有主程序运行,否则会出现问题)
 28 5.json.dumps(dict)方法取出的字符串类型,二进制的,decode不好用,怎么解决
 29 (已经解决json.dumps(content, ensure_ascii=False)保持原有的编码)
 30
 31
 32 ‘‘‘
 33 # 获取能够 xpath 匹配的 HTML 匹配对象
 34 def get_html(url):
 35     time.sleep(1)
 36     header = {
 37         ‘Referer‘:‘https://bj.lianjia.com/zufang/‘,
 38         ‘User-Agent‘:‘Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0‘
 39     }
 40     req = request.Request(url, headers = header)
 41     # 请求
 42     response = request.urlopen(req)
 43     result = response.read().decode()
 44     # 构建 HTML 匹配对象
 45     html = etree.HTML(result)
 46     return html
 47 # 主程序
 48 def main(p, url):
 49     # 加锁,写入本条数据后指针才会进行跳转
 50     lock = threading.Lock()
 51     # 获取 get_html() 函数返回的 HTML 匹配对象
 52     html = get_html(url)
 53     # 进行 xpath 初步匹配
 54     house_list = html.xpath(‘//ul[@id="house-lst"]/li/div[@class = "info-panel"]‘)
 55     threading_list = []
 56     # 遍历得到的匹配列表
 57     for index, house in enumerate(house_list):
 58         content, house_address, house_dict ,broker_name = get_info(p,index, house)
 59         print(‘正在保存第 %d 页 第 %s 条数据......‘ % (p, index+1))
 60         lock.acquire()
 61         # save_info(p, str(index+1) + ‘ ‘ + content + ‘\n‘)
 62         get_class_data(house_address, house_dict, broker_name)
 63         t2 = threading.Thread(target=save_info, args=(p, str(index+1) + ‘ ‘ + content + ‘\n‘))
 64         t3 = threading.Thread(target=get_class_data, args=(house_address, house_dict, broker_name))
 65         t2.setDaemon(True)  # 这个好像没有用,等老师帮助解答
 66         t2.start()
 67         t3.start()
 68         threading_list.append(t2)
 69         threading_list.append(t3)
 70         lock.release()
 71     for t in threading_list:
 72         t.join()
 73     # 这里必须的写, 这个错误得记住,必须要有主进程 ,所有线程才会都运行
 74     print(‘我是守护线程‘)
 75 # 获取分类数据,方便数据分析
 76 def get_class_data(house_address, house_dict, broker_name):
 77     # 按区域划分
 78     if house_address in address_class:
 79         address_class[house_address][‘num‘] += 1
 80         address_class[house_address][‘house‘].append(house_dict)
 81     else:
 82         address_class[house_address] =  {‘num‘: 0, ‘house‘: []}
 83         address_class[house_address][‘num‘] += 1
 84         address_class[house_address][‘house‘].append(house_dict)
 85     # 按经纪人划分
 86     if broker_name in broker_class:
 87         broker_class[broker_name][‘num‘] += 1
 88         broker_class[broker_name][‘house‘].append(house_dict)
 89     else:
 90         broker_class[broker_name] =  {‘num‘: 0, ‘house‘: []}
 91         broker_class[broker_name][‘num‘] += 1
 92         broker_class[broker_name][‘house‘].append(house_dict)
 93 # 获取房产信息
 94 def get_info(p,index, house):
 95     house_url = house.xpath(‘h2/a/@href‘)[0]
 96     house_html = get_html(house_url)
 97     broker_name = house_html.xpath(
 98         ‘//div[@class="brokerInfo"]/div[@class="brokerInfoText"]/div[@class="brokerName"]/a/text()‘)
 99     broker_phone = house_html.xpath(‘//div[@class="phone"]/text()‘)
100     if broker_name != []:
101         broker_name = broker_name[0]
102         broker_phone = str(broker_phone[0].strip()) + ‘转‘ + str(broker_phone[1].strip())
103     else:
104         broker_name = ‘暂无相关经纪人!‘
105         broker_phone = ‘请直接联系客服  10109666‘
106     house_name = house.xpath(‘h2/a/text()‘)[0]
107     house_style = house.xpath(‘div[@class="col-1"]/div[@class="where"]/span[@class="zone"]/span/text()‘)[0]
108     house_size = house.xpath(‘div[@class="col-1"]/div[@class="where"]/span[@class="meters"]/text()‘)[0].strip()
109     house_address = house.xpath(‘div[@class="col-1"]/div[@class="other"]/div[@class="con"]/a/text()‘)[0]
110     house_price = house.xpath(‘div[@class="col-3"]/div[@class="price"]/span/text()‘)[0]
111     house_dict = {
112         ‘house_name‘: house_name,
113         ‘style‘: house_style.strip(),
114         ‘size‘: house_size,
115         ‘address‘: house_address,
116         ‘price‘: house_price,
117         ‘broker_name‘: broker_name,
118         ‘broker_phone‘: broker_phone
119     }
120     content = "名字:%(house_name)s 样式:%(style)s  大小:%(size)s  地址:%(address)s  " 121               "价格:%(price)s 经纪人:%(broker_name)s 联系电话:%(broker_phone)s " % house_dict
122     # 构建字典类型 {‘house_name’:{‘num‘:13, ‘house‘:[house_dict]}}
123     print(p, index+1, content)
124     return content,house_address,house_dict,broker_name
125 # 保存文件
126 def save_info(p, content):
127     with open(‘%s/%s.txt‘ % (‘链家房产信息‘, str(p)), ‘a‘, encoding=‘utf-8‘) as f:
128         f.write(content)
129 # 随机消息头, 这里修改后再用,应该是出问题了
130 # def random_agent():
131 #     header_str = ‘‘‘Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50#Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50#Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)#Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1#Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1#Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11#Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)#Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)#Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)#Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)#Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5#Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5#MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
132 #     ‘‘‘
133 #     header = header_str.split(‘#‘)
134 #     return header[random.randint(1, len(header)) - 1]
135 # 数据分析
136 def analyze_data():
137     # 查询信息内房屋总套数
138     address_sum = 0
139     # 区域
140     for key, value in address_class.items():
141         print(key, ‘一共‘, value[‘num‘], ‘套‘)
142         save_info(‘房屋分类‘, key+ ‘一共‘+ json.dumps(value[‘num‘])+ ‘套‘+‘\n‘)
143         # with open(‘%s/%s.txt‘ % (‘链家房产信息‘, ‘房屋分类‘), ‘a‘, encoding=‘utf-8‘) as f:
144         #     f.write(key+ ‘一共‘+ value[‘num‘]+ ‘套‘)
145         # 每遍历到一个区域 房屋总数量变量address_sum 就将这个区域的房屋数量加上
146         address_sum += int(value[‘num‘])
147         # 遍历每个区域房屋信息
148         for item in value[‘house‘]:
149             print(item)
150             save_info(‘房屋分类‘, json.dumps(item)+‘\n‘)
151             # with open(‘%s/%s.txt‘ % (‘链家房产信息‘, ‘房屋分类‘), ‘a‘, encoding=‘utf-8‘) as f:
152             #     f.write(item)
153         print(‘----------------------------------‘)
154     print(‘当前查询房屋一共‘, address_sum, ‘套‘)
155     save_info(‘房屋分类‘, ‘当前查询房屋一共‘+ str(address_sum)+ ‘套‘)
156     # 创建字典:键为 经纪人 值为 经纪人所拥有房屋数量 num
157     broker_dict = {}
158     for key, value in broker_class.items():
159         # 打印 经纪人 和 其所拥有的房屋数量
160         print(key, ‘一共‘, value[‘num‘], ‘套‘)
161         save_info(‘经纪人分类‘, key+ ‘一共‘+ json.dumps(value[‘num‘])+ ‘套‘+‘\n‘)
162         # 将经纪人 和 房屋数量信息添加到 字典中
163         broker_dict[key] = value[‘num‘]
164         # 分别打印该 经纪人 下面每套房屋的信息
165         for item in value[‘house‘]:
166             print(item)
167             save_info(‘经纪人分类‘, json.dumps(item) + ‘\n‘)
168         print(‘----------------------------------‘)
169     # 如果存在 ‘暂无相关经纪人!‘这种情况,那么统计的联系人数量需要减一
170     if ‘暂无相关经纪人!‘ in list(broker_class.keys()):
171         # broker_sum 为经纪人 数量总数
172         broker_sum = int(len(broker_class)) - 1
173         print(broker_sum)
174         # broker_house 为 经纪人 拥有房屋总套数
175         broker_house = address_sum - int(broker_class[‘暂无相关经纪人!‘][‘num‘])
176         del broker_dict[‘暂无相关经纪人!‘]
177     else:
178         broker_sum = len(broker_class)
179         broker_house = address_sum
180     print(broker_dict)
181     # 整理出不含有 ‘暂无相关经纪人!‘ 的字典,方便下面进行数据分析
182     # if broker_dict[‘暂无相关经纪人!‘]:
183     #     del broker_dict[‘暂无相关经纪人!‘]
184
185     print(‘当前查询经纪人共有‘, broker_sum, ‘人‘)
186     print(‘当前查询有经纪人的房屋‘, broker_house, ‘套‘)
187     # 存储前十名的列表
188     max_list = []
189     print(‘排序得到前十的经纪人‘)
190     for i in range(10):
191         # 取出手里拥有房子最多的经纪人
192         max_num = max(zip(broker_dict.values(), broker_dict.keys()))
193         # 将房子最多的联系人添加到前十的列表中
194         max_list.append(max_num)
195         # 打印,第几名,是谁
196         print(‘第 %d 名‘ % (i + 1), max_num)
197         save_info(‘排名‘, ‘第 %d 名‘ % (i + 1)+‘姓名: ‘+ max_num[1]+‘   ‘+str(max_num[0])+‘套‘+‘\n‘)
198         # 已经被取出的经纪人,从列表中删除掉,以免影响下一次筛选
199         del broker_dict[max_num[1]]
200         # 创建存储经纪人位置的字典,
201         broker_postion = {}
202         # 对经纪人手中的房子按照区域划分,并且存入字典中,统计各区域拥有房屋数量
203         # 房屋最多的区域就是 经纪人最有可能在的位置
204         for dict in broker_class[max_num[1]][‘house‘]:
205             # 如果此区域存在字典中,那么相应的区域数量 num + 1
206             # 如果不存在,那么将这个区域添加到字典中,数量 num + 1
207             if dict[‘address‘] in broker_postion:
208                 broker_postion[dict[‘address‘]][‘num‘] += 1
209             else:
210                 broker_postion[dict[‘address‘]] = {‘num‘: 0}
211                 broker_postion[dict[‘address‘]][‘num‘] += 1
212         # 取出经纪人按找区域分类的字典中 ,数量num最大的那个区域元组
213         postion = max(zip(broker_postion.values(), broker_postion.keys()))
214         print(‘最可能在的位置‘, postion[1])
215         save_info(‘排名‘, ‘最可能在的位置‘+ postion[1]+‘\n‘)
216         # 此经纪人数据分析已经结束,字典清空释放掉,方便下次其他经纪人使用
217         broker_postion.clear()
218     # print(‘排序得到前十的经纪人‘)
219     # print(max_list)
220
221
222 if __name__ == "__main__":
223     # 以地址划分, 创建以 address 为键字典
224     address_class = {}
225     # 以经纪人划分, 创建以 broker 为键字典
226     broker_class = {}
227     # 加锁
228     lock = threading.Lock()
229     # 运行初始提示
230     print(‘   -------------可供选择的区域--------------\n东城 西城 朝阳 海淀 丰台 石景山 通州 昌平 大兴 顺义\n亦庄开发区 房山 门头沟 平谷 怀柔 密云 延庆 燕郊 香河‘)
231     option = input(‘请输入相应区域的拼音,默认视为选择全部:‘)
232     page = int(input(‘请输入要获取的页数:‘))
233     # 创建文件夹
234     if not os.path.exists(‘链家房产信息‘):
235         os.mkdir(‘链家房产信息‘)
236     # 多线程列表
237     thread_list = []
238     for p in range(1, page+1):
239         if p == 1:
240             url = ‘https://bj.lianjia.com/zufang/%s/‘ % option
241         else:
242             url = ‘https://bj.lianjia.com/zufang/%s/pg%d/‘ % (option, p)
243         print(‘----------开始打印第 %d 页信息----------‘ % p)
244         lock.acquire()
245         t1 = threading.Thread(target=main, args=(p,url))
246         # 设置守护线程
247         t1.setDaemon(True)
248         t1.start()
249         thread_list.append(t1)
250         lock.release()
251         print(‘----------打印第 %d 页信息结束----------‘ % p)
252     for t1 in thread_list:
253         t1.join()
254     # 执行数据分析
255     analyze_data()

代码还有很大的优化空间,python 是艺术品,需要慢慢的精雕细刻,在努力的路上!

原文地址:https://www.cnblogs.com/AAA-AAA-AAA/p/9611032.html

时间: 2024-11-09 07:37:07

爬虫系列之链家的信息爬取及数据分析的相关文章

爬虫系列之淘宝商品爬取

1 import re 2 import requests 3 4 def getHTMLText(url): 5 try: 6 r = requests.get(url, timeout = 30) 7 r.raise_for_status() 8 r.encoding = r.apparent_encoding 9 return r.text 10 except: 11 return "" 12 13 14 def parsePage(ilt, html): 15 try: 16

链家信息爬取

一.数据库封装 import pymysql class MysqlHelper(object):    def __init__(self):        self.db = pymysql.connect(host='127.0.0.1', port=3306, user='root', password='abc123', database='py1011', charset='utf8')        self.cursor = self.db.cursor() def execut

爬虫案例—中基协数据爬取

因为工作原因,需要爬取相关网站的数据,包括中基协网站和天眼查部分数据. 一.中基协网站 爬取思路: 1.查看目标页:http://gs.amac.org.cn/amac-infodisc/api/pof/manager?rand=0.9775162173180119&page=%s&size=50 发现有随机数字串(刷新反爬措施),以及页码和每页信息条数,可以用来拼接爬取url 用一个循环爬取所有展示页面,用到requests库以及random函数生成随机数 返回的是json数据,直接用r

爬虫学习 09.移动端数据爬取

爬虫学习 09.移动端数据爬取 前言 随着移动市场的火热,各大平台都陆陆续续的推出了自己的移动端APP来拉拢吸引和便捷其广大的用户.那么在移动端的平台当时势必会出现大量有价值的信息和数据,那这些数据我们是否可以去享用一下呢?那么接下来就进入我们的移动端APP数据的爬虫中来吧. 今日概要 fiddler简介 手机APP抓包设置 fiddler设置 安装证书下载 安全证书安装 局域网设置 fiddler手机抓包测试 今日详情 1 什么是Fiddler? Fiddler是位于客户端和服务器端的HTTP

(原)python爬虫入门(2)---排序爬取的辽宁科技大学热点新闻

发现科大网页的源码中还有文章的点击率,何不做一个文章点击率的降序排行.简单,前面入门(1)基本已经完成我们所要的功能了,本篇我们仅仅需要添加:一个通过正则获取文章点击率的数字:再加一个根据该数字的插入排序.ok,大功告成! 简单说一下本文插入排序的第一个循环,找到列表中最大的数,放到列表 0 的位置做观察哨. 上代码: # -*- coding: utf-8 -*- # 程序:爬取点击排名前十的科大热点新闻 # 版本:0.1 # 时间:2014.06.30 # 语言:python 2.7 #--

爬虫简单之二---使用进程爬取起点中文网的六万多也页小说的名字,作者,等一些基本信息,并存入csv中

爬虫简单之二---使用进程爬取起点中文网的六万多也页小说的名字,作者,等一些基本信息,并存入csv中 准备使用的环境和库Python3.6 + requests + bs4 + csv + multiprocessing 库的说明 requests模拟计算机对服务器发送requests请求 bs4:页面分析功能,分析页面找到所需要的特定内容 xlwt:把爬取的内容存入csv文件中 multiprocessing:开启多进程爬取 1.准备URLs 起点中文网 起点中文网的URL:https://w

python爬虫教程:《利用Python爬取表情包》

python爬虫教程:<利用Python爬取表情包>,微信没有表情包?不用愁!老师带领你使用多线程爬虫一键爬取20w的表情包~ python爬虫教程:<利用Python爬取表情包>,微信没有表情包?不用愁!老师带领你使用多线程爬虫一键爬取20w的表情包~ python爬虫教程:<利用Python爬取表情包>,微信没有表情包?不用愁!老师带领你使用多线程爬虫一键爬取20w的表情包~ python爬虫教程:<利用Python爬取表情包>,微信没有表情包?不用愁!

python网络爬虫学习(六)利用Pyspider+Phantomjs爬取淘宝模特图片

本篇博文在编写时参考了http://cuiqingcai.com/2652.html,向作者表示感谢 一.新的问题与工具 平时在淘宝上剁手的时候,总是会看到各种各样的模特.由于自己就读于一所男女比例三比一的工科院校--写代码之余看看美女也是极好的放松方式.但一张一张点右键–另存为又显得太过麻烦而且不切实际,毕竟图片太多了.于是,我开始考虑用万能的python来解决问题. 我们先看看淘女郎页面的URL,https://mm.taobao.com/json/request_top_list.htm?

Python爬虫实战(2):爬取京东商品列表

1,引言 在上一篇<Python爬虫实战:爬取Drupal论坛帖子列表>,爬取了一个用Drupal做的论坛,是静态页面,抓取比较容易,即使直接解析html源文件都可以抓取到需要的内容.相反,JavaScript实现的动态网页内容,无法从html源代码抓取需要的内容,必须先执行JavaScript. 我们在<Python爬虫使用Selenium+PhantomJS抓取Ajax和动态HTML内容>一文已经成功检验了动态网页内容的抓取方法,本文将实验程序进行改写,使用开源Python爬虫