Python爬蟲項目--爬取自如網房源信息

来源:https://www.cnblogs.com/star-zhao/archive/2018/09/13/9637588.html
-Advertisement-
Play Games

本次爬取自如網房源信息所用到的知識點: 1. requests get請求 2. lxml解析html 3. Xpath 4. MongoDB存儲 正文 1.分析目標站點 1. url: http://hz.ziroom.com/z/nl/z3.html?p=2 的p參數控制分頁 2. get請求 ...


本次爬取自如網房源信息所用到的知識點:

1. requests get請求

2. lxml解析html

3. Xpath

4. MongoDB存儲

正文

1.分析目標站點

1. url: http://hz.ziroom.com/z/nl/z3.html?p=2 的p參數控制分頁

2. get請求

2.獲取單頁源碼

 1 # -*- coding: utf-8 -*-
 2 import requests
 3 import time
 4 from requests.exceptions import RequestException
 5 def get_one_page(page):
 6     try:
 7         url = "http://hz.ziroom.com/z/nl/z2.html?p=" + str(page)
 8         headers = {
 9             'Referer':'http://hz.ziroom.com/',
10             'Upgrade-Insecure-Requests':'1',
11             'User-Agent':'Mozilla/5.0(WindowsNT6.3;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/68.0.3440.106Safari/537.36'
12         }
13         res = requests.get(url,headers=headers)
14         if res.status_code == 200:
15             print(res.text)
16     except RequestException:
17         return None
18 def main():
19     page = 1
20     get_one_page(page)
21 if __name__ == '__main__':
22     main()
23     time.sleep(1)

3.解析單頁源碼

1. 解析html文檔, 目的: 測試XPath表達式

將獲取的源碼保存到當前文件夾下的"result.html"中, 然後通過XPath對其進行相應內容的提取, 當然你也可以使用某些線上工具.

 1 from lxml import etree
 2 #解析html文檔
 3 html = etree.parse("./resul.html",etree.HTMLParser())
 4 results = html.xpath('//ul[@id="houseList"]/li')
 5 for result in results[1:]:
 6     title = result.xpath("./div/h3/a/text()")[0][5:] if len(result.xpath("./div/h3/a/text()")[0]) >5 else ""
 7     location = result.xpath("./div/h4/a/text()")[0].replace("[","").replace("]",'')
 8     area = " ".join(result.xpath("./div/div/p[1]/span/text()")).replace(" ","",1) #使用join方法將列表中的內容以" "字元連接
 9     nearby = result.xpath("./div/div/p[2]/span/text()")[0]
10     print(title)
11     print(location)
12     print(area)
13     print(nearby)

2. 解析源代碼

 1 from lxml import etree
 2 def parse_one_page(sourcehtml):
 3     '''解析單頁源碼'''
 4     contentTree = etree.HTML(sourcehtml)   #解析源代碼
 5     results = contentTree.xpath('//ul[@id="houseList"]/li') #利用XPath提取相應內容
 6     for result in results[1:]:
 7         title = result.xpath("./div/h3/a/text()")[0][5:] if len(result.xpath("./div/h3/a/text()")[0]) > 5 else ""
 8         location = result.xpath("./div/h4/a/text()")[0].replace("[", "").replace("]", '')
 9         area = " ".join(result.xpath("./div/div/p[1]/span/text()")).replace(" ", "", 1)  # 使用join方法將列表中的內容以" "字元連接
10         nearby = result.xpath("./div/div/p[2]/span/text()")[0]
11         yield {
12         "title": title,
13         "location": location,
14         "area": area,
15         "nearby": nearby
16         }
17 def main():
18     page = 1
19     html = get_one_page(page)
20     print(type(html))
21     parse_one_page(html)
22     for item in parse_one_page(html):
23       print(item)
24 
25 if __name__ == '__main__':
26     main()
27     time.sleep(1)

4.獲取多個頁面

 1 def parse_one_page(sourcehtml):
 2     '''解析單頁源碼'''
 3     contentTree = etree.HTML(sourcehtml)   #解析源代碼
 4     results = contentTree.xpath('//ul[@id="houseList"]/li') #利用XPath提取相應內容
 5     for result in results[1:]:
 6         title = result.xpath("./div/h3/a/text()")[0][5:] if len(result.xpath("./div/h3/a/text()")[0]) > 5 else ""
 7         location = result.xpath("./div/h4/a/text()")[0].replace("[", "").replace("]", '')
 8         area = " ".join(result.xpath("./div/div/p[1]/span/text()")).replace(" ", "", 1)  # 使用join方法將列表中的內容以" "字元連接
 9         #nearby = result.xpath("./div/div/p[2]/span/text()")[0].strip()這裡需要加判斷, 改寫為下句
