學(xué)習(xí)記錄:搜房網(wǎng)新樓盤信息爬蟲

目標(biāo):爬取海南搜房網(wǎng)上的海南新樓盤信息

一、搜集待爬取的目標(biāo)網(wǎng)址

先打開海南搜房網(wǎng)進(jìn)入新樓盤頁面進(jìn)行研究,
http://newhouse.hn.fang.com/
但是這個頁面主要是信息聚合呈現(xiàn),新樓盤信息并不全,接著找到列表頁,
http://newhouse.hn.fang.com/house/s/
這回是想要的了。
經(jīng)研究發(fā)現(xiàn)該列表頁的網(wǎng)址加上分頁為如下形式,分頁共有28頁,分頁字段主要是在/b91/這部分
從b91到b928,這樣如果把這28頁爬完就能初步得到全部新樓盤條目,接著再對每個新樓盤的主頁進(jìn)行爬取提取信息,就能得到想要的內(nèi)容。
http://newhouse.hn.fang.com/house/s/b91/?ctm=1.hn.xf_search.page.1
具體某個樓盤主頁為:
http://zhongyangwenhuachengld.fang.com
樓盤詳情頁為:
http://zhongyangwenhuachengld.fang.com/house/5011126788/housedetail.htm
開始寫代碼,先導(dǎo)入依賴的庫

import requests
import re
from bs4 import BeautifulSoup

寫了一個函數(shù)用于提取某個頁面中包含的所有不重復(fù)鏈接,返回一個列表

def get_page_urls(url,regular="\w+"):
    if url is None:
        return None
    new_urls = set()
    headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/5.0.2.2000 Chrome/47.0.2526.73 Safari/537.36' }
    r = requests.get(url,headers=headers,timeout=None)
    if r.status_code == 200:
        soup = BeautifulSoup(r.text, 'html.parser',from_encoding='utf-8')
        links = soup.find_all('a', href=re.compile(r'%s' % regular))
        for link in links:
            new_url = link['href']
            new_urls.add(new_url)
            return list(new_urls)

沒想到在去重這部分花了很多時間。
開始對于每一個列表頁面進(jìn)行下載和解析,解析頁面內(nèi)所有的<a>標(biāo)簽,將鏈接地址提取出來,這里使用的正則表達(dá)式如下:

^https?://\w+.fang.com/$

將提取到的網(wǎng)址列表先存入一個set(),保證在一個頁面上抓到的網(wǎng)址沒有重復(fù),抓取完后再將該集合轉(zhuǎn)成list存入一個整體的網(wǎng)址列表中。
然后對全部網(wǎng)址進(jìn)行去除重復(fù),這里要去掉的重復(fù)網(wǎng)址是指頁面上其他的非樓盤鏈接,由于每一個樓盤列表頁都會有這些重復(fù)的信息,一共抓了28頁說明會有28個重復(fù),因此要想辦法去除這一部分的鏈接。
想來想去,想出先找出重復(fù)的網(wǎng)址,保存進(jìn)一個列表中,然后再將全部網(wǎng)址列表跟重復(fù)網(wǎng)址列表進(jìn)行比較,若有相同項則從全部網(wǎng)址列表中刪除重復(fù)網(wǎng)址項,這樣就能得出最后想要的每個新樓盤主頁。重點代碼為:

if all_urls.count(housepage) > 1:

總覺得這樣做是個笨辦法效率不高,因為有重復(fù)操作,不知道有沒有更方便的算法,目前想不出來。
經(jīng)過一番提取去重后,得到一個所有樓盤詳情頁鏈接的文本文件,用于后續(xù)信息抓取。保存的代碼為:

with open('soufangwang-detail.txt','w',encoding='utf-8') as f:
    for i in all_detail_urls:
        f.write(i)
        f.write("\n")

二、抓取信息

首先研究了一下樓盤詳情頁結(jié)構(gòu),想爬取的結(jié)構(gòu)信息是如下這樣的,每條信息在一條li的下面有兩個<div>,第一個是信息名稱,第二個是信息值,90%的信息都是這樣的結(jié)構(gòu),除了部分標(biāo)題,主圖等:

<li>
<div class="list-left">交房時間:</div>
<div class="list-right">預(yù)計2017年6月30日A#、B#、C#交房</div>
</li>

開始的想法是針對信息條目,一條條分析進(jìn)行抓取,根據(jù)每個想要的信息構(gòu)造對應(yīng)的抓取函數(shù):

name_node = soup.find('h1').find('a',class_="ts_linear")
data["樓盤名稱"] = name_node.get_text()
address_node = soup.find('div',string = re.compile("樓盤地址")).find_next('div')
data["樓盤地址"] = address_node.get_text()

但是這樣做,首先是發(fā)現(xiàn)如果有的信息名稱是三個字的話,搜房網(wǎng)會在中間插入i標(biāo)簽,像下面的例子,導(dǎo)致抓取函數(shù)無法抓取到正確的<div>。

<li>
<div class="list-left">容<i style="margin-right: 6px;"></i>積<i style="margin-right: 6px;"></i>率:</div>
<div class="list-right">3.50 </div>
</li>

