前言
作為一只小白,剛進入Python爬蟲領域,今天嘗試一下爬取鏈家的二手房,之前已經爬取了房天下的了,看看鏈家有什么不同,馬上開始。
一、分析觀察爬取網站結構
這里以廣州鏈家二手房為例:http://gz.lianjia.com/ershoufang/
這是第一頁,我們看看第二頁的url會有什么變化發現多出來一個/g2,第三頁/pg3,那么原始的是不是就是增加/pg1呢,我們測試一下http://gz.lianjia.com/ershoufang/pg1/ == http://gz.lianjia.com/ershoufang/那么問題不大,我們繼續分析。
這些就是我們想得到的二手房資訊,但是這個是有鏈接可以點進去的,我們看看:
里面的二手房資訊更加全面,那我是想得到這個網頁里面的資訊了。
二、編寫爬蟲
1.得到url
我們先可以得到全部詳細的鏈接,這里有100頁,那么我們可以http://gz.lianjia.com/ershoufang/pg1/.../pg2.../pg3.../pg100 先生成全部url,再從這些url得到每一頁里面詳細的url,再從詳細的url分析html得到我想要的資訊。
2.分析 htmlhttp://gz.lianjia.com/ershoufang/pg1/
先打開chrom自帶的開發者工具分析里面的network,把preserve log
勾上,清空
,然后我們刷新一下網頁。
發現get:http://gz.lianjia.com/ershoufang/pg1/請求到的html
那么我們就可以開始生成全部url先了:
def generate_allurl(user_in_nub): url = 'http://gz.lianjia.com/ershoufang/pg{}/' for url_next in range(1,int(user_in_nub)): yield url.format(url_next) def main(): user_in_nub = input('輸入生成頁數:') for i in generate_allurl(user_in_nub): print(i) if __name__ == '__main__': main()
運行結果:
這樣我們就生成了100頁的url
然后我們就要分析這些url里面的詳細每一頁的url:
先分析網頁結構,
發現我們要的url是再class為title里面的a標簽,我們可以使用request來獲取html,用正則表達法來分析獲取詳情頁url:
import requests
import re
def一個方法,把得到的generate_allurl傳進來再打印一下看看
def get_allurl(generate_allurl): get_url = requests.get(generate_allurl,) if get_url.status_code == 200: re_set = re.compile('<li.*?class="clear">.*?<a.*?class="img.*?".*?href="(.*?)"') re_get = re.findall(re_set,get_url.text) print(re_get)
正常獲取詳細頁的鏈接
下一步我們就要分析這些詳細頁連接以獲取里面的資訊,使用自帶開發者工具點擊這個箭頭可以選擇網頁元素:
發現資訊在一個class為main里面,可以用BeautifulSoup模塊里面的方法得到:
from bs4 import BeautifulSoup
定義一個方法來把詳情url鏈接傳進來分析:
def open_url(re_get): res = requests.get(re_get) if res.status_code == 200: info = {} soup = BeautifulSoup(res.text,'lxml') info['標題'] = soup.select('.main')[0].text info['總價'] = soup.select('.total')[0].text + '萬' info['每平方售價'] = soup.select('.unitPriceValue')[0].text return info
這里把requests.get對象傳給res,然后把這個變量傳給BeautifulSoup,用lxml解析器解析,再把結果傳給soup,然后就可以soup.select方法來篩選,因為上面標題在,main下:
soup.select('.main'),因為這里是一個class,所以前面要加.,如果篩選的是id,則加#。
得到如下結果:
是一個list,所以我們要加[ 0 ]取出,然后可以運用方法 .text得到文本。
def open_url(re_get):
res = requests.get(re_get)
if res.status_code == 200:
soup = BeautifulSoup(res.text,'lxml')
title = soup.select('.main')[0].text
print(title)
得到結果
然后還可以添加到字典,return返回字典:
def open_url(re_get): res = requests.get(re_get) if res.status_code == 200: info = {} soup = BeautifulSoup(res.text,'lxml') info['標題'] = soup.select('.main')[0].text info['總價'] = soup.select('.total')[0].text + '萬' info['每平方售價'] = soup.select('.unitPriceValue')[0].text return info
得到結果:
還可以儲存到xlsx文檔里面:
def pandas_to_xlsx(info): pd_look = pd.DataFrame(info) pd_look.to_excel('鏈家二手房.xlsx',sheet_name='鏈家二手房')
ok基本完成,可能有沒有說清楚的,留言我繼續更新
1 #!/usr/bin/env python3 2 # -*- coding: utf-8 -*- 3 # Author;Tsukasa 4 5 import json 6 from multiprocessing import Pool 7 import requests 8 from bs4 import BeautifulSoup 9 import re 10 import pandas as pd 11 import pymongo 12 13 14 def generate_allurl(user_in_nub, user_in_city): # 生成url 15 url = 'http://' + user_in_city + '.lianjia.com/ershoufang/pg{}/' 16 for url_next in range(1, int(user_in_nub)): 17 yield url.format(url_next) 18 19 20 def get_allurl(generate_allurl): # 分析url解析出每一頁的詳細url 21 get_url = requests.get(generate_allurl, 'lxml') 22 if get_url.status_code == 200: 23 re_set = re.compile('<li.*?class="clear">.*?<a.*?class="img.*?".*?href="(.*?)"') 24 re_get = re.findall(re_set, get_url.text) 25 return re_get 26 27 28 def open_url(re_get): # 分析詳細url獲取所需信息 29 res = requests.get(re_get) 30 if res.status_code == 200: 31 info = {} 32 soup = BeautifulSoup(res.text, 'lxml') 33 info['標題'] = soup.select('.main')[0].text 34 info['總價'] = soup.select('.total')[0].text + '萬' 35 info['每平方售價'] = soup.select('.unitPriceValue')[0].text 36 info['參考總價'] = soup.select('.taxtext')[0].text 37 info['建造時間'] = soup.select('.subInfo')[2].text 38 info['小區名稱'] = soup.select('.info')[0].text 39 info['所在區域'] = soup.select('.info a')[0].text + ':' + soup.select('.info a')[1].text 40 info['鏈家編號'] = str(re_get)[33:].rsplit('.html')[0] 41 for i in soup.select('.base li'): 42 i = str(i) 43 if '</span>' in i or len(i) > 0: 44 key, value = (i.split('</span>')) 45 info[key[24:]] = value.rsplit('</li>')[0] 46 for i in soup.select('.transaction li'): 47 i = str(i) 48 if '</span>' in i and len(i) > 0 and '抵押信息' not in i: 49 key, value = (i.split('</span>')) 50 info[key[24:]] = value.rsplit('</li>')[0] 51 print(info) 52 return info 53 54 55 def update_to_MongoDB(one_page): # update儲存到MongoDB 56 if db[Mongo_TABLE].update({'鏈家編號': one_page['鏈家編號']}, {'$set': one_page}, True): #去重復 57 print('儲存MongoDB 成功!') 58 return True 59 return False 60 61 62 def pandas_to_xlsx(info): # 儲存到xlsx 63 pd_look = pd.DataFrame(info) 64 pd_look.to_excel('鏈家二手房.xlsx', sheet_name='鏈家二手房') 65 66 67 def writer_to_text(list): # 儲存到text 68 with open('鏈家二手房.text', 'a', encoding='utf-8')as f: 69 f.write(json.dumps(list, ensure_ascii=False) + '\n') 70 f.close() 71 72 73 def main(url): 74 75 writer_to_text(open_url(url)) #儲存到text文件 76 # update_to_MongoDB(list) #儲存到Mongodb 77 78 79 if __name__ == '__main__': 80 user_in_city = input('輸入爬取城市:') 81 user_in_nub = input('輸入爬取頁數:') 82 83 Mongo_Url = 'localhost' 84 Mongo_DB = 'Lianjia' 85 Mongo_TABLE = 'Lianjia' + '\n' + str('zs') 86 client = pymongo.MongoClient(Mongo_Url) 87 db = client[Mongo_DB] 88 pool = Pool() 89 for i in generate_allurl('2', 'zs'): 90 pool.map(main, [url for url in get_allurl(i)])
源碼地址:https://gist.github.com/Tsukasa007/660fce644b7dd33afc57998fdc6c376a