Python抓取58同城深圳合租房源和自如有家租房信息

目的:了解深圳單簡出租房屋的價格分布

成果(簡單可視化):

各地區(qū)數(shù)據(jù)

各地區(qū)平均合租租金和平均面積
標(biāo)題詞云圖

各地區(qū)自如租房和GDP
平均臥室面積
自如有家住房價格和臥室面積散點圖

由于請求限制目前,目前樣本只有1200個左右。有待。


hotmap
hotmap

hotmap

主要使用的庫:BeautifulSoup,requests,Pool

IDE:Pycharm

瀏覽器:Opera Next

數(shù)據(jù)庫:Mongodb

分析工具:Power BI,Excel

一,編寫爬蟲

(1)抓取各個地區(qū)的主頁面

58同城深圳合租主頁

我們要把每個地區(qū)的主網(wǎng)頁抓下來,導(dǎo)入需要的庫


from bs4 import BeautifulSoup

import requests

先點一個地區(qū)看一下網(wǎng)址是什么樣子的

我們得到了:sz.58.com/futian/hezu/

再看一下地區(qū)所在的標(biāo)簽

image

在dd下的a標(biāo)簽,url后部分是href部分

可以知道各個地區(qū)的url是:http://sz.58.com +'href'http://sz.58.com + /futian/hezu/

定義一下主頁部分:

host_url ='http://sz.58.com'

接下來可以定義抓取的函數(shù)了

def get_index_url(url):

  wb_data =requests.get(url)

  soup = BeautifulSoup(wb_data.text,'lxml')

  links = soup.select('body > div.mainbox > div.main > div.search_bd >     dl.secitem.secitem_fist > dd > a')#用copy中的copy selector

    for linkin links:

      page_url = host_url + link.get('href')

      print(page_url)

我們把所有a中的href取出來和主頁http://sz.58.com加在一起再打印出來,就得到了各個地區(qū)的合租主頁了,其實這幾個可以手動復(fù)制粘貼出來,但是Life is short,U need Python.這也是我們Python的一個原因。

打印出來把他直接復(fù)制出來定義成hezu_channel

hezu_channel ='''

http://sz.58.com/luohu/hezu/

http://sz.58.com/futian/hezu/

http://sz.58.com/nanshan/hezu/

http://sz.58.com/yantian/hezu/

http://sz.58.com/baoan/hezu/

http://sz.58.com/longgang/hezu/

http://sz.58.com/buji/hezu/

http://sz.58.com/pingshanxinqu/hezu/

http://sz.58.com/guangmingxinqu/hezu/

http://sz.58.com/szlhxq/hezu/

http://sz.58.com/dapengxq/hezu/

http://sz.58.com/shenzhenzhoubian/hezu/

'''

注意這里有一個'所有'下的鏈接,把它手動刪除

(2)抓取各個地區(qū)的網(wǎng)頁上的數(shù)據(jù)

由于我們想要的標(biāo)題、價格、地址、面積信息都在頁面上展示了就不用再下到詳細(xì)頁面去抓取了

image

現(xiàn)在導(dǎo)入鏈接mongodb的庫pymongo,還有讓爬蟲休息一下避免被封ip的time庫和random(讓時間隨機(jī)一下)

import pymongo

import random

import time

先在mongodb創(chuàng)建庫

client = pymongo.MongoClient('localhost',27017)

work = client['work']

hezu2 = work['hezu2']

寫一個函數(shù)能抓取一個頁面的信息,變量為前面得到的channel_list和頁碼(待會對頁碼做個循環(huán)就可以遍歷所有頁了)

我們先看一下網(wǎng)頁結(jié)構(gòu):http://sz.58.com/futian/hezu/

點擊第二頁:http://sz.58.com/futian/hezu/pn2/

我們試試把pn2給成pn1,結(jié)果是跳到第一頁,可以知道對channel_list中的url加上pn{}就可以翻頁了

于是頁面構(gòu)成變?yōu)椋篶hannel_list+pn{}

寫一個函數(shù)包含著兩個變量

def get_url_all_infom(channel,pages):

list_view ='{}pn{}'.format(channel,str(pages))#要看的頁url

wb_data = requests.get(list_view)#請求

soup = BeautifulSoup(wb_data.text,'lxml')#解析

由于有些地區(qū)的頁碼沒有70頁(如坪山) ,我們要判斷如果沒有就跳過,唯一標(biāo)識就是頁碼欄了

看一下源代碼的位置

image

這里有一個strong,我們看看是不是唯一的,搜索發(fā)現(xiàn)的確是唯一的,而對pn9的頁面是沒有的,我們可以把‘strong’作為唯一標(biāo)識

如果在soup發(fā)現(xiàn)了這個標(biāo)識就抓取,沒有的話就打印ERROR

if soup.find('strong'):

  try:

  except:

    print('ERROR')

接下來是抓取元素

一樣的,我們找到所對應(yīng)的標(biāo)簽,這里要調(diào)整的是我們要抓取標(biāo)簽下的所有子標(biāo)簽

titles = soup.select('li > div > h2 > a')

areas = soup.select('body > div.mainbox > div.main > div.content > div.listBox > ul > li > div.des > p.add')