于是在這里研究了好久,先是各種換搜索正則表達(dá)式,怎么都搜不到,后來突發(fā)奇想,能不能在抓取之前把所有的i標(biāo)簽去掉,于是查文檔,寫了如下代碼

soup = BeautifulSoup(r.text, 'html.parser')
    for tag_i in soup.findAll('i'):
    tag_i.decompose()

這樣先對下載到的文檔進(jìn)行處理再抓取應(yīng)該是可以的,但是很奇怪,去掉i標(biāo)簽后文字還是無法查找到,這回真的卡殼了。
然后經(jīng)過一番冥思苦想,忽然想到,干嘛要一個個信息來針對性抓取啊,既然它結(jié)構(gòu)大部分都是相同的,干脆全部抓取出來存入一個字典里好了。于是開始寫代碼:

data = {}
key_nodes = soup.findAll('div', class_="list-left")
for key_node in key_nodes:
    key = key_node.get_text().replace("\t","").replace("\n","").replace("\r","").replace(":","").strip()
    value_node = key_node.find_next('div')
    value = value_node.get_text().replace("\t","").replace("\n","").replace("\r","").strip()
    data[key] = value

抓取成功!發(fā)現(xiàn)這樣做不光效率高,而且既方便又能容錯,獲得的信息也全,唉怎么不早點想到呢,折騰好久。
另外在頁面結(jié)構(gòu)中發(fā)現(xiàn)有一個<script>標(biāo)簽內(nèi)有樓盤的主圖,因此也想把這部分抓取下來,這段的原始結(jié)構(gòu)是這樣的:

<script>
newcode='5011111904';
projn = '清瀾半島';
newhousedomaintail='house/';
newhousedomain = 'http://newhouse.hn.fang.com';
address='文昌市';
vcity= '海南';
ucity = '%BA%A3%C4%CF';
price = '13000';
pricetype = '元/平方米';
priceright = '13000';
pricetyperight = '元/平方米';
face = 'http://imgs.soufun.com/house/2013_10/30/hainan/1383115329744_000.jpg';
houseurl = 'http://qinglanbandao.fang.com/';
microID=0;
bbsError ="0";
bbs_id ="5011111904";
</script>

先初步寫了個節(jié)點抓取語句,成功找到該<script>標(biāo)簽

script_node = soup.find('script', string = re.compile("face ="))

但是抓取之后怎么轉(zhuǎn)成字典的鍵值對呢,搜索加研究,使用split()函數(shù)可以實現(xiàn),方法如下,注意處理末尾多出來的一個分號:

subdata = (script_node.get_text().replace("\r","").replace("\n","").replace("\t","").replace(";", ",").replace("'","").replace(" ",""))[:-1]
subdata_dict = dict(s.split('=') for s in subdata.split(','))
data['樓盤主圖'] = subdata_dict['face']
data['樓盤主頁'] = subdata_dict['houseurl']

一些小問題和解決方法:

  • 頁面中文亂碼,若是知道頁面編碼的話,可以直接寫
r.encoding = "所用編碼"

如果不知道的話,可以試試寫上,一般都會解決

r.encoding = r.apparent_encoding

但是有些頁面怎么弄都是亂碼,不知道是不是繁體中文編的碼,待解決

  • 刪除文檔中的換行符回車符制表符和空格,一般用
replace("\n","") #刪除全部換行符
strip() #刪除開頭和結(jié)尾的空白符(包括'\n', '\r', '\t',  ' ')
rstrip('\n') #刪除結(jié)尾的換行符
lstrip() #刪除開頭的空白符

三、存入excel文件

信息抓取到了,要保存為excel文件。
在官網(wǎng)搜索了一下,先在命令行用pip命令下載excel的支持庫

pip install xlwt

參考官網(wǎng)的例子,xlw的使用方法為:

wb = xlwt.Workbook() #新建一個工作簿
ws = wb.add_sheet('新工作表') #新建一個工作表
ws.write(行索引, 列索引, 數(shù)據(jù)) #寫入數(shù)據(jù)
wb.save('海南新樓盤.xls') #保存

這樣就成功將海南搜房網(wǎng)新樓盤信息抓取下來了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,836評論 6 540
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,275評論 3 428
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,904評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,633評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,368評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,736評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,740評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,919評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,481評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,235評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,427評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,968評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,656評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,055評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,348評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,160評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,380評論 2 379

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,712評論 25 708
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,818評論 18 139
  • 這個系列的第六個主題,主要談一些搜索引擎相關(guān)的常見技術(shù)。 1995年是搜索引擎商業(yè)公司發(fā)展的重要起點,《淺談推薦系...
    我偏笑_NSNirvana閱讀 6,693評論 3 24
  • 微信對話框一直顯示對方正在輸入,許久之后才收到君君給我發(fā)過來的消息,我以為會是很長的一段話,結(jié)果卻是這么簡單的一句...
    南遙思故閱讀 2,078評論 2 18
  • 《我可以任你宰割》 文/愚木 你打擾了我 等于是殺了我 是否要我反綁雙手任你宰割 這就是你的美 驚起了早晨的風(fēng) 而...
    愚木的簡書閱讀 458評論 1 1