疫情過去女朋友想去重慶玩,python批量爬取小豬短租重慶民宿信息

疫情過去女朋友想去重慶玩,python批量爬取小豬短租重慶民宿信息

隨着時間的流逝,在中國共產黨的領導,全國人民的共同努力下,疫情逐漸受到了控制,逐漸好轉,復工,開學有望。最近在和女朋友的閒聊當中得知她想五一去重慶你玩兒,上完網課後,閒來無事,就想的能不能直接把小豬短租上的重慶住宿信息批量爬取下來,順便爲自己的爬蟲能力做做練習,話不多說,直接開整!

首先打開小豬短租的網頁,給出第一頁的 url:

url = 'https://cq.xiaozhu.com/search-duanzufang-p0-0/'

在這裏插入圖片描述
可以看出我選擇的關鍵詞是重慶,之後就會顯示出民宿的信息,經過下拉瀏覽,我發現這個網頁是使用頁數來進行網頁的跳轉,我判斷這個網頁是靜態網頁。我先分析這個網頁的請求,看看自己想要的內容在哪。
在這裏插入圖片描述
在這裏插入圖片描述在Request Headers中是沒有params參數列表這一項的,說明確實是通過點擊不同的頁數更改網頁的url鏈接來更新網頁的信息。再進行觀察,並沒有什麼特別的地方,我感覺這和網頁在構造請求頭的時候只需要設置 User-Agent 即可,一會兒我就試試我的猜想。

在General中,可以看到Request URL 鏈接也沒有跟的參數信息,使用的請求方法是GET,還可以看到服務器的IP地址等信息。

接着我點擊不同的頁數,複製每次的URL鏈接,看看它的變化規律:

https://cq.xiaozhu.com/search-duanzufang-p0-0/
https://cq.xiaozhu.com/search-duanzufang-p1-0/
https://cq.xiaozhu.com/search-duanzufang-p2-0/

可以發現它的變化僅僅在於p0,p1的變化,用來控頁數,接着我們就來看看自己所要的信息在哪,由於判斷是靜態網頁,在服務器返回的時候直接返回所有數據,那麼源代碼可能在第一個響應中:
在這裏插入圖片描述
果然我在第一個請求響應中找到網頁未經渲染的源代碼,並發現每一個房子的相關信息都存在 li 標籤當中,然後我就開始着手寫代碼了,直接上代碼:

導入的庫(這裏我才用Xpath的方法進行定點提取,所以導入了lxml庫):

'''
小豬短租:重慶
'''
import time
import re
import requests
import lxml
from lxml import etree

獲得網頁源碼:

def getHTMLText(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36',

    }
    try:
        r = requests.get(url,headers = headers,timeout=5)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return '頁面訪問錯誤'

主方法構造網頁鏈接列表:

if __name__ == '__main__':
    # url = 'https://cq.xiaozhu.com/search-duanzufang-p0-0/'
    url_list = []
    #range 大小控制爬取房子信息的頁數
    for i in range(1):
        i = str(i)
        url = 'https://cq.xiaozhu.com/search-duanzufang-p' + i +'-0/'
        url_list.append(url)
    for i in url_list:
        text = getHTMLText(i)
        get_house_information(text)

使用Xpath提取房子信息,並進行輸出(我將每個信息的源碼標籤寫在每個Xpath的上方,這是我在編寫代碼的時候方便進行分析和編寫代碼):

def get_house_information(text):
    tree = etree.HTML(text)
    #<a target="_blank" href="https://cq.xiaozhu.com/fangzi/129561560803.html" class="resule_img_a">
    house_href = tree.xpath('//a[contains(@target,"_blank") and @class="resule_img_a"]/@href')
    # <img class="lodgeunitpic" title="磁器口古鎮 川外西政 地鐵站一室北歐大牀整租"
    house_name = tree.xpath('//img[@class="lodgeunitpic"]/@title')
    # <span class="result_price">&#165;<i>238</i>起/晚</span>
    house_price = tree.xpath('//span[@class="result_price"]//i/text()')
    #<a class=="search_result_gridsum" href="https://www.xiaozhu.com/fangdong/105924673701/" target="_blank">
    house_ownerInfo = tree.xpath('//a[contains(@class,"search_result_gridsum") and @target="_blank"]/@href')
    # <em class="hiddenTxt">整套出租/1室0廳/1張牀/宜住2人    <span class="commenthref">- 0條點評   </span></em>
    house_size = tree.xpath('//em[@class="hiddenTxt"]/text()')
    house_remark_num = tree.xpath('//em[@class="hiddenTxt"]/span[@class="commenthref"]/text()')
    #返回值有換行符需要處理   normalize-space  我不建議這麼做
    house_size = sub_house_size(house_size)
    house_remark_num = sub_house_remark_num(house_remark_num)
    #  <span class="col_slogn" title="速訂:下單即可入住,無需房東確認"><i class="new_ico"></i>速訂</span>
    house_condition = tree.xpath('//span[@class="col_slogn"]/@title')

    # print(house_size)
    # print(house_remark_num)


    for i in range(len(house_size)):
        print('房子名稱:{}'.format(house_name[i]))
        print('房子一晚價格:{}'.format(house_price[i]))
        print('房子大小:{}'.format(house_size[i]))
        print('房子評論數:{}'.format(house_remark_num[i]))
        print('房子入住信息:{}'.format(house_condition[i]))
        print('房子詳細鏈接:{}'.format(house_href[i]))
        print('房子主人信息鏈接:{}'.format(house_ownerInfo[i]))
        print('------------------------------------------------------------')

在這裏我想強調的是Xpath對於爬取文本含空格符等信息的時候很難在爬取過程中直接進行處理,網上大多的方法是使用 normalize-space 方法,但這回只保留一個返回值,我不建議這麼做,我建議另寫函數用正則表達式對返滬文本中的空格符進行處理,所以對於房子的 house_size 和 house_remark_num 這兩個信息在處理的時候,我另寫了兩個方法來對其進行處理:

def sub_house_size(list):
    list_new = []
    result = []
    for i in list:
        i = re.sub(r'\n','',i)
        list_new.append(i)
    for i in list_new[::2]:
        result.append(i)
    return result

def sub_house_remark_num(list):
    result = []
    for i in list:
        i = re.sub(r'\n','',i)
        result.append(i)
    return result

這就是我全部的代碼,後臺執行結果:
在這裏插入圖片描述

自我感覺,對於這些靜態網頁的爬取,Xpath和CSS選擇器代碼量和方法更爲簡單和只管,現在自己已經開始不怎麼喜歡使用BeautifulSoup方法了…

謝謝大家能看我寫的分享😁

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章