Python 爬蟲 100 例專欄,即將售賣出 900 份啦,作為一個良心博主,我們把這 100 例在復盤一下吧,
爬蟲技術,是一個時效性極強的技術體系,也是技術體系中非常有名的一門雜學,因為它需要:
- 你比前端工程師略懂一點點前端知識;
- 你比后端工程師略懂一點點資料庫知識;
- 你比網路工程師略懂一點點網路協議;
- 最好你會安卓和 iOS 開發;
- 資料分析與資料挖掘要了解;
- 加密解密要懂一點點吧;
- 調度演算法要懂一點點吧;
- 為了識別驗證碼,要求會一點點機器學習不過分吧;
- 上面都會了,分布式的架構和使用,網路底層協議,網路安全攻防是不是也應該掌握呢?
- ……
如你所愿,這是爬蟲的體系,Python 爬蟲 100 例專欄,只是給你打開爬蟲世界的一扇門,給你發了一個邀請函,能進到這個世界,才能知道這個世界的美麗,
復盤爬蟲 100 例
在 100 例中采集的目標站點,隨著時間的推移,有的網站消失了,有的更新了,有的增加了反爬,有的給橡皮擦發了律師函,是時候整體復盤一下啦,
我們將通過 15~20 篇博客,將《爬蟲 100 例》整體梳理一遍,確定每一篇文章的可行性,如果網站消失,也會給大家補充一個替代網站,同時將梳理所有代碼到 CSDN 的代碼托管平臺中,
補更博客之后,《爬蟲 100 例》專欄將進行最后一次調價,即到達本專欄的終點價格 49.9 元,抓緊訂閱嘍,
更新程序中,我會將大家的評論全部都回復一遍,如果有特殊性問題,將一一進行補充,
案例一:在 CentOS 中安裝 Python 環境
這個沒啥好說的了,畢竟如果給我一次重寫的機會,我一定在 windows 中安裝,不過大家可以忽略,就當知識擴展了,畢竟后文都是在 Windows 上進行的代碼撰寫,
案例二:命運多喘的一個案例了
這個案例被下架了不下 10 次,因為涉及的網站被和諧掉了,導致現在案例 2 的名稱是 爬取 X 圖網,更難的是其它平臺也把這個 X 圖網給屏蔽了,不知道這個網站闖了多大的禍,
這個不得不更新一下啦,在原案例中,咱使用的是 CentOS 系統,更新案例就不用了,直接切換到 Windows 即可,
原案例其實是一個與漂亮女生有關的網站,那我們在保留核心技術不變的情況下,就把它換成裝修效果圖爬取吧,
目標網站切換為如下網站:https://home.fang.com/album/s24/,這美麗的裝修圖指定不會被和諧掉,

