摘要:美空網(wǎng)數(shù)據(jù)簡介從今天開始,我們嘗試用篇博客的內(nèi)容量,搞定一個網(wǎng)站叫做美空網(wǎng)網(wǎng)址為,這個網(wǎng)站我分析了一下,我們要爬取的圖片在下面這個網(wǎng)址然后在去分析一下,我需要找到一個圖片列表頁面是最好的,作為一個勤勞的爬蟲,我找到了這個頁面列表頁面被我找
1.美空網(wǎng)數(shù)據(jù)-簡介
從今天開始,我們嘗試用2篇博客的內(nèi)容量,搞定一個網(wǎng)站叫做“美空網(wǎng)”網(wǎng)址為:http://www.moko.cc/, 這個網(wǎng)站我分析了一下,我們要爬取的圖片在 下面這個網(wǎng)址
http://www.moko.cc/post/13020...
然后在去分析一下,我需要找到一個圖片列表頁面是最好的,作為一個勤勞的爬蟲coder,我找到了這個頁面
http://www.moko.cc/post/da39d...
列表頁面被我找到了,貌似沒有分頁,這就簡單多了,但是剛想要爬,就翻車了,我發(fā)現(xiàn)一個嚴(yán)重的問題。
http://www.moko.cc/post/==da3...
我要做的是一個自動化的爬蟲,但是我發(fā)現(xiàn),出問題了,上面那個黃色背景的位置是啥?
ID,昵稱,個性首頁,這個必須要搞定。
我接下來隨機的找了一些圖片列表頁,試圖找到規(guī)律到底是啥?
http://www.moko.cc/post/978c7...
http://www.moko.cc/post/junda...
http://www.moko.cc/post/slavi...
......
沒什么問題,發(fā)現(xiàn)規(guī)律了
http://www.moko.cc/post/==個...
這就有點意思了,我要是能找到盡量多的昵稱,不就能拼接出來我想要得所有地址了嗎
開干?。?!
手段,全站亂點,找入口,找切入點,找是否有API
.... .... 結(jié)果沒找著
下面的一些備選方案
趴這個頁面,發(fā)現(xiàn)只有 20頁 http://www.moko.cc/channels/p...
每頁48個模特,20頁。那么也才960人啊,完全覆蓋不到盡可能多的用戶。
接著又找到
http://www.moko.cc/catalog/in... 這個頁面
確認了一下眼神,以為發(fā)現(xiàn)問題了,結(jié)果
哎呀,還么有權(quán)限,誰有權(quán)限,可以跟我交流一下,一時激動,差點去下載他們的APP,然后進行抓包去。
上面兩條路,都不好弄,接下來繼續(xù)找路子。
無意中,我看到了一絲曙光
關(guān)注名單,點進去
哈哈哈,OK了,這不就是,我要找到的東西嗎?
不多說了,爬蟲走起,測試一下他是否有反扒機制。
我找到了一個關(guān)注的人比較多的頁面,1500多個人
http://www.moko.cc/subscribe/...
然后又是一波分析操作
2.美空網(wǎng)數(shù)據(jù)- 爬蟲數(shù)據(jù)存儲確定了爬蟲的目標(biāo),接下來,我做了兩件事情,看一下,是否對你也有幫助
確定數(shù)據(jù)存儲在哪里?最后我選擇了MongoDB
用正則表達式去分析網(wǎng)頁數(shù)據(jù)
對此,我們需要安裝一下MongoDB,安裝的辦法肯定是官網(wǎng)教程啦!
https://docs.mongodb.com/mast...
如果官方文檔沒有幫助你安裝成功。
那么我推薦下面這篇博客
https://www.cnblogs.com/hacky...
安裝MongoDB出現(xiàn)如下結(jié)果
恭喜你安裝成功了。
接下來,你要學(xué)習(xí)的是 關(guān)于mongodb用戶權(quán)限的管理
http://www.cnblogs.com/shiyiw...
mongodb索引的創(chuàng)建
https://blog.csdn.net/salmone...
別問為啥我不重新寫一遍,懶唄~~~ 況且這些資料太多了,互聯(lián)網(wǎng)大把大把的。
一些我經(jīng)常用的mongdb的命令
鏈接 mongo --port <端口號> 選擇數(shù)據(jù)庫 use admin 展示當(dāng)前數(shù)據(jù)庫 db 當(dāng)前數(shù)據(jù)庫授權(quán) db.auth("用戶名","密碼") 查看數(shù)據(jù)庫 show dbs 查看數(shù)據(jù)庫中的列名 show collections 創(chuàng)建列 db.createCollection("列名") 創(chuàng)建索引 db.col.ensureIndex({"列名字":1},{"unique":true}) 展示所有索引 db.col.getIndexes() 刪除索引 db.col.dropIndex("索引名字") 查找數(shù)據(jù) db.列名.find() 查詢數(shù)據(jù)總條數(shù) db.列名.find().count()
上面基本是我最常用的了,我們下面實際操作一把。
用Python鏈接MongoDB使用 pip3 安裝pymongo庫
使用pymongo模塊連接mongoDB數(shù)據(jù)庫
一些準(zhǔn)備工作
創(chuàng)建dm數(shù)據(jù)庫
鏈接上mongodb 在終端使用命令 mongo --port 21111
[linuxboy@localhost ~]$ mongo --port 21111 MongoDB shell version v3.6.5 connecting to: mongodb://127.0.0.1:21111/ MongoDB server version: 3.6.5 >
配置用戶權(quán)限:接著上面輸入命令 show dbs 查看權(quán)限
權(quán)限不足
創(chuàng)建管理用戶
db.createUser({user: "userAdmin",pwd: "123456", roles: [ { role: "userAdminAnyDatabase", db: "admin" } ] } )
授權(quán)用戶
db.auth("userAdmin","123456")
查看權(quán)限
> db.auth("userAdmin","123456") 1 > show dbs admin 0.000GB config 0.000GB local 0.000GB moko 0.013GB test 0.000GB >
接下來創(chuàng)建 dm數(shù)據(jù)庫<在這之前還需要創(chuàng)建一個讀寫用戶>
> use dm switched to db dm > db dm > db.createUser({user: "dba",pwd: "dba", roles: [ { role: "readWrite", db: "dm" } ] } ) Successfully added user: { "user" : "dba", "roles" : [ { "role" : "readWrite", "db" : "dm" } ] } >
重新授權(quán)
db.auth("dba","dba")
創(chuàng)建一列數(shù)據(jù)
> db.createCollection("demo") { "ok" : 1 } > db.collections dm.collections > show collections demo >
Python實現(xiàn)插入操作
import pymongo as pm #確保你已經(jīng)安裝過pymongo了 # 獲取連接 client = pm.MongoClient("localhost", 21111) # 端口號是數(shù)值型 # 連接目標(biāo)數(shù)據(jù)庫 db = client.dm # 數(shù)據(jù)庫用戶驗證 db.authenticate("dba", "dba") post = { "id": "111111", "level": "MVP", "real":1, "profile": "111", "thumb":"2222", "nikename":"222", "follows":20 } db.col.insert_one(post) # 插入單個文檔 # 打印集合第1條記錄 print (db.col.find_one())
編譯執(zhí)行
[linuxboy@bogon moocspider]$ python3 mongo.py {"_id": ObjectId("5b15033cc3666e1e28ae5582"), "id": "111111", "level": "MVP", "real": 1, "profile": "111", "thumb": "2222", "nikename": "222", "follows": 20} [linuxboy@bogon moocspider]$
好了,我們到現(xiàn)在為止,實現(xiàn)了mongodb的插入問題。
3.美空網(wǎng)數(shù)據(jù)-用Python 爬取關(guān)注對象首先,我需要創(chuàng)造一個不斷抓取鏈接的類
這個類做的事情,就是分析
http://www.moko.cc/subscribe/...
這個頁面,總共有多少頁,然后生成鏈接
抓取頁面中的總頁數(shù)為77
正則表達式如下
onfocus="this.blur()">(d*?)<
在這里,由所有的分頁都一樣,所以,我匹配了全部的頁碼,然后計算了數(shù)組中的最大值
#獲取頁碼數(shù)組 pages = re.findall(r"onfocus="this.blur()">(d*?)<",content,re.S) #獲取總頁數(shù) page_size = 1 if pages: #如果數(shù)組不為空 page_size = int(max(pages)) #獲取最大頁數(shù)
接下來就是我們要搞定的生產(chǎn)者編碼階段了,我們需要打造一個不斷獲取連接的爬蟲
簡單的說就是
我們需要一個爬蟲,不斷的去爬取
http://www.moko.cc/subscribe/... 這個頁面中所有的用戶,并且還要爬取到總頁數(shù)。
比如查看上述頁面中,我們要獲取的關(guān)鍵點如下
通過這個頁面,我們要得到,這樣子的一個數(shù)組,注意下面數(shù)組中有個位置【我用爬蟲爬到的】這個就是關(guān)鍵的地方了
all_urls = [ "http://www.moko.cc/subscribe/chenhaoalex/1.html", "http://www.moko.cc/subscribe/chenhaoalex/2.html", "http://www.moko.cc/subscribe/chenhaoalex/3.html", "http://www.moko.cc/subscribe/chenhaoalex/4.html", ...... "http://www.moko.cc/subscribe/dde760d5dd6a4413aacb91d1b1d76721/1.html" "http://www.moko.cc/subscribe/3cc82db2231a4449aaa97ed8016b917a/1.html" "http://www.moko.cc/subscribe/d45c1e3069c24152abdc41c1fb342b8f/1.html" "http://www.moko.cc/subscribe/【我用爬蟲爬到的】/1.html" ]
引入必備模塊
# -*- coding: UTF-8 -*- import requests #網(wǎng)絡(luò)請求模塊 import random #隨機模塊 import re #正則表達式模塊 import time #時間模塊 import threading #線程模塊 import pymongo as pm #mongodb模塊
接下來,我們需要準(zhǔn)備一個通用函數(shù)模擬UserAgent做一個簡單的反爬處理
class Config(): def getHeaders(self): user_agent_list = [ "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1" "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5", "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24" ] UserAgent=random.choice(user_agent_list) headers = {"User-Agent": UserAgent} return headers
編寫生產(chǎn)者的類和核心代碼,Producer繼承threading.Thread
#生產(chǎn)者 class Producer(threading.Thread): def run(self): print("線程啟動...") headers = Config().getHeaders() if __name__ == "__main__": p = Producer() p.start()
測試運行,一下,看是否可以啟動
[linuxboy@bogon moocspider]$ python3 demo.py 線程啟動... {"User-Agent": "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"} [linuxboy@bogon moocspider]$
如果上面的代碼沒有問題,接下來就是我們爬蟲代碼部分了,為了方便多線程之間的調(diào)用,我們還是創(chuàng)建一個共享變量在N個線程之間調(diào)用
# -*- coding: UTF-8 -*- import requests import random import re import time import threading import pymongo as pm # 獲取連接 client = pm.MongoClient("localhost", 21111) # 端口號是數(shù)值型 # 連接目標(biāo)數(shù)據(jù)庫 db = client.moko # 數(shù)據(jù)庫用戶驗證 db.authenticate("moko", "moko") urls = ["http://www.moko.cc/subscribe/chenhaoalex/1.html"] index = 0 #索引 g_lock = threading.Lock() #初始化一個鎖 #生產(chǎn)者 class Producer(threading.Thread): def run(self): print("線程啟動...") headers = Config().getHeaders() print(headers) global urls global index while True: g_lock.acquire() if len(urls)==0: g_lock.release() continue page_url = urls.pop() g_lock.release() #使用完成之后及時把鎖給釋放,方便其他線程使用 response = "" try: response = requests.get(page_url,headers=headers,timeout=5) except Exception as http: print("生產(chǎn)者異常") print(http) continue content = response.text rc = re.compile(r"") follows = rc.findall(content) print(follows) fo_url = [] threading_links_2 = [] for u in follows: this_url = "http://www.moko.cc/subscribe/%s/1.html" % u g_lock.acquire() index += 1 g_lock.release() fo_url.append({"index":index,"link":this_url}) threading_links_2.append(this_url) g_lock.acquire() urls += threading_links_2 g_lock.release() print(fo_url) try: db.text.insert_many(fo_url,ordered=False ) except: continue if __name__ == "__main__": p = Producer() p.start()
上面代碼除了基本操作以外,我做了一些細小的處理
現(xiàn)在說明如下
fo_url.append({"index":index,"link":this_url})
這部分代碼,是為了消費者使用時候,方便進行查找并且刪除操作而特意改造的,增加了一個字段index作為標(biāo)識
第二個部分,插入數(shù)據(jù)的時候,我進行了批量的操作使用的是insert_many函數(shù),并且關(guān)鍵的地方,我增加了一個ordered=False的操作,這個地方大家可以自行研究一下,我的目的是去掉重復(fù)數(shù)據(jù),默認情況下insert_many函數(shù)如果碰到數(shù)據(jù)重復(fù),并且在mongodb中創(chuàng)建了索引==創(chuàng)建索引的辦法,大家自行翻閱文章上面==,那么是無法插入的,但是這樣子會插入一部分,只把重復(fù)的地方略過,非常方便。
關(guān)于pymongo的使用,大家可以參考官網(wǎng)手冊
這個是 pymongo的官方教程
http://api.mongodb.com/python...
MongoDB的手冊大家也可以參考
https://docs.mongodb.com/manu...
db.text.insert_many(fo_url,ordered=False )
我們鏈接上MongoDB數(shù)據(jù)庫,查詢一下我們剛剛插入的數(shù)據(jù)
> show collections col links text > db.text moko.text > db.text.find() { "_id" : ObjectId("5b1789e0c3666e642364a70b"), "index" : 1, "link" : "http://www.moko.cc/subscribe/dde760d5dd6a4413aacb91d1b1d76721/1.html" } { "_id" : ObjectId("5b1789e0c3666e642364a70c"), "index" : 2, "link" : "http://www.moko.cc/subscribe/3cc82db2231a4449aaa97ed8016b917a/1.html" } ....... { "_id" : ObjectId("5b1789e0c3666e642364a71e"), "index" : 20, "link" : "http://www.moko.cc/subscribe/8c1e4c738e654aad85903572f9090adb/1.html" } Type "it" for more
其實上面代碼,有一個非常嚴(yán)重的BUG,就是當(dāng)我們實際操作的時候,發(fā)現(xiàn),我們每次獲取到的都是我們使用this_url = "http://www.moko.cc/subscribe/%s/1.html" % u 進行拼接的結(jié)果。
也就是說,我們獲取到的永遠都是第1頁。這個按照我們之前設(shè)計的就不符合邏輯了,
我們還要獲取到分頁的內(nèi)容,那么這個地方需要做一個簡單的判斷,就是下面的邏輯了。
==如果完整代碼,大家不知道如何觀看,可以直接翻閱到文章底部,有對應(yīng)的github鏈接==
#如果是第一頁,那么需要判斷一下 #print(page_url) is_home =re.search(r"(d*?).html",page_url).group(1) if is_home == str(1): pages = re.findall(r"onfocus="this.blur()">(d*?)<",content,re.S) #獲取總頁數(shù) page_size = 1 if pages: page_size = int(max(pages)) #獲取最大頁數(shù) if page_size > 1: #如果最大頁數(shù)大于1,那么獲取所有的頁面 url_arr = [] threading_links_1 = [] for page in range(2,page_size+1): url = re.sub(r"(d*?).html",str(page)+".html",page_url) threading_links_1.append(url) g_lock.acquire() index += 1 g_lock.release() url_arr.append({ "index":index, "link": url}) g_lock.acquire() urls += threading_links_1 # URL數(shù)據(jù)添加 g_lock.release() try: db.text.insert_many(url_arr,ordered=False ) except Exception as e: print("數(shù)據(jù)庫輸入異常") print (e) continue else: pass else: pass
截止到現(xiàn)在為止,其實你已經(jīng)實現(xiàn)了鏈接的生產(chǎn)者了 。
我們在MongoDB中生成了一堆鏈接,接下來就是使用階段了。
使用起來也是非常簡單。
我先給大家看一個比較復(fù)雜的正則表達式爬蟲寫的好不好,正則表達式站很重要的比例哦~
divEditOperate_(?Pd*)["] .*>[sS]*? .*?(?P<級別>w*P).*(?P<是否認證>
[sS]*?
)?.*?相關(guān)文章
Python爬蟲入門教程 3-100 美空網(wǎng)數(shù)據(jù)爬取
摘要:美空網(wǎng)數(shù)據(jù)簡介從今天開始,我們嘗試用篇博客的內(nèi)容量,搞定一個網(wǎng)站叫做美空網(wǎng)網(wǎng)址為,這個網(wǎng)站我分析了一下,我們要爬取的圖片在下面這個網(wǎng)址然后在去分析一下,我需要找到一個圖片列表頁面是最好的,作為一個勤勞的爬蟲,我找到了這個頁面列表頁面被我找 1.美空網(wǎng)數(shù)據(jù)-簡介 從今天開始,我們嘗試用2篇博客的內(nèi)容量,搞定一個網(wǎng)站叫做美空網(wǎng)網(wǎng)址為:http://www.moko.cc/, 這個網(wǎng)站我...
Python爬蟲入門教程 3-100 美空網(wǎng)數(shù)據(jù)爬取
摘要:美空網(wǎng)數(shù)據(jù)簡介從今天開始,我們嘗試用篇博客的內(nèi)容量,搞定一個網(wǎng)站叫做美空網(wǎng)網(wǎng)址為,這個網(wǎng)站我分析了一下,我們要爬取的圖片在下面這個網(wǎng)址然后在去分析一下,我需要找到一個圖片列表頁面是最好的,作為一個勤勞的爬蟲,我找到了這個頁面列表頁面被我找 1.美空網(wǎng)數(shù)據(jù)-簡介 從今天開始,我們嘗試用2篇博客的內(nèi)容量,搞定一個網(wǎng)站叫做美空網(wǎng)網(wǎng)址為:http://www.moko.cc/, 這個網(wǎng)站我...
Python爬蟲入門教程 4-100 美空網(wǎng)未登錄圖片爬取
摘要:爬蟲分析首先,我們已經(jīng)爬取到了多的用戶個人主頁,我通過鏈接拼接獲取到了在這個頁面中,咱們要找?guī)讉€核心的關(guān)鍵點,發(fā)現(xiàn)平面拍攝點擊進入的是圖片列表頁面。 簡介 上一篇寫的時間有點長了,接下來繼續(xù)把美空網(wǎng)的爬蟲寫完,這套教程中編寫的爬蟲在實際的工作中可能并不能給你增加多少有價值的技術(shù)點,因為它只是一套入門的教程,老鳥你自動繞過就可以了,或者帶帶我也行。 爬蟲分析 首先,我們已經(jīng)爬取到了N多的...
發(fā)表評論
0條評論
閱讀 2744·2023-04-25 14:21
閱讀 1181·2021-11-23 09:51
閱讀 4026·2021-09-22 15:43
閱讀 614·2019-08-30 15:55
閱讀 1565·2019-08-29 11:28
閱讀 2451·2019-08-26 11:44
閱讀 1688·2019-08-23 18:15
閱讀 2886·2019-08-23 16:42