日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何高效地爬取链家的房源信息(一)

發布時間:2023/11/27 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何高效地爬取链家的房源信息(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Python實現的鏈家網站的爬蟲第一部分。


在之前的文章,以鏈家成都站為例,分析過鏈家網站數據的爬取,文章如下:

干貨!鏈家二手房數據抓取及內容解析要點


但是,當時沒有根據分析,將爬取實現。


本系列文將以鏈家南京站為例,使用Python實現鏈家二手房源信息的爬蟲,將數據爬取,并存入數據庫中,以便使用。


本文是第一部分,是整個爬取的基礎,包括爬取邏輯、偽裝正常訪問、數據庫設計及封裝、區域URL爬取四個部分。


01

爬取邏輯


本文爬取的地區站雖與之前分析的地區站不同,但二者的結構是一樣的,之前分析的成果可以直接套用。


根據之前的分析成果,得到爬取流程如下:

第一步,找到爬取站點的地址,這里爬取的是南京站,為https://nj.lianjia.com/。

第二步,從二手房查詢頁面獲取大區信息,以便后續的查詢。

這樣的好處是可以分區查詢,避免單次數據太多,鏈家服務器無法返回全部內容,最終導致數據不全。

第二步,根據分區信息,獲取小區信息,存數據庫,后續爬取操作,均以小區信息為起點。

第三步,根據各個小區信息,獲取該小區的所有在售房源信息,存數據庫。

第四步,根據各個小區信息,獲取該小區的所有成交房源信息,存數據庫。


確定了爬取流程,也就確定了程序的基本框架,接下來我們還需要準備相關Python庫,數據庫——sqlite3,以及分析網頁庫——BeautifulSoup。后者的安裝參考:

Windows下Python 3.6 安裝BeautifulSoup庫


02


偽裝正常訪問


為避免被服務器發現爬蟲行為,通常需要準備一批User Agents,這里收集了一些UA,可以直接拿去使用:

hds = [{'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}, \

? ? ? ?{'User-Agent': 'Mozilla/5.0 (Windows NT 6.2) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.12 Safari/535.11'}, \

? ? ? ?{'User-Agent': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)'}, \

? ? ? ?{'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:34.0) Gecko/20100101 Firefox/34.0'}, \

? ? ? ?{'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/44.0.2403.89 Chrome/44.0.2403.89 Safari/537.36'}, \

? ? ? ?{'User-Agent': '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'}, \

? ? ? ?{'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50'}, \

? ? ? ?{'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0'}, \

? ? ? ?{'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1'}, \

? ? ? ?{'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1'}, \

? ? ? ?{'User-Agent': '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'}, \

? ? ? ?{'User-Agent': 'Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11'}, \

? ? ? ?{'User-Agent': 'Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11'}]


03


數據庫設計及封裝


由于房源數據量不小,使用文本方式保存明顯不便,因此,我們采用SQLite來進行數據的存儲。這里,設計三個數據庫,來保存不同的信息:

lianjia-xq.db,用來存儲小區信息,需要存儲URL、小區名稱、小區區域及建設年代等信息。


lianjia-cj.db,用來存儲小區成交二手房的信息,需要存儲鏈接、小區名稱、戶型、面積、朝向、裝修、電梯、簽約時間、簽約總價、樓層、年代樓型、來源、簽約單價、稅費、地鐵、掛牌價、成交周期等信息。


lianjia-zs.db用來存儲小區在售二手房的信息,需要存儲鏈接、房子描述、小區名稱、戶型、面積、朝向、裝修、電梯、樓層年代樓型、區域、關注、帶看、發布時間、稅費、地鐵、限制、掛牌價、掛牌單價等信息。


這樣,基本上把網站上的描述點都給提取出來了。


同時,我們對數據庫的操作進行封裝以便操作,直接參考網上的代碼,并適當修改,這里給出代碼:

class SQLiteWraper(object):

? ? """

? ? 數據庫的一個小封裝,更好的處理多線程寫入

? ? """

? ? def __init__(self, path, command='', *args, **kwargs):

? ? ? ? self.lock = threading.RLock()? # 鎖

? ? ? ? self.path = path? # 數據庫連接參數

? ? ? ? if command != '':

? ? ? ? ? ? conn = self.get_conn()

? ? ? ? ? ? cu = conn.cursor()

? ? ? ? ? ? cu.execute(command)


? ? def get_conn(self):

? ? ? ? conn = sqlite3.connect(self.path)? # ,check_same_thread=False)

? ? ? ? conn.text_factory = str

? ? ? ? return conn


? ? def conn_close(self, conn=None):

? ? ? ? conn.close()


? ? def conn_trans(func):

? ? ? ? def connection(self, *args, **kwargs):

? ? ? ? ? ? self.lock.acquire()

? ? ? ? ? ? conn = self.get_conn()

? ? ? ? ? ? kwargs['conn'] = conn

? ? ? ? ? ? rs = func(self, *args, **kwargs)

? ? ? ? ? ? self.conn_close(conn)

? ? ? ? ? ? self.lock.release()

? ? ? ? ? ? return rs


? ? ? ? return connection


? ? @conn_trans

? ? def execute(self, command, method_flag=0, conn=None):

? ? ? ? cu = conn.cursor()

? ? ? ? try:

? ? ? ? ? ? if not method_flag:

? ? ? ? ? ? ? ? cu.execute(command)

? ? ? ? ? ? else:

? ? ? ? ? ? ? ? cu.execute(command[0], command[1])

? ? ? ? ? ? conn.commit()

? ? ? ? except sqlite3.IntegrityError as e:

? ? ? ? ? ? # print e

? ? ? ? ? ? return -1

? ? ? ? except Exception as e:

? ? ? ? ? ? print(e)

? ? ? ? ? ? return -2

? ? ? ? return 0


? ? @conn_trans

? ? def fetchall(self, command="select name from xiaoqu", conn=None):

? ? ? ? cu = conn.cursor()

? ? ? ? lists = []

? ? ? ? try:

? ? ? ? ? ? cu.execute(command)

? ? ? ? ? ? lists = cu.fetchall()

? ? ? ? except Exception as e:

? ? ? ? ? ? print(e)

? ? ? ? ? ? pass

? ? ? ? return lists


同時,封裝幾個具體的操作。

生成小區數據庫插入操作命令:

def gen_xiaoqu_insert_command(info_dict):

? ? """

? ? 生成小區數據庫插入命令

? ? """

? ? info_list = [ u'url',u'小區名稱', u'大區域', u'小區域', u'建造時間']?

? ? t = []

? ? for il in info_list:

? ? ? ? if il in info_dict:

? ? ? ? ? ? t.append(info_dict[il])

? ? ? ? else:

? ? ? ? ? ? t.append('')

? ? t = tuple(t)

? ? command = (r"insert into xiaoqu values(?,?,?,?,?)", t) #?,

? ? return command


生成成交記錄數據庫插入操作命令:

def gen_chengjiao_insert_command(info_dict):

? ? """

? ? 生成成交記錄數據庫插入命令

? ? """

? ? info_list = [u'鏈接',u'小區名稱',u'戶型',u'面積',u'朝向',u'裝修',u'電梯',u'簽約時間',u'簽約總價',u'樓層',u'年代樓型',u'來源',u'簽約單價',u'稅費',u'地鐵',u'掛牌價',u'成交周期']

? ? t = []

? ? for il in info_list:

? ? ? ? if il in info_dict:

? ? ? ? ? ? t.append(info_dict[il])

? ? ? ? else:

? ? ? ? ? ? t.append('')

? ? t = tuple(t)

? ? command = (r"insert into chengjiao values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", t)

? ? return command


生成在售記錄數據庫插入操作命令:

def gen_zaishou_insert_command(info_dict):

? ? """

? ? 生成在售記錄數據庫插入命令

? ? """

? ? info_list = [u'鏈接',u'房子描述',u'小區名稱',u'戶型',u'面積',u'朝向',u'裝修',u'電梯',u'樓層年代樓型',u'區域',u'關注',u'帶看',u'發布時間',u'稅費',u'地鐵',u'限制',u'掛牌價',u'掛牌單價']

? ? t = []

? ? for il in info_list:

? ? ? ? if il in info_dict:

? ? ? ? ? ? t.append(info_dict[il])

? ? ? ? else:

? ? ? ? ? ? t.append('')

? ? t = tuple(t)

? ? command = (r"insert into zaishou values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", t)

? ? return command


當然,數據庫表需要創建:

command = "create table if not exists xiaoqu (url TEXT primary key UNIQUE,name TEXT, regionb TEXT, regions TEXT, year TEXT)"#

db_xq = SQLiteWraper('lianjia-xq.db', command)


command = "create table if not exists zaishou (href TEXT primary key UNIQUE, detail TEXT,xiaoqu TEXT, style TEXT, area TEXT, orientation TEXT, zhuangxiu TEXT, dianti TEXT, loucenniandai TEXT, quyu TEXT, guanzhu TEXT, daikan TEXT, fabushijian TEXT,shuifei TEXT,subway TEXT,xianzhi TEXT, total_price TEXT, unit_price TEXT)"

db_zs = SQLiteWraper('lianjia-zs.db', command)


command = "create table if not exists chengjiao (href TEXT primary key UNIQUE, name TEXT, style TEXT, area TEXT, orientation TEXT, zhuangxiu TEXT, dianti TEXT, sign_time TEXT, total_price TEXT, loucen TEXT, year TEXT,source TEXT, unit_price TEXT,shuifei TEXT, subway TEXT, guapaiprice TEXT, cycletime TEXT)"

db_cj = SQLiteWraper('lianjia-cj.db', command)


基礎準備好了,接下來就是具體的爬取了。


04


區域URL爬取及異常處理


爬取大區域的URL:

def get_qu_url_spider():

? ? """

? ? 爬取大區信息

? ? """

? ? url = u"https://nj.lianjia.com/xiaoqu/"

? ? try:

? ? ? ? req = urllib.request.Request(url, headers=hds[random.randint(0, len(hds) - 1)])

? ? ? ? source_code = urllib.request.urlopen(req, timeout=5).read()

? ? ? ? plain_text = source_code.decode('utf-8');

? ? ? ? soup = BeautifulSoup(plain_text,"html.parser")

? ? except (urllib.request.HTTPError, urllib.request.URLError) as e:

? ? ? ? print(e)

? ? ? ? return

? ? except Exception as e:

? ? ? ? print(e)

? ? ? ? return


? ? d=soup.find('div', {'data-role':"ershoufang"}).findAll('a');

? ? for item in d:

? ? ? ? href=item['href'];

? ? ? ? region = item.contents[0];

? ? ? ? fullhref=u"https://nj.lianjia.com"+href;

? ? ? ? print(region+fullhref);

? ? ? ? regions.append(region)

? ? ? ? regionurls.append(fullhref)


爬取過程中如果異常,寫入異常日志:

def exception_write(fun_name,url):

? ? """

? ? 寫入異常信息到日志

? ? """

? ? lock.acquire()

? ? f = open('log.txt','a')

? ? line="%s %s\n" % (fun_name,url)

? ? f.write(line)

? ? f.close()

? ? lock.release()


爬取的URL不需要存入數據庫,直接存到一個列表即可,然后遍歷,獲取各個大區域的小區信息。




在接下來將說明如何爬取小區信息、在售二手房信息、歷史成交二手房信息,敬請期待。

長按進行關注。

總結

以上是生活随笔為你收集整理的如何高效地爬取链家的房源信息(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

歡迎分享!

轉載請說明來源于"生活随笔",并保留原作者的名字。

本文地址:如何高效地爬取链家的房源信息(一)