10         nearby = result.xpath("./div/div/p[2]/span/text()")[0].strip() if len(result.xpath("./div/div/p[2]/span/text()"))>0 else ""
11         yield {
12         "title": title,
13         "location": location,
14         "area": area,
15         "nearby": nearby
16         }
17         print(nearby)
18     #yield {"pages":pages}
19 def get_pages():
20     """得到總頁數"""
21     page = 1
22     html = get_one_page(page)
23     contentTree = etree.HTML(html)
24     pages = int(contentTree.xpath('//div[@class="pages"]/span[2]/text()')[0].strip("共頁"))
25     return pages
26 def main():
27     pages = get_pages()
28     print(pages)
29     for page in range(1,pages+1):
30         html = get_one_page(page)
31         for item in parse_one_page(html):
32             print(item)
33 
34 if __name__ == '__main__':
35     main()
36     time.sleep(1)

5. 存儲到MongoDB中

需確保MongoDB已啟動服務, 否則必然會存儲失敗

 1 def save_to_mongodb(result):
 2     """存儲到MongoDB中"""
 3     # 創建資料庫連接對象, 即連接到本地
 4     client = pymongo.MongoClient(host="localhost")
 5     # 指定資料庫,這裡指定ziroom
 6     db = client.iroomz
 7     # 指定表的名稱, 這裡指定roominfo
 8     db_table = db.roominfo
 9     try:
10         #存儲到資料庫
11         if db_table.insert(result):
12             print("---存儲到資料庫成功---",result)
13     except Exception:
14         print("---存儲到資料庫失敗---",result)

6.完整代碼

 1 # -*- coding: utf-8 -*-
 2 
 3 import requests
 4 import time
 5 import pymongo
 6 from lxml import etree
 7 from requests.exceptions import RequestException
 8 def get_one_page(page):
 9     '''獲取單頁源碼'''
10     try:
11         url = "http://hz.ziroom.com/z/nl/z2.html?p=" + str(page)
12         headers = {
13             'Referer':'http://hz.ziroom.com/',
14             'Upgrade-Insecure-Requests':'1',
15             'User-Agent':'Mozilla/5.0(WindowsNT6.3;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/68.0.3440.106Safari/537.36'
16         }
17         res = requests.get(url,headers=headers)
18         if res.status_code == 200:
19             return res.text
20         return None
21     except RequestException:
22         return None
23 def parse_one_page(sourcehtml):
24     '''解析單頁源碼'''
25     contentTree = etree.HTML(sourcehtml)   #解析源代碼
26     results = contentTree.xpath('//ul[@id="houseList"]/li') #利用XPath提取相應內容
27     for result in results[1:]:
28         title = result.xpath("./div/h3/a/text()")[0][5:] if len(result.xpath("./div/h3/a/text()")[0]) > 5 else ""
29         location = result.xpath("./div/h4/a/text()")[0].replace("[", "").replace("]", '')
30         area = " ".join(result.xpath("./div/div/p[1]/span/text()")).replace(" ", "", 1)  # 使用join方法將列表中的內容以" "字元連接
31         #nearby = result.xpath("./div/div/p[2]/span/text()")[0].strip()這裡需要加判斷, 改寫為下句
32         nearby = result.xpath("./div/div/p[2]/span/text()")[0].strip() if len(result.xpath("./div/div/p[2]/span/text()"))>0 else ""
33         data = {
34         "title": title,
35         "location": location,
36         "area": area,
37         "nearby": nearby
38         }
39         save_to_mongodb(data)
40     #yield {"pages":pages}
41 def get_pages():
42     """得到總頁數"""
43     page = 1
44     html = get_one_page(page)
45     contentTree = etree.HTML(html)
46     pages = int(contentTree.xpath('//div[@class="pages"]/span[2]/text()')[0].strip("共頁"))
47     return pages
48 def save_to_mongodb(result):
49     """存儲到MongoDB中"""
50     # 創建資料庫連接對象, 即連接到本地
51     client = pymongo.MongoClient(host="localhost")
52     # 指定資料庫,這裡指定ziroom
53     db = client.iroomz
54     # 指定表的名稱, 這裡指定roominfo
55     db_table = db.roominfo
56     try:
57         #存儲到資料庫
58         if db_table.insert(result):
59             print("---存儲到資料庫成功---",result)
60     except Exception:
61         print("---存儲到資料庫失敗---",result)
62 
63 def main():
64     pages = get_pages()
65     print(pages)
66     for page in range(1,pages+1):
67         html = get_one_page(page)
68         parse_one_page(html)
69 
70 if __name__ == '__main__':
71     main()
72     time.sleep(1)
點擊查看

