從零開始學爬蟲(3):通過MongoDB資料庫獲取爬蟲資料
這是我學習爬蟲的筆記,作為備忘,如果可以幫到大家,那就更好了~
從零開始學爬蟲(1):爬取房天下二手房資訊
從零開始學爬蟲(2):突破限制,分類爬取,獲得全部資料
從零開始學爬蟲(3):通過MongoDB資料庫獲取爬蟲資料
一、MongoDB資料庫是什麼
MongoDB是一個基於分散式檔案儲存的資料庫。他支援的資料結構非常鬆散,是類似json的bson格式,因此可以儲存比較複雜的資料型別。Mongo最大的特點是他支援的查詢語言非常強大,其語法有點類似於物件導向的查詢語言,幾乎可以實現類似關聯式資料庫單表查詢的絕大部分功能,而且還支援對資料建立索引。
一個MongoDB 例項可以包含一組資料庫,一個DataBase 可以包含一組Collection(集合),一個集合可以包含一組Document(文件)。一個Document包含一組field(欄位),每一個欄位都是一個key/value pair。
以上是百度百科的介紹,那麼所謂的bson格式是什麼東西呢?文件是什麼樣的?集合又是什麼呢?下圖是我在mongodb視覺化管理工具上Robomongo截的圖:
好了,那我們可以看到一個集合裡面有很多個文件,這類似於一個關係型資料庫一個表裡面有多條記錄。
二、MongoDB安裝與配置
安裝MongoDB資料庫
MongoDB資料庫安裝的詳細過程參見 Windows下安裝MongoDB
安裝MongoDB資料庫視覺化管理工具Robomongo:直接去官網下載安裝即可,下載地址:https://robomongo.org/download
安裝Pymongo
以管理員身份開啟命令列提示符,執行pip3 install pymongo,即可完成安裝。
至此MongoDB資料庫的安裝與配置就已經完成了。
三、如何通過pymongo操作MongoDB
1、連線資料庫
第一步,通過pymongo建立資料庫連線,並且連線一個名為test的資料庫(如果test不存在,這一步就是新建一個test資料庫)
from pymongo import MongoClient
# 建立 MongoDB 資料庫連線
conn = MongoClient('localhost', 27017)
# 新建一個test資料庫
db = conn.test
2、資料庫操作
假設向test資料庫中的test集合中插入文件data(data = {"name": "xyl", "age": 25}),只需要一條語句db.test.insert_one(data)就行了;多個文件的插入用db.test.insert_many(data)。
db = conn.test
# 插入一條記錄
data = {"name": "xyl", "age": 25}
db.test.insert_one(data)
# 插入多條記錄
data = [{"name": "xyl", "age": 25}, {"name": "yxl", "age": 27}]
db.test.insert_many(data)
# 遍歷coll = db.test.find()查詢到的所有結果,以及它key=name的value
coll = db.test.find()
for i in col1:
print(i)
print(i["name"])
OK,其實MongoDB也是一個資料庫,也是可以通過一些語句對其中的資料進行各種操作,這裡我們先不深究,有興趣的可以看一下官方文件。現在,我們來把上一篇文章最後的問題解決一下。
3、二手房資訊儲存與匯出
基於pymongo的常用操作,我們來改寫一下上篇文章中的程式碼(以下是修改後的資料儲存的程式碼)
# -*- coding: utf-8 -*-
from pymongo import MongoClient
from bs4 import BeautifulSoup
import requests
import time
# 建立 MongoDB 資料庫連線
conn = MongoClient('localhost', 27017)
# 新建一個test資料庫
db = conn.test
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36',
'Cookie': 'global_cookie=gpe9gqaciutsnx2zke6bsyizp29iypii6li; polling_imei=231c34cb02f4f783; SoufunSessionID_Esf=3_1486111884_10590; SKHRecordsXIAN=%25e5%258d%258e%25e8%25bf%259c%25e6%25b5%25b7%25e8%2593%259d%25e5%259f%258e%257c%255e2017%252f2%252f13%2b16%253a13%253a18%257c%255e3610937652%257c%2523%25e6%259d%258e%25e5%25ae%25b6%25e6%259d%2591%25e4%25b8%2587%25e8%25be%25be%25e5%25b9%25bf%25e5%259c%25ba%25e9%259b%2581%25e5%25a1%2594%25e8%25b7%25af%25e6%2596%2587%25e8%2589%25ba%25e8%25b7%25af%25e5%258f%258b%25e8%25b0%258a%25e8%25b7%25af%25e9%2593%2581%25e4%25b8%2580%25e4%25b8%25ad215%25e5%25b9%25b3%25e5%2586%2599%25e5%25ad%2597%25e9%2597%25b4%257c%255e2017%252f2%252f16%2b21%253a41%253a27%257c%255e0; logGuid=1d724a5a-3c98-4e52-8e84-924a7ca9a1ac; __utmt_t0=1; __utmt_t1=1; __utmt_t2=1; city=xian; __utma=147393320.1839238857.1486108289.1487256095.1487298760.22; __utmb=147393320.87.10.1487298760; __utmc=147393320; __utmz=147393320.1486191809.5.3.utmcsr=esf.xian.fang.com|utmccn=(referral)|utmcmd=referral|utmcct=/; unique_cookie=U_6qx5dbebzr1btgohc0anj3f2p16iz97a455*29'
}
def spider_1(url):
response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, 'lxml')
titles = soup.select('dd > p.title > a') # 標題
hrefs = soup.select('dd > p.title > a') # 連結
details = soup.select('dd > p.mt12') # 建築資訊
courts = soup.select('dd > p:nth-of-type(3) > a') # 小區
adds = soup.select('dd > p:nth-of-type(3) > span') # 地址
areas = soup.select('dd > div.area.alignR > p:nth-of-type(1)') # 面積
prices = soup.select('dd > div.moreInfo > p:nth-of-type(1) > span.price') # 總價
danjias = soup.select('dd > div.moreInfo > p.danjia.alignR.mt5') # 單價
authors = soup.select('dd > p.gray6.mt10 > a') # 釋出者
trains = soup.select('dd > div.mt8.clearfix > div.pt4.floatl > span.train.note') # 地鐵房
for title, href, detail, court, add, area, price, danjia, author, train in zip(titles, hrefs, details, courts, adds, areas, prices, danjias, authors, trains):
data = {
'title': title.get_text(),
'href': 'http://esf.xian.fang.com' + href.get('href'),
'detail': list(detail.stripped_strings),
'court': court.get_text(),
'add': add.get_text(),
'area': area.get_text(),
'price': price.get_text(),
'danjia': danjia.get_text(),
'author': author.get_text(),
'train': train.get_text()
}
db.test.insert_one(data)
response = requests.get('http://esf.xian.fang.com/', headers=headers)
soup = BeautifulSoup(response.text, 'lxml')
regions = soup.select('#list_D02_10 > div.qxName > a') # 區域
totprices = soup.select('#list_D02_11 > p > a') # 總價
housetypes = soup.select('#list_D02_12 > a') # 戶型
areas = soup.select('#list_D02_13 > p > a') # 面積
# 對於大於等於100頁的進行細分
n = 1
while n < 8:
i = 1
while i < 7:
resp1 = requests.get('http://esf.xian.fang.com' + regions[n].get('href') + '-' + housetypes[i].get('href')[7:], headers=headers)
soup1 = BeautifulSoup(resp1.text, 'lxml')
pages = soup1.select('#list_D10_01 > span > span') # 頁數
if pages and pages[0].get_text().split('/')[1] == '100':
m = 1
while m < 10:
resp1 = requests.get('http://esf.xian.fang.com' + regions[n].get('href') + totprices[m].get('href')[7:-1] + '-' + housetypes[i].get('href')[7:], headers=headers)
soup1 = BeautifulSoup(resp1.text, 'lxml')
pages = soup1.select('#list_D10_01 > span > span') # 頁數
if pages and pages[0].get_text().split('/')[1] == '100':
j = 1
while j < 10:
resp1 = requests.get('http://esf.xian.fang.com' + regions[n].get('href') + totprices[m].get('href')[7:-1] + '-' + housetypes[i].get('href')[7:-1] + '-' + areas[j].get('href')[7:], headers=headers)
soup1 = BeautifulSoup(resp1.text, 'lxml')
pages = soup1.select('#list_D10_01 > span > span') # 頁數
if pages:
k = int(pages[0].get_text().split('/')[1])
while k > 0:
spider_1('http://esf.xian.fang.com' + regions[n].get('href') + totprices[m].get('href')[7:-1] + '-' + housetypes[i].get('href')[7:-1] + '-' + areas[j].get('href')[7:-1] + '-i3' + str(k))
k = k - 1
time.sleep(2)
else:
pass
j = j + 1
else:
if pages:
k = int(pages[0].get_text().split('/')[1])
while k > 0:
spider_1('http://esf.xian.fang.com' + regions[n].get('href') + totprices[m].get('href')[7:-1] + '-' + housetypes[i].get('href')[7:-1] + '-i3' + str(k))
k = k - 1
time.sleep(2)
else:
pass
m = m + 1
else:
if pages:
k = int(pages[0].get_text().split('/')[1])
while k > 0:
spider_1('http://esf.xian.fang.com' + regions[n].get('href') + housetypes[i].get('href')[7:-1] + '-i3' + str(k))
k = k - 1
time.sleep(2)
else:
pass
i = i + 1
n = n + 3 # 只取1/4/7
這段程式碼執行的時候我們就可以開啟Robomongo去檢視當前爬取下來的資料量,它支援三種模式的檢視:
OK,沒問題的話就讓他一直執行下去,直至把我們需要的資料全部爬下來。雖然MongoDB是一種檔案型資料庫,但它畢竟不是資料分析工具,接下來,我們需要把這些資料匯出為txt、csv、excel等檔案型別,方便後續處理。
重寫一段專門用來匯出已經儲存在test資料庫test集合中的資料如下:
# -*- coding: utf-8 -*-
from pymongo import MongoClient
# 建立 MongoDB 資料庫連線
conn = MongoClient('localhost', 27017)
# 新建一個test資料庫
db = conn.test
Myfile = open('D:\ershoufang.txt', 'w', encoding='utf-8')
coll = db.test.find()
k = 1
for i in coll:
# 把欄位名寫入檔案第一行
while k == 1:
m = 1
for j in i:
if m < 11:
Myfile.write(j + "\t")
else:
Myfile.write(j + "\n")
m = m + 1
k = k + 1
# 把欄位值寫入檔案第2到x行
n = 1
for j in i:
if n < 11:
Myfile.write(str(i[j]) + "\t")
else:
Myfile.write(str(i[j]) + "\n")
n = n + 1
注意,在windows下面,新檔案的預設編碼是gbk,這樣的話,python直譯器會用gbk編碼去解析我們的網路資料流txt,然而txt此時已經是decode過的unicode編碼,這樣的話就會導致解析不了,出現上述問題。 解決的辦法就是,改變目標檔案的編碼:Myfile = open('D:\ershoufang.txt', 'w', encoding='utf-8')中加上encoding='utf-8'。
匯出以tab分隔的txt資料:
四、後記
到現在為止,簡單的網頁資訊爬取和資料儲存基本上可以搞定了,剩下的就是資料的整理和分析。
當然,其實在爬取網頁資訊的過程中我們還遇到一些問題:同一個網頁每次爬取到的文件數不同,據瞭解,應該是因為目標網站有反爬蟲策略(ban),對方可以根據你的訪問頻率和IP判斷你是爬蟲,而不是正常的瀏覽。知乎大神介紹了3個常用的防ban的策略:
1、設定隨機漫步。訪問間隔時間可以設為一個服從正態分佈的隨機數,模擬人類瀏覽網頁的頻率。
2、設定爬蟲的工作週期。深更半夜就停止工作,早上就開始工作,儘量模擬人類的作息。
3、搭建叢集,分散式爬蟲。這樣訪問的IP會不固定,對方不容易判斷出你是爬蟲。這個開發成本就相對較高了。推薦NUTCH框架。
作者:淡泊明志
連結:https://www.zhihu.com/question/38123412/answer/75123814
來源:知乎
我們們有空再來研究研究~~~待續
相關文章
- 【從零開始學爬蟲】採集全國高校導師資料爬蟲
- 【從零開始學爬蟲】採集收視率排行資料爬蟲
- 【從零開始學爬蟲】建立模板爬蟲
- 【從零開始學爬蟲】採集全國曆史天氣資料爬蟲
- 爬蟲爬取資料如何繞開限制?爬蟲
- 【從零開始學爬蟲】採集丁香醫生新冠問答資料爬蟲
- 從零開始寫一個node爬蟲(上)—— 資料採集篇爬蟲
- Python爬蟲入門【3】:美空網資料爬取Python爬蟲
- 《從零開始學Python網路爬蟲》概要Python爬蟲
- 【從零開始學爬蟲】對任務的操作爬蟲
- Scrapy爬蟲 - 獲取知乎使用者資料爬蟲
- 爬蟲實戰:從HTTP請求獲取資料解析社群爬蟲HTTP
- 《從零開始學習Python爬蟲:頂點小說全網爬取實戰》Python爬蟲
- 從零開始的爬蟲專案(一)爬蟲
- 爬蟲可以通過代理ip收集哪些資料?爬蟲
- 爬蟲實戰——58同城租房資料爬取爬蟲
- 如何保障爬蟲高效穩定爬取資料?爬蟲
- 利用Python爬蟲爬取天氣資料Python爬蟲
- 房產資料爬取、智慧財產權資料爬取、企業工商資料爬取、抖音直播間資料python爬蟲爬取Python爬蟲
- 【從零開始學爬蟲】模板的高階選項爬蟲
- API商品資料介面呼叫實戰:爬蟲與資料獲取API爬蟲
- 從零開始寫一個node爬蟲(一)爬蟲
- 從零開始的Python爬蟲速成指南Python爬蟲
- 【0基礎學爬蟲】爬蟲基礎之資料儲存爬蟲
- 【從零開始學爬蟲】模板的複製與貼上爬蟲
- Python爬蟲精簡步驟1 獲取資料Python爬蟲
- 爬蟲:拉勾自動投遞簡歷+資料獲取爬蟲
- python爬蟲獲取天氣網實時資料Python爬蟲
- 網路爬蟲如何獲取IP進行資料抓取爬蟲
- 【Python學習】爬蟲爬蟲爬蟲爬蟲~Python爬蟲
- Python爬蟲之使用MongoDB儲存資料Python爬蟲MongoDB
- Python爬蟲框架:scrapy爬取高考派大學資料Python爬蟲框架
- 爬蟲如何爬取貓眼電影TOP榜資料爬蟲
- Golang爬蟲,Go&&正則爬取資料,槓桿的Golang爬蟲
- Python3爬蟲資料入資料庫---把爬取到的資料存到資料庫,帶資料庫去重功能Python爬蟲資料庫
- Python資料爬蟲學習筆記(11)爬取千圖網圖片資料Python爬蟲筆記
- 從零基礎開始學習Python爬蟲你需要注意的點以及如何學習爬蟲Python爬蟲
- 機器學習股票價格預測從爬蟲到預測-資料爬取部分機器學習爬蟲