由于是復盤類文章,技術的線性學習還是要依據原文,復盤文只做對比更新(有可能會全部更新)
本網站的頁面規則如下,與原網站基本一致,
https://home.fang.com/album/s24/1/
https://home.fang.com/album/s24/2/
https://home.fang.com/album/s24/3/
第一步用生成了待抓取地址,重點邏輯查看注釋即可,
import requests
all_urls = [] # 我們拼接好的圖片集和串列路徑
class Spider():
# 建構式,初始化資料使用
def __init__(self, target_url, headers):
self.target_url = target_url
self.headers = headers
# 獲取所有的想要抓取的 URL
def getUrls(self, start_page, page_num):
global all_urls
# 回圈得到URL
for i in range(start_page, page_num+1):
url = self.target_url % i
all_urls.append(url)
if __name__ == "__main__":
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0',
'HOST': 'home.fang.com'
}
target_url = 'https://home.fang.com/album/s24/%d/' # 圖片集和串列規則
spider = Spider(target_url, headers)
# 先測驗 10 頁資料
spider.getUrls(1, 10)
print(all_urls)
第二步進行資料提取,在原案例中使用了多執行緒,還使用了生產者和觀察者模式,現在想想,好像調調一上來就起的太高了,不知道有多少同學在這里上來就翻車了,
新案例的目標網站,禁止滑鼠右鍵查看原始碼,你可以通過直接點擊 F12 喚醒開發者工具即可,
由于頁面已經修改,顧正則運算式提取邏輯需要調整,
修改 Producer 類中的正則運算式
all_pic_link = re.findall('<a href="(.*?)" title=".*?" target="_blank">',response.text,re.S)
再次修改之后的如下所示,果然有一定的學習量,重點邏輯都在注釋中進行了體現,
import requests
import threading # 多執行緒模塊
import re # 正則運算式模塊
import time # 時間模塊
# 圖片串列頁面的陣列
all_img_urls = []
# 初始化一個鎖
g_lock = threading.Lock()
# 我們拼接好的圖片集和串列路徑
all_urls = []
class Spider():
# 建構式,初始化資料使用
def __init__(self, target_url, headers):
self.target_url = target_url
self.headers = headers
# 獲取所有的想要抓取的 URL
def getUrls(self, start_page, page_num):
global all_urls
# 回圈得到URL
for i in range(start_page, page_num+1):
url = self.target_url % i
all_urls.append(url)
# 生產者,負責從每個頁面提取圖片串列鏈接
class Producer(threading.Thread):
def run(self):
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0',
'HOST': 'home.fang.com'
}
global all_urls
while len(all_urls) > 0:
# 在訪問all_urls的時候,需要使用鎖機制
g_lock.acquire()
# 通過pop方法移除最后一個元素,并且回傳該值
page_url = all_urls.pop()
# 使用完成之后及時把鎖給釋放,方便其他執行緒使用
g_lock.release()
try:
print("分析"+page_url)
response = requests.get(page_url, headers=headers, timeout=3)
# 提取詳情頁地址的正則運算式,需要重新撰寫
all_pic_link = re.findall(
'<a href="(.*?)" title=".*?" target="_blank">', response.text)
global all_img_urls
# 這里還有一個鎖
g_lock.acquire()
# 這個地方注意陣列的拼接,沒有用 append 直接用的+=也算是 python 的一個新語法
all_img_urls += all_pic_link
print(all_img_urls)
# 釋放鎖
g_lock.release()
time.sleep(0.5)
except:
pass
if __name__ == "__main__":
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0',
'HOST': 'home.fang.com'
}
target_url = 'https://home.fang.com/album/s24/%d/' # 圖片集和串列規則
spider = Spider(target_url, headers)
# 先測驗 10 頁資料
spider.getUrls(1, 10)
# print(all_urls)
for x in range(2):
t = Producer()
t.start()
接下來就是補充消費者邏輯了,這部分代碼重點也是修改了正則運算式部分,
import requests
import threading # 多執行緒模塊
import re # 正則運算式模塊
import time # 時間模塊
import os # 目錄操作模塊
# 圖片串列頁面的陣列
all_img_urls = []
# 初始化一個鎖
g_lock = threading.Lock()
# 我們拼接好的圖片集和串列路徑
all_urls = []
# 圖片地址串列
pic_links = []
class Spider():
# 建構式,初始化資料使用
def __init__(self, target_url, headers):
self.target_url = target_url
self.headers = headers
# 獲取所有的想要抓取的 URL
def getUrls(self, start_page, page_num):
global all_urls
# 回圈得到URL
for i in range(start_page, page_num+1):
url = self.target_url % i
all_urls.append(url)
# 生產者,負責從每個頁面提取圖片串列鏈接
class Producer(threading.Thread):
def run(self):
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0',
'HOST': 'home.fang.com'
}
global all_urls
while len(all_urls) > 0:
# 在訪問all_urls的時候,需要使用鎖機制
g_lock.acquire()
# 通過pop方法移除最后一個元素,并且回傳該值
page_url = all_urls.pop()
# 使用完成之后及時把鎖給釋放,方便其他執行緒使用
g_lock.release()
try:
print("分析"+page_url)
response = requests.get(page_url, headers=headers, timeout=3)
# 提取詳情頁地址的正則運算式,需要重新撰寫
all_pic_link = re.findall(
'<a href="(.*?)" title=".*?" target="_blank">', response.text)
global all_img_urls
# 這里還有一個鎖
g_lock.acquire()
# 這個地方注意陣列的拼接,沒有用 append 直接用的+=也算是 python 的一個新語法
# 這里還需要將圖片地址拼接完整
all_img_urls += [
f"https://home.fang.com{link}" for link in all_pic_link]
# print(all_img_urls)
# 釋放鎖
g_lock.release()
time.sleep(0.5)
except:
pass
# 消費者
class Consumer(threading.Thread):
def run(self):
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0',
'HOST': 'home.fang.com'
}
global all_img_urls # 呼叫全域的圖片詳情頁面的陣列
print("%s is running " % threading.current_thread)
# print(len(all_img_urls))
while len(all_img_urls) > 0:
g_lock.acquire()
img_url = all_img_urls.pop()
g_lock.release()
try:
response = requests.get(img_url, headers=headers)
# 設定案例編碼
response.encoding = 'utf-8'
title = re.search('<title>(.*?)-房天下家居裝修網</title>', response.text).group(1)
all_pic_src = re.findall('<img src[2]?="(.*?)" οnerrοr=".*?"/>', response.text)
pic_dict = {title: all_pic_src} # python字典
global pic_links
g_lock.acquire()
pic_links.append(pic_dict) # 字典陣列
print(title+" 獲取成功")
g_lock.release()
except Exception as e:
print(e)
time.sleep(0.5)
if __name__ == "__main__":
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0',
'HOST': 'home.fang.com'
}
# 圖片集和串列規則
target_url = 'https://home.fang.com/album/s24/%d/'
spider = Spider(target_url, headers)
# 先測驗 5 頁資料
spider.getUrls(1, 5)
# print(all_urls)
threads = []
# 開啟兩個執行緒去訪問
for x in range(2):
t = Producer()
t.start()
threads.append(t)
for tt in threads:
tt.join()
print("進行到我這里了")
# 開啟10個執行緒去獲取鏈接
for x in range(10):
ta = Consumer()
ta.start()
除了正則運算式修改以外,在 main 中代碼涉及了多執行緒的執行順序問題,可重點學習一下,
接下來補齊圖片下載部分邏輯,案例 2 復盤完成,核心代碼未進行任何變更,篇幅原因,完整代碼提交到 https://codechina.csdn.net/hihell/scrapy,clone 案例 2 即可,最終得到大量裝修美圖,

