爬蟲實戰01——利用python爬蟲並進行數據分析(鏈家 爬蟲)
爬取鏈家二手房相關信息並進行數據分析 {[https://sh.lianjia.com/ershoufang/pg](https://sh.lianjia.com/ershoufang/pg)}
一、爬蟲部分
背景
需求來源於生活
大數據時代來臨,數據就是核心,數據就是生產力,越來越多的企業開始注重收集用戶數據,而爬蟲技術是收集數據的一種重要手段
python版本:3.6.5 ,系統環境是windows,
工具包:request獲取頁面數據
實現頁面數據分析的兩個庫:from parsel import Selector;from bs4 import BeautifulSoup
代碼
法一:通過Selector 調用xpath方法,{XPath (它是一種在 XML 文檔中查找信息的語言。XPath 可用來在 XML
文檔中對元素和屬性進行遍歷)};
import requests
from parsel import Selector
# 進行網絡請求的瀏覽器頭部
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'
}
url = 'https://m.lianjia.com/sh/ershoufang/pg'
wr=requests.get(url,headers=headers,stream=True)
sel=Selector(wr.text)
tag = sel.xpath('//div[@class="price_total"]//text()').extract()
print(tag)
[/code]
法二:lxml 實現頁面數據的分析,提取我們想要的數據
```code
import requests
from bs4 import BeautifulSoup
url = 'https://m.lianjia.com/sh/ershoufang/pg'
res = requests.get(url, timeout=60).content
soup = BeautifulSoup(res, "lxml")
tag = soup.find_all("span", attrs={"class": "price_total"})
print(tag)
[/code]
上海鏈家二手房鏈接:https://m.lianjia.com/sh/ershoufang/pg
在抓取的過程中,在翻頁的過程中出現一點點意外(在翻頁到60頁左右數據就出現重復抓取的),后上網嘗試發現還有一個鏈接:https://sh.lianjia.com/ershoufang/pg
,而且該鏈接有房子id的信息,故完整的代碼用該鏈接進行獲取數據。
### 附上爬蟲完整代碼
鏈家二手房網址 ` https://sh.lianjia.com/ershoufang/pg `
```code
import requests
from parsel import Selector
import pandas as pd
import time
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'
}
# pages是不同頁碼的網址列表
pages=['https://sh.lianjia.com/ershoufang/pg{}/'.format(x) for x in range(1,1000)]
lj_shanghai= pd.DataFrame(columns=['hou_code','title','infotitle','alt',
'positionIcon_region','positionIcon_new',
'positionInfo_new','position_xiaoqu','starIcon','price_total_new','unitPrice'])
count=0
def l_par_html(url):
wr=requests.get(url,headers=headers,stream=True)
sel=Selector(wr.text)
# hou_code用來獲取房源的編號
hou_code=sel.xpath('//div[@class="title"]/a/@data-housecode').extract()
#獲取標題
title=sel.xpath('//div[@class="title"]//text()').extract()
infotitle=sel.xpath('//div[@class="title"]/a/text()').extract()
# =============================================================================
# #圖片
# # src=sel.xpath('//img[@class="lj-lazy"]//@src').extract()
# # print('src:%s'%src)
# =============================================================================
#圖片地址
alt=sel.xpath('//img[@class="lj-lazy"]//@alt').extract()
positionIcon_region=sel.xpath('//div[@class="houseInfo"]/a/text()').extract()
#獲取房屋信息
positionIcon = sel.xpath('//div[@class="houseInfo"]//text()').extract()
positionIcon_new=([x for x in positionIcon if x not in positionIcon_region ])
positionInfo = sel.xpath('//div[@class="positionInfo"]//text()').extract()
position_xiaoqu = sel.xpath('//div[@class="positionInfo"]/a/text()').extract()
positionInfo_new = ([x for x in positionInfo if x not in position_xiaoqu])
starIcon =sel.xpath('//div[@class="followInfo"]//text()').extract()
price_total = sel.xpath('//div[@class="totalPrice"]//text()').extract()
price_total_new =([x for x in price_total if x != '萬' ])
unitPrice =sel.xpath('//div[@class="unitPrice"]//text()').extract()
wr=requests.get(url,headers=headers,stream=True)
sel=Selector(wr.text)
tag = sel.xpath('//div[@class="tag"]//text()').extract()
# print("tag:%s"%tag)
pages_info=pd.DataFrame(list(zip(hou_code,title,infotitle,alt,
positionIcon_region,positionIcon_new,
positionInfo_new,position_xiaoqu,starIcon,price_total_new,unitPrice)),
columns=['hou_code','title','infotitle','alt',
'positionIcon_region','positionIcon_new',
'positionInfo_new','position_xiaoqu','starIcon','price_total_new','unitPrice'])
# print(pages_info)
#由於抓取下來的信息是存儲在列表中的,出現了一對多的情況,故將tag,title,infotitle單獨取出分析
return pages_info,tag,title,infotitle
for page in pages:
a=l_par_html(page)[0]
b=l_par_html(page)[1:]
print('advantage:{}'.format(b))
count=count+1
print ('the '+str(count)+' page is sucessful')
#每隔20s翻頁一次
time.sleep(20)
lj_shanghai=pd.concat([lj_shanghai,a],ignore_index=True)
print(lj_shanghai)
#將數據存儲到excel表格中
lj_shanghai.to_excel(r'\\lianjia_ershou_shanghai.xlsx')
[/code]
Q:使用xpath的text()函數定位界面元素,文本中含有空格如何解決呢?
### 數據結果展示
抓取前1000頁房價的相關數據,抓取3W+數據,但是對hou_code進行去重后,發現只有近3000條數據沒有重復,上網搜了一下原因,沒有找到原因,反而找到有相同問題的帖子(要么代碼錯了要么鏈家錯了,反正wifi沒錯,hhhh~),此處有❓,等你來解
~
發現原因 :鏈家默認展示前100頁房源,也就是說,當你從101頁開始循環的時候,自動跳轉到第一頁重新開始循環,所以一次你只能抓取100頁的房源信息

將數據導入mysql存儲,並進行簡單的數據清洗,得到:

插一句題外話:
關於python和mysql之間數據導入導出很方便,附上代碼:
```code
import pandas as pd
import pymysql
# 數據庫對應地址及用戶名密碼,指定格式,解決輸出中文亂碼問題
conn = pymysql.connect(host=None, port=3306,
user='root', passwd='******', db='test',
charset='utf8')
# cursor獲得python執行Mysql命令的方法,也就是操作游標
#使用cursor()方法創建一個游標對象
cur = conn.cursor()
v_sql = "select * from a"
#獲取數據並以dataframe讀取
table = pd.read_sql(v_sql,conn)
# =============================================================================
# 另一種方式獲取數據庫表
#使用execute()方法執行SQL語句
cur.execute(v_sql)
#使用fetall()獲取全部數據
data = cur.fetchall()
# =============================================================================
#關閉游標和數據庫的連接
cur.close()
conn.close()
table
data
[/code]
這里也可以直接用python的pandas模塊進行做處理,a.str.split(r’/’,expand = True)
需要注意的是,這里的面積、單價、總價等字段都是** str** 格式,需轉成 ** flaot**
類型,再進行a.describe()統計分析,這里不一一展示了,只展示部分結果,注意這里的數據有3054條,比distinct
hou_code數據要多,因為這里是根據一整條記錄進行a.duplicated()的。(不同的原因是由於關注人數不同,可能是重復循環翻頁的過程中,用戶的關注增加導致的),null


## 二、數據分析部分
### 利用詞雲分析
根據標題信息進行結巴分詞
```code
import pandas as pd
file = open(r'\title.xlsx','rb')
data = pd.read_excel(file)
data.columns
title = data['標題']
import numpy as np
import os
lis = np.array(title)
lis = lis.tolist()
lis[:5]
str1 = "".join(lis)
item_main = str1.strip().replace('span','').replace('class','').replace('emoji','').replace(' ','')
def save_fig(fig_id, tight_layout=True):
path = os.path.join(r"D:\\python\爬蟲", fig_id + ".png")
print("Saving figure", fig_id)
if tight_layout:
plt.tight_layout()
plt.savefig(path, format='png', dpi=300)
/*
這里沒有使用結巴分詞,因為這里的部分詞語分詞效果不是很好,由於時間不是很充裕並沒有在本地分詞庫中添加房子相關的詞語
import jieba
wordlist = jieba.cut(item_main,cut_all=True)
word_space_split =" ".join(wordlist)
type(word_space_split)
*/
import matplotlib.pyplot as plt
from wordcloud import WordCloud,ImageColorGenerator
import PIL.Image as Image
coloring = np.array(Image.open(r'\Desktop\圖片.jpg'))
my_wordcloud = WordCloud(background_color='white',max_words=200,mask=coloring,max_font_size=60,random_state=42,
scale=2,font_path=r'C:\Windows\Fonts\simkai.ttf').generate(item_main)
image_colors = ImageColorGenerator(coloring)
plt.imshow(my_wordcloud.recolor(color_func=image_colors))
plt.imshow(my_wordcloud)
plt.axis('off')
save_fig('my_wordcloud_fangjia')
plt.show()
[/code]
利用圖片生成詞雲圖
鏈接: [link] 
圖片:
![Alt] 
### 利用地圖展示房價信息
tips:本來打算用python調用百度接口的,申請了百度地圖開發密匙,但是運行出來的結果顯示接口禁用(APP
服務被禁用(240)),嘗試沒成功就暫時放棄了,https://jingyan.baidu.com/article/e73e26c0b5b75124adb6a786.html
,附上代碼,有興趣的小伙伴可以嘗試一下,回頭請教@-@~
echarts沒嘗試
```code
from urllib.request import urlopen, quote
from json import loads as loadjson
#將申請的AK復制粘貼到字符串里
ak = '*********'
def _url(service,**kv):
qstr = ''
url = 'http://api.map.baidu.com/' \
+ service + '/v2/' \
+ '?output=json' \
+ '&ak=' + ak
for k, v in kv.items():
url += '&' + k + '=' + quote(v)
return url
def baidumapapi(service,**kv):
data = urlopen(_url(service,**kv)).read().decode('utf-8')
return loadjson(data)
geo = baidumapapi('geocoder',address='gd')
if geo['status'] == 0:
try:
print(geo['result']['location']['lng'])
except (Exception,):
print(geo)
else:
print('{}({})'.format(geo['msg'] if 'msg' in geo.keys() else geo['message'],
geo['status']))
下圖是用excel的三維地圖做的(在 Excel 2016 for Windows
中開始使用三維地圖),該地圖對地理位置大部分街道可以識別(本次地圖展示的可信度99%),只有一個地址沒能識別,不知道為什么這個地址一直識別不出來,按照標准格式修改還是沒法識別,
—— ,求解~

但是具體地址的識別率很低,要是想精確到小區地址,這個工具不是一個好的idea
附上部分截圖,其中柱狀圖表示該地區總價的平均值,熱力圖表示該地區單價的平均值

對於地圖可視化,最好通過經緯度進行展示,這是最好的方式,不知道,網上有沒有通過輸入地址之后可以輸出經緯度的?回頭研究一下~
Ps:
通過經緯度在地圖上精准展示地理地址,相關代碼查看博客:
https://editor.csdn.net/md/?articleId=94437168
[ 不同小區在地圖上展示的鏈接地址
](https://blog.csdn.net/wifi_wuxian/article/details/94437168)
希望上述內容可以幫助到大家~
不足之處與改進之處 :
1、本文只是進行一些簡單地爬蟲,過程中遇到一些問題,比如獲取tag,title,infotitle
存在列表中的,由於hou_code與這些字符串是一對多的關系,所以在進行dataframe(類似關系型數據庫)之后,這些信息就會發生錯位,這個問題沒有解決;使用循環解決???嘗試了it
doesn’t work
2、每個房屋的詳細信息可深一步研究
3、使用xpath的text()函數定位界面元素, 文本中含有空格如何解決呢?
4、地址如何批量獲取經緯度,在地圖上完美展示?(已解決,詳情 https://editor.csdn.net/md/?articleId=94437168)
5、可以進行模型分析,對於類別變量可進行獨熱編碼,計算WOE進行分箱,回歸預測房價走勢