7.最終結果

總結

1. 在第三步中XPath使用註意事項

title = result.xpath("./div/h3/a/text()")
此處的點'.'不能忘記, 它表示當前節點, 如果不加'.', '/'就表示從根節點開始選取

 2. 在第四步獲取多個頁面時出現索引超出範圍錯誤

nearby = result.xpath("./div/div/p[2]/span/text()")[0].strip()

IndexError: list index out of range

   造成這種錯誤原因有兩種:

   1) [index] index超出list範圍

   2) [index] index索引內容為空

   因為這裡的nearby的index是0, 排除第一種情況, 那麼這裡就是空行了, 加句if判斷就可以解決

nearby = result.xpath("./div/div/p[2]/span/text()")[0].strip()
#改寫以後:
nearby = result.xpath("./div/div/p[2]/span/text()")[0].strip() if len(result.xpath("./div/div/p[2]/span/text()"))>0 else ""

 以上主要是對爬蟲過程學習的總結, 若有不對的地方, 還請指正, 謝謝!

因還在學習中, 價格部分會用到圖片識別, 有待完善.


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 明天老王要給我們講JVM的知識,提前發了一個小Demo給我們看,代碼如下: 運行上述代碼,結果毫無疑問,電腦瞬間開始狂躁起來,過了十幾秒,然後G了 基於JDK1.8運行的,估計老版本會崩的更快。。。 如果不計算記憶體,這個HashMap一共要插入4000*4000*4個對象,但是其實只有4個是不重覆的 ...
  • 據說Visual Studio Code(VS Code)的諸多好處,瞭解了一下果然很喜歡,我喜歡它的原因主要有3個,一是VS Code開源且跨平臺,二是因為其界面非常酷,三是可以我的大所屬代碼需求,除此之外當然還有強大的好奇心。使用VScode編寫第一個Python程式“one.py”,並將其打包... ...
  • 本文主要記錄如何使用aop切麵的方式來實現日誌記錄功能。 主要記錄的信息有: 操作人,方法名,參數,運行時間,操作類型(增刪改查),詳細描述,返回值。 ...
  • 最近工作上的事不忙了,開始忙著找房子了 我打算在天津再買一套房子,一個是投資一個是給我爸換個環境 但是二手的房子真的很少有非常完美的 現在天天守著以鏈家為主的APP看各種房子,晚上睡覺滿腦袋飛戶型圖 再有一個愁人的就是因為我在北京有房貸,所以在天津也算二套 二套要60%的首付,我手裡的錢不夠,還要湊 ...
  • c/c++ 標準順序容器 之 push_back,push_front,insert,emplace 操作 關鍵概念:向容器添加元素時,添加的是元素的拷貝,而不是對象本身。隨後對容器中元素的任何改變都不會影響到原始對象,反之亦然。 關鍵警告:因為vector,deque,string的記憶體存儲都是在 ...
  • 前面的菜單、部門、職位與管理員管理功能完成後,接下來要處理的是將它們關聯起來,根據職位管理中選定的許可權控制菜單顯示以及頁面數據的訪問和操作。 那麼要怎麼改造呢?我們可以通過用戶的操作步驟來一步步進行處理,具體思路如下: 1.用戶在管理端登錄時,通過用戶記錄所綁定的職位信息,來確定用戶所擁有的許可權。我 ...
  • /*介面List分為LinkedList和ArrayList;泛型<String>規定該類new出的對象或聲明的引用只能存放String類的對象 eg:List<String> map = new LinkedList<String>(); List<Integer> map = new Linke ...
  • 矩陣 並不想扯什麼高端線代的內容因為我也不會 定義 由$n \times m$個數$a_{ij}$排成的$n$行$m$列的數表稱為$n$行$m$列的矩陣,簡稱$n \times m$矩陣。 $$A =\begin{bmatrix}a_{11} & a_{12} & \dots a_{1m} \\ a ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...