好吧,我道歉,這個案例作為起手專案,有點難了,
案例三:美空網資料抓取
時隔三年,美空網竟然已經不能通過 PC 瀏覽模特資料了,是時候升級這個案例了,我們將其替換為站酷網 zcool,只做爬取展示,資料保存到 mongo 中,不再進行撰寫,
本案例核心是為了抓取用戶關系鏈,起始選擇任意一個用戶進行爬取都可,
https://douge2013.zcool.com.cn/follow?condition=0&p=1

安裝 mongodb 服務的時候出現了一點小問題,即 mangodb 服務無法啟動,
解決方案如下:
在 MongoDB 安裝目錄中找到 bin 檔案夾,同級目錄創建 data 檔案夾,在 data 中創建 db 與 logs 檔案夾,然后在控制臺輸入如下命令,
mongod --dbpath="C:\Program Files\MongoDB\Server\3.6\data\db" --logpath="C:\Program Files\MongoDB\Server\3.6\data\logs\MongoDB.log" --install --serviceName "MongoDB"
后面啟動 mongo 留給你自己完成,mongo --port 27017,
第一步鏈接生產者的代碼修改如下:
# -*- coding: UTF-8 -*-
import requests # 網路請求模塊
import random # 隨機模塊
import re # 正則運算式模塊
import time # 時間模塊
import threading # 執行緒模塊
import pymongo as pm #mongodb模塊
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",
"其它 UserAgent "
]
UserAgent = random.choice(user_agent_list)
headers = {'User-Agent': UserAgent}
return headers
# 起始種子地址
urls = ["https://douge2013.zcool.com.cn/follow?condition=0&p=1"]
index = 0 # 索引
g_lock = threading.Lock() # 初始化一個鎖
# 獲取連接
client = pm.MongoClient('127.0.0.1', 27017) # 埠號是數值型
# 連接目標資料庫
db = client.zcool
# 資料庫用戶驗證
db.authenticate("zcool", "zcool")
# 生產者
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("生產者例外")
print(http)
continue
content = response.text
rc = re.compile(
r'<a href="(.*?)" title=".*?" class="avatar" target="_blank" z-st="member_content_card_1_user_face">')
follows = rc.findall(content)
# print(follows)
fo_url = []
threading_links_2 = []
for u in follows:
# 生成關注串列地址
this_url = "%s/follow?condition=0&p=1" % 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()
最終經過我的一番修改,爬蟲 100 例案例三重獲新生,再次可用,重點修改的依舊是正則運算式決議邏輯,
修改后的代碼下載地址:https://codechina.csdn.net/hihell/scrapy 案例 3,

案例四:基于案例三抓取到的用戶地址,進行圖片抓取
通過案例三,獲取了大量的用戶地址,圖片抓取就不在進行案例更新了,使用案例三與案例四的思路,直接進行修改即可,
恰巧更新的站酷網也有圖片,正好可以練手,

今日復盤結論
在復盤程序中,要記住爬蟲的思路是不會發生變化的,實踐程序也看到,只需要進行目標網站地址變更,正則運算式變更,就可以撰寫一個全新的爬蟲,
良心博主,竟然 3 年不掉線,
收藏時間
做個不可能實作的任務吧,收藏過400,橡皮擦將回復評論區所有人,發一個神秘碼
今天是持續寫作的第 185 / 200 天,
可以關注我,點贊我、評論我、收藏我啦,
更多精彩
- Python 爬蟲 100 例教程導航帖(抓緊訂閱啦)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/289301.html
標籤:python
上一篇:[Python影像處理] 四十二.Python影像銳化及邊緣檢測萬字詳解(Roberts、Prewitt、Sobel、Laplacian、Canny、LOG)
下一篇:使用python制作世界地圖