zones = soup.select('body > div.mainbox > div.main > div.content > div.listBox > ul > li > div.des > p.room')

links = soup.select('li > div > h2 > a')

prices = soup.select('body > div.mainbox > div.main > div.content > div.listBox > ul > li > div.listliright > div.money > b')

把這些東西裝進(jìn)一個字典

for title, area, price, zone, linkin zip(titles, areas, prices, zones, links):

    title = title.text,#直接把文本提取出來

    area = area.text + list_view.split('/')[-3],#同理,但是這里的位置沒有區(qū)名,我們從訪問的url提取,用split根據(jù)/把url拆開再取倒數(shù)第三個(http://sz.58.com/**pingshanxinqu**/hezu/pn2/)

    price = price.text,#這里可以用int轉(zhuǎn)成數(shù)值,但是可能出現(xiàn)價格為‘面議’的情況,所以直接這樣處理

    zone = zone.text.split(' ')[-1],#面積標(biāo)簽下還有是否是主臥次臥,我們只要面積

    link = link.get('href')#可以把這個租房的地址也取出來

要通過一定的方法把要的東西篩選出來,具體看注釋。

然后對字典里的逐一插入數(shù)據(jù)庫

hezu2.insert_one({'title':title,'area':area,'price':price,'zone':zone,'link':link})

睡上一些時間

i=int(random.choice([20,22,23]))

time.sleep(i)

完整代碼:

def get_url_all_infom(channel,pages):

list_view ='{}pn{}'.format(channel,str(pages))

wb_data = requests.get(list_view)

soup = BeautifulSoup(wb_data.text,'lxml')

if soup.find('strong'):

try:

titles = soup.select('li > div > h2 > a')

areas = soup.select('body > div.mainbox > div.main > div.content > div.listBox > ul > li > div.des > p.add')

zones = soup.select('body > div.mainbox > div.main > div.content > div.listBox > ul > li > div.des > p.room')

links = soup.select('li > div > h2 > a')

prices = soup.select('body > div.mainbox > div.main > div.content > div.listBox > ul > li > div.listliright > div.money > b')

for title, area, price, zone, linkin zip(titles, areas, prices, zones, links):

                title = title.text,

                area = area.text + list_view.split('/')[-3],

                price = price.text,

                zone = zone.text.split(' ')[-1],

                link = link.get('href')

hezu2.insert_one({'title':title,'area':area,'price':price,'zone':zone,'link':link})

i=int(random.choice([20,22,23]))

time.sleep(i)

except:

print('ERROR')

我們使用多進(jìn)程處理,新建一個main.py調(diào)動所有要用的函數(shù)

#-*- coding: utf-8 -*-

from multiprocessingimport Pool

from parsingimport get_url_all_infom#抓取信息并插入數(shù)據(jù)庫的函數(shù)

from shenzhen_extractimport hezu_channel_list#各個地區(qū)的主頁列表

def get_all_from(channel):#提取各地區(qū)里的1到70頁的鏈接

    for iin range(1,71):

get_url_all_infom(channel,i)#用這個函數(shù)提取地區(qū)所有鏈接

if __name__ =='__main__':

pool = Pool()

# pool = Pool(processes=4)

    pool.map(get_all_from,hezu_channel_list.split())#map函數(shù)可以用第一個參數(shù)中的函數(shù)一一處理第二個參數(shù)的元素(用split把他們拆分一一放進(jìn)get_all_from)

我們再編寫一個監(jiān)控腳本,當(dāng)數(shù)據(jù)庫中的數(shù)據(jù)不發(fā)生變化時發(fā)出警告(可能是58同城監(jiān)視到了要求輸入驗證碼,可以手動輸入一下)

import time

from parsingimport hezu2

import winsound#是一個發(fā)出聲音的函數(shù)

print('ok~')

t=0

while True:

print(hezu2.find().count())

i = int(hezu2.find().count())

time.sleep(5)

print(hezu2.find().count())

time.sleep(5)

if i == int(hezu2.find().count()):

       winsound.Beep(1000,5000)#1000位頻率,5000為時間

(3)終端運行爬蟲

先運行main.py,到所在文件夾調(diào)用命令python main.py

再運行counts.py

(4)改進(jìn)與問題

多進(jìn)程只對多核處理器有用

BeautifulSoup解析速度過慢,可改用lxml庫

異步非阻塞方式提高請求效率

異步網(wǎng)絡(luò)和多個ip請求

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 不知不覺讀書已經(jīng)是第三個月了。再過10天洪鎮(zhèn)洙就要變成另外一個人了。想想自己一路走來,除了戀愛的時候,這還是第一次...
    休文刀閱讀 133評論 0 1
  • 生命中感恩遇到慈悲大愛智慧的格西老師,讓我通過種子法則的學(xué)習(xí)放大了格局,有意的做出慷慨的行為,去施善幫助能幫到的人...
    張蓉萍閱讀 117評論 1 2
  • 前 言 在網(wǎng)頁制作過程中,布局是我們最重要的一個環(huán)節(jié)。可以說布局的好壞直接影響到整個網(wǎng)頁的成?。〔季殖?,則事半功倍...
    小風(fēng)飛魚閱讀 6,284評論 2 25

友情鏈接更多精彩內(nèi)容