利用requestes\pyquery\BeautifulSoup爬取某租房公寓(深圳市)4755條租房資訊及總結

不遷徙候鳥發表於2020-11-22

為了分析深圳市所有長租、短租公寓的資訊,爬取了某租房公寓深圳區域所有在租公寓資訊,以下記錄了爬取過程以及爬取過程中遇到的問題:

爬取程式碼:

 1 import requests
 2 from requests.exceptions import RequestException
 3 from pyquery import PyQuery as pq
 4 from bs4 import BeautifulSoup
 5 import pymongo
 6 from config import *
 7 from multiprocessing import Pool
 8 
 9 client = pymongo.MongoClient(MONGO_URL)    # 申明連線物件
10 db = client[MONGO_DB]    # 申明資料庫
11 
12 def get_one_page_html(url):    # 獲取網站每一頁的html
13     headers = {
14         "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
15                       "Chrome/85.0.4183.121 Safari/537.36"
16     }
17     try:
18         response = requests.get(url, headers=headers)
19         if response.status_code == 200:
20             return response.text
21         else:
22             return None
23     except RequestException:
24         return None
25 
26 
27 def get_room_url(html):    # 獲取當前頁面上所有room_info的url
28     doc = pq(html)
29     room_urls = doc('.r_lbx .r_lbx_cen .r_lbx_cena a').items()
30     return room_urls
31 
32 
33 def parser_room_page(room_html):
34     soup = BeautifulSoup(room_html, 'lxml')
35     title = soup.h1.text
36     price = soup.find('div', {'class': 'room-price-sale'}).text[:-3]
37     x = soup.find_all('div', {'class': 'room-list'})
38     area = x[0].text[7:-11]    # 面積
39     bianhao = x[1].text[4:]
40     house_type = x[2].text.strip()[3:7]    # 戶型
41     floor = x[5].text[4:-2]    # 樓層
42     location1 = x[6].find_all('a')[0].text    # 分割槽
43     location2 = x[6].find_all('a')[1].text
44     location3 = x[6].find_all('a')[2].text
45     subway = x[7].text[4:]
46     addition = soup.find_all('div', {'class': 'room-title'})[0].text
47     yield {
48         'title': title,
49         'price': price,
50         'area': area,
51         'bianhao': bianhao,
52         'house_type': house_type,
53         'floor': floor,
54         'location1': location1,
55         'location2': location2,
56         'location3': location3,
57         'subway': subway,
58         'addition': addition
59     }
60 
61 
62 def save_to_mongo(result):
63     if db[MONGO_TABLE].insert_one(result):
64         print('儲存到mongodb成功', result)
65         return True
66     return False
67 
68 
69 def main(page):
70     url = 'http://www.xxxxx.com/room/sz?page=' + str(page)    # url就不粘啦,嘻嘻
71     html = get_one_page_html(url)
72     room_urls = get_room_url(html)
73     for room_url in room_urls:
74         room_url_href = room_url.attr('href')
75         room_html = get_one_page_html(room_url_href)
76         if room_html is None:    # 非常重要,否則room_html為None時會報錯
77             pass
78         else:
79             results = parser_room_page(room_html)
80             for result in results:
81                 save_to_mongo(result)
82 
83 if __name__ == '__main__':
84     pool = Pool()  # 使用多程式提高爬取效率
85     pool.map(main, [i for i in range(1, 258)])

在寫爬取程式碼過程中遇到了兩個問題:

(一)在get_room_url(html)函式中,開始是想直接return每個租房資訊的room_url,但是return不同於print,函式執行到return時就會結束該函式,這樣就只能返回每頁第一個租房room_url。解決辦法是:return 包含每頁所有room_url的generator生成器,在main函式中用for迴圈遍歷,再從每個room_url中獲取href,傳入到get_one_page_html(room_url_href)中進行解析。

(二)沒有寫第76行的if語句,我預設get_one_page_html(room_url_href)返回的room_html不為空,因此出現multiprocessing.pool.RemoteTraceback報錯:

 

 上圖中顯示markup為None情況下報錯,點選藍色"F:\ProgramFiles\anaconda3\lib\site-packages\bs4\__init__.py"發現markup為room_html,即部分room_html出現None情況。要解決這個問題,必須讓程式碼跳過room_html is None的情況,因此新增 if 語句解決了這個問題。

最終成功爬取某租房公寓深圳市258頁共4755條租房資訊,為下一步進行資料分析做準備。

 

 其中單條資訊:

 

相關文章