還有一件事:
- 本教學配合c語言中文網 python爬蟲 教學 食用
- 本教學不適用於未成年人
- 一定要刷牙
- 本教學不存在知識詛咒
- 學完本教學即可進入築基期
- js 基礎和本教學學習效率成正比
- 不要笑
- 暫時不要駕駛你的行李箱
- 本教學是針對前端程式設計師制定的
- vscode是IDE大王,什麼?你說vscode不是IDE?
令我驚喜的是 py和js有很多相似的地方 甚至作為一個前端程式設計師,在看到python程式碼的那一刻,倍感親切
本來我覺得js已經夠自由了,弱型別變數、以回車結束語句、簡潔明瞭又極度自由的語法,而python程式碼則更為簡潔
如果你也是正在學習Python的前端程式設計師,那麼你一定跟我感同身受
py定義變數時甚至不需要 關鍵詞 (js是 let var),這個東西甚至簡潔到讓我懷疑它是不是真的能用
可能寫C++的人看到 js 程式碼也會有這種疑惑
相信看到這裡,你和我有了一個共同的問題:既然簡潔到這種程度,那我想定義一個常數該怎麼辦?牛逼的事情來了,python摒棄了常數這個東西,我覺得是py認為常數太不純粹,我為什麼需要一個不能修改的值?於是,python沒有常數,如果你實在需要一個常數,也可以 通過其他方式實現
如果你的程式設計生涯也是從切圖仔做起的,不懂什麼資料結構、計算機原理、編譯原理,那麼你可能會對下面的程式碼產生疑惑
import urllib.request
和 js 相比較,這個寫法簡直奇怪到姥姥家了,主要的疑問有兩點:1.我從沒有下載過這個包,怎麼引入成功了?2.我怎麼知道哪些包可以參照?參見 Python是如何找包的,Python安裝的包放在哪裡 ,當然的然,沒有下載過一個包,或者py沒有自帶這個包,也就是說,你本地沒有這個包的情況下,也是不能引入的,只是py的直譯器會自動在設定好的路徑中去查詢這個包。
就比如 在標準npm專案中 的使用import引入,會自動去node_modules中查詢一樣
在js中,我想實現某個相較複雜的功能,會先去npm上搜尋有沒有可用包,這是正常操作。在py中,也有類似的操作,且py能幹的事情不再侷限在web的前後端上,所以py的包幾乎涵蓋了所有領域,這也是py崛起的原因之一。作為一個py新手,如果你想實現一個功能,不妨先去pip上搜一下。
我看到的py爬蟲教學,第一個程式是這麼寫的
import urllib.request
response = urllib.request.urlopen('http://www.baidu.com/')
print(response)
html = response.read().decode('utf-8')
print(html)
顯然,如果你有一點任何語言的基礎,那麼這幾行程式碼根本不需要註釋,py十分貼近自然語言,這也是我為什麼選擇py作為第二語言的原因。
對與上面的程式碼,需要注意的點有:
本節教學:http://c.biancheng.net/python_spider/the-first-spider.html
半路出家的前端人,對網路協定、網路請求也知之甚少,要學習爬蟲,對此要有進一步的瞭解。首先,各大網站都對爬蟲做了一些限制,比如監測到爬蟲頻繁存取的話,有可能對該ip進行短時間的封鎖,比如常見的:「操作頻繁」提示,就是對ip的一種封鎖,在前端的眼裡,這個操作叫節流和防抖,在py爬蟲上,叫做反爬。
網站對爬蟲做出限制,其實是很好理解的,因為不同於普通的瀏覽器使用者(真人),爬蟲有能力大量頻繁的存取,可能會對伺服器造成負擔。當然,也不是不希望爬蟲去存取,相反的,很多網站其實是歡迎爬蟲的,因為這有利於在百度等搜尋引擎的關鍵詞排名,也就是常常聽說的SEO。總之就是一句話,想讓你爬,但不想讓你會會的爬,年輕人不要太氣盛。
我們知道,一個大型網站的存取的數量級是很大的,爬蟲,多我一個不多,少我一個不少。我如果就想不斷地、頻繁的存取怎麼辦?User-Agent,使用者代理。如果你玩手機時,在手機瀏覽器裡曾經見過一個叫UA的選項,裡面可以選擇PC、Iphone、Android,那麼恭喜你,因為你早就認識它了,網站反爬時,識別UA是一個基本手段。UA是一個字串,可以告知你存取的網站你使用的的軟體基本資訊 參見 User-Agent(使用者代理)是什麼
不斷地變換你的UA就可以達到欺騙反爬程式的效果。
本節教學 http://c.biancheng.net/python_spider/useragent-pool.html
自定義UA代理池,嚴先生(介紹一下,他是C語言中文網的站長,記住了,下面不再介紹了)為我們列舉了幾個常用的UA字串,並把它放在了一個新建檔案裡。
問題來了,引入pip包我會了,但是自己建的檔案我卻不會,這沒什麼可擔心的,這種事情一聽就很基礎,參見 python引入其他資料夾裡的py檔案的方法,引入後,接下來的你就會了。
嚴先生說了,我們要不斷變換我們的UA值,那麼我就想著取一個亂數,然後使用這個亂數作為陣列的下標值,取出資料,於是我上網搜了:python亂數
看到了這樣一個震驚的東西
解釋一下sequence:我也不懂,搜了一下,叫序列,應該跟陣列是一種東西,注意,這個東西不是任何專業術語,這是個單詞,python中的序列型別包括:list, tuple 和 range 物件。
關於python序列參見 https://blog.csdn.net/weixin_42214654/article/details/114411515
淺看一眼,我得知python中沒有陣列,和陣列最類似的就是 list ,基本上等於js中的Array,但是稍微有點區別
參見 https://blog.csdn.net/weixin_30834019/article/details/97694533
綜上所述,現在來綜合試一下,檔案引入,和隨機取元素
import uaList #這是我自定義的那個檔案
import random #如果你沒有引入這個東西,會自動提示引入的
headers = {
'User-Agent': random.choice(uaList.ua_list)
}
很顯然,我寫的沒有問題,每次都能取到一個隨機的值。
哎等會,現在發生了一件很奇怪的事情
我乾乾淨淨的目錄出現了一個命名方式令人抓狂的、不認識的、裡邊檔案打不開的資料夾!能不能刪除,我替你們試了,可以刪,但是刪掉之後一執行還會出來。關於這個檔案,參見:pyhton中__pycache__資料夾的產生與作用
我們好像已經做了2178個詞的準備了,但是學python好像不如我想象的那麼迅速,我們寫HTML下一秒就能看到效果,但是python好像不行,耐心點,我們應該馬上可以學會了。
接下來需要了解的是 URL的編碼和解碼。
為什麼URL還需要編碼,編什麼碼,什麼編碼?在我的印象裡,url就是網址,我只知道他是一個網址,或者叫連結,我也不知道怎麼叫才是正規的。
URL 是由一些簡單的元件構成,比如協定、域名、埠號、路徑和查詢字串等,範例如下:
http://www.biancheng.net/index?param=10
顯然 http是網路協定 冒號雙斜槓不知道為什麼要加,但我們都知道要加,後面的問號我們知道是用來分割網址和引數的,我們還知道使用&分割引數與引數。其餘的不知道了。
那麼此時可以聯想到,上述幾個符號:斜槓、冒號、問號、and符號 都是不能被作為正常的字元去解析的,他們被稱為保留字,就像在js中,你不可以把一個變數命名為 let
在url中,保留字需要轉碼,其次,就是不安全字元,像方括號、尖括號、雙引號、大括號、分隔符等,還有,url是用的ASCII碼,也就是說它不支援中文(我們知道支援中文的編碼有 utf-8或者GBK,其他的不知道了),中文也需要轉碼!
等等,我是說,等一下,太多了,我怎麼記得住?
沒關係,要是我們在學別的語言,那確實太多了,但我們學的是python,python啊大哥,python的標準庫中有自動編碼的東西,他媽的,上邊一通白說了,我們要快速麵向業務!
Python 的標準庫urllib.parse
模組中提供了用來編碼和解碼的方法,分別是 urlencode() 與 unquote() 方法。
#匯入parse模組
from urllib import parse
#構建查詢字串字典
query_string = {
'wd' : '爬蟲'
}
#呼叫parse模組的urlencode()進行編碼
result = parse.urlencode(query_string)
#使用format函數格式化字串,拼接url地址
url = 'http://www.baidu.com/s?{}'.format(result)
print(url)
#wd=%E7%88%AC%E8%99%AB
#http://www.baidu.com/s?wd=%E7%88%AC%E8%99%AB
result = parse.unquote(url)
print(result)
#爬蟲
好小子,白讓我看這麼多,有自動的我還學什麼,現用現搜。
本節教學:URL編碼/解碼詳解
做了2869個詞的準備之後,我們終於要開始爬了。
明確一下,爬蟲程式的三個步驟:
本節教學:http://c.biancheng.net/python_spider/crawl-webpage.html
根據教學寫完,我們又發現了一些新的東西
py可以很容易的和使用者交換資訊,比如它不必寫一個輸入框或者文字域來讓使用者輸入資訊,py要獲取使用者輸入的字元,只需寫:
input("請輸入內容:")
即可,這個函數會返回使用者輸入的值,咱可以拿一個變數去接受,即 userInput = input("請輸入內容:")
py定義函數很特別,靠縮排來辨別函數體,沒有大括號,所以py的函數長這樣
def getUserInput():
# 使用者輸入
global userInput
userInput = input("請輸入內容:")
return userInput
一旦縮排出現錯誤,那麼此處也將不屬於這個函數體,你可以自己試一下。
細心的你也許已經發現,上述函數中出現了關鍵字 global ,這是定義全域性變數的方法,雖然定義在函數內部,但是其作用域是全域性的,因為我們後續要對使用者輸入的中文字元進行轉碼,所以這裡做一個全域性變數來儲存它,以便於最後給檔案命名。
細心的你也許又發現,py定義函數的關鍵字是 def ,且因為沒有大括號包裹函數體,它必須以return結束,否則程式無法知道這個函數是否結束,我是這麼認為的。
本節教學寫的程式碼,以及嚴先生整理的,函數式的修改,我都沒看。
所以我寫了如下,跟教學完全不同風格的程式碼,我自認為比較符合 js 思想
import uaList
import random
from urllib import request
from urllib import parse
def getUserInput():
# 使用者輸入
global userInput
userInput = input("請輸入內容:")
return userInput
def buildHeader():
# 製作請求頭
headers = {
# 隨機在序列中取元素,這個usList是我自定義的檔案
'User-Agent': random.choice(uaList.ua_list)
}
return headers
def makeUrl(url, param):
# parse.urlencode 和 parse.quote的區別是
# 前者可以把物件(指js物件的形式,python好像叫集合)的鍵值對變成get請求的鍵值對,也就是 wd=爬蟲 這種形式
return url.format(parse.urlencode(param))
def getHtmlDoc(url, param):
req = request.Request(
url=makeUrl(url, param),
headers=buildHeader()
) # 建立請求
res = request.urlopen(req) # 傳送請求
html = res.read().decode('utf-8') # 編碼為utf-8,我不知道為什麼
writeFiles(userInput, html) # 這裡使用了全域性變數 在定義是使用關鍵字 global (@line:9)
return
def writeFiles(fileNameIn, data):
filename = parse.unquote(fileNameIn) + '.html' # 拼接檔名
with open(filename, 'w', encoding='utf-8') as f: # 寫入檔案,這裡我也不懂,好像是py自帶的東西
f.write(data)
return
getHtmlDoc("http://www.baidu.com/s?{}", {
"wd": getUserInput()
})
這次你可能沒這麼細心,我告訴你,倒數第三行在字串中出現了一個大括號,這個大括號在字串被讀取時會被忽略(我認為),其作用是告訴 .format方法,後面拼接的東西該放在哪(我認為).format好像也是py自帶的一個字串處理方法。用法類似 c 語言中的 字串變數格式化
例如
printf("%s\n", str);
其中 %s 含義為 此處為字串,對應後面的str。
參見:Python format 格式化函數 和 C語言字串的輸入和輸出
其實 ,這種寫法在 c、js、python中都可以使用 參見 JavaScript console.log %c %o %s %d %f
至此,我們已經可以把一個頁面完整的爬下來,上面的一小段程式會將 百度搜尋結果頁生成一個html檔案,在專案根目錄,恭喜各位。
本節教學:http://c.biancheng.net/python_spider/case01.html
嚴先生上來就教我們判斷頁面型別,笑話,我們用你教?
尋找URL變化規律,笑話,用你教?
編寫爬蟲程式,笑話...等等,這個跟前面的不太一樣
出現了一個我聽過,都不知道是什麼的東西 class(類),看到這,相信很多大佬要指責我了,js也有類(es6),沒錯,但是我真沒用過,剛剛 看了一下,這個東西還是個物件而已,要不怎麼說js是個基於物件的語言呢?關於js的類,參見 終於,JavaScript也有了類(class)的概念
相信在座各位在公司都是一個被UI牽著鼻子,又被後端打著屁股的美麗小夥。我們只會切圖和調介面啊,什麼類啊,真不懂啊!
其實類沒有什麼複雜的,之所以不懂,是因為適用場景不多,因為沒有很多的邏輯需要類來加持,有時使用一個物件就足夠了,雖然類能很方便的管理變數和方法,但是我們一般還是習慣使用自定義物件來實現業務,對吧?
好的,既然你跟我想的一樣,那麼這節就基本結束了,因為基本邏輯和前面講的是一樣的,在本章程式碼的最後,出現了一個令人迷惑的東西,而嚴先生沒有對此進行解釋(知識詛咒)
if __name__=='__main__':
對此,請參見: Python中「if name=='main':」理解與總結 ,這個人講的真好,建議給他點個贊。
最後的最後,嚴先生介紹了程式隨機休眠的重要性
爬蟲程式存取網站會非常快,這與正常人類的點選行為非常不符。因此,通過隨機休眠可以使爬蟲程式模仿成人類的樣子點選網站,從而讓網站不易察覺是爬蟲存取網站,但這樣做的代價就是影響程式的執行效率。
聚焦爬蟲是一種執行效率較低的程式,提升其效能,是業界一直關注的問題,由此也誕生了效率較高的 Python 爬蟲框架 Scrapy。
嚴先生寫的 正規表示式基本語法 非常精煉易懂,作為前端程式設計師,我們用到正規表示式的機會還是很多的,所以相信大家多多少少都對正規表示式有一定的認識,在w3school或者菜鳥教學的教學亂的一批,建議換成嚴先生的教學。
菜鳥教學提供線上的正則測試 正規表示式線上測試
Python re模組用法詳解 是對re模組(正則相關)的一些解讀,大部分在講正規表示式,可以略過,等用到時再搜
Python csv模組(讀寫檔案) 介紹了csv檔案的讀寫,可能很多同學對csv也比較熟悉,且在前端有過實踐經驗,這裡主要介紹python的讀寫。
上面程式碼提到過寫入檔案,但是沒有具體解釋,因為那會我也不懂,就是這個 with open()
參見:https://blog.csdn.net/m0_48936146/article/details/124360734
應用以上所學的知識,我們就可以編寫一個稍微複雜的爬蟲,並在其中找出我們需要的資料了,我相信你會解決編寫過程中遇到的問題!
接下來,我們略過課程:
[範例]抓取貓眼電影排行榜 主要講正則的應用
Python Pymysql儲存資料 主要描述在python中操作mysql資料庫,如果你不會mysql,那你沒必要學這章
[範例]抓取多級頁面資料 主要講正則應用的變體,和增量爬蟲,增量爬蟲就是隻抓更新的部分
看到這三個標題,如果你不能快速的整理思路,那麼你可以先檢視一下這三節(我反正沒看)
不知道你在做上面的例子的時候,有沒有遇到過爬取頁面要求你進行人機驗證的,Requests 庫有時可以有效地規避這個問題,同時,它是在python中應用最廣泛的http請求庫
方法 | 說明 |
---|---|
requests.request() | 構造一個請求物件,該方法是實現以下各個方法的基礎。 |
requests.get() | 獲取HTML網頁的主要方法,對應於 HTTP 的 GET 方法。 |
requests.head() | 獲取HTML網頁頭資訊的方法,對應於 HTTP 的 HEAD 方法。 |
requests.post() | 獲取 HTML 網頁提交 POST請求方法,對應於 HTTP 的 POST。 |
requests.put() | 獲取HTML網頁提交PUT請求方法,對應於 HTTP 的 PUT。 |
requests.patch() | 獲取HTML網頁提交區域性修改請求,對應於 HTTP 的 PATCH。 |
requests.delete() | 獲取HTML頁面提交刪除請求,對應於 HTTP 的 DELETE。 |
由此可見,此庫囊括了所有http請求方法,基於此,我們甚至可以寫一個自己的介面測試工具
代理IP-proxies引數
一些網站為了限制爬蟲從而設定了很多反爬策略,其中一項就是針對 IP 地址設定的。比如,存取網站超過規定次數導致流量異常,或者某個時間段內頻繁地更換瀏覽器存取,存在上述行為的 IP 極有可能被網站封殺掉。可以使用瀏覽器外掛:Proxy SwitchyOmega,可以便捷的更換ip代理
本節課程:Requests庫常用方法及引數介紹
接下來介紹一個你可能用過的東西 Xpath ,這個東西在前端也有應用,有一個js外掛叫做 jsonpath,不知道你有沒有聽說過,簡單說,jsonpath可以用特定的語法在複雜的json資料中查詢
例如,我們現在有如下 json 資料
{
"objectTop":[
{
name:"data1",
id:1,
status:"on"
},
{
name:"data2",
id:2,
status:"off"
},
{
name:"data3",
id:3,
status:"on"
}
]
}
我們要查詢 status == on 的資料,按照正常思路,我們首先要遍歷 objectTop ,大概這麼寫
function getStatusOn(){
let res = []
for(let item of objectTop){
if(item.status == "on")
res.push(item)
}
}
或者使用 Object.x 去遍歷,陣列還可以使用filter或者map去遍歷,當然這麼寫已經很方便了,但是jsonpath一行程式碼就可以搞定了,大概這麼寫
let res = jsonpath.query(objectTop,"$..[?(@.status == 'on')]")
更多關於 jsonpath 的教學 ,參見 JsonPath基本用法 npm上也有jsonpath的包可供下載。
解釋一下上面表示式的大概含義
$:根節點 即 objectTop
.. : 遞迴查詢(貪婪模式,查詢到最後一級)
[?()] :裡面包含條件語句
@. : 當前key(或者當前節點)
status == 'on' 是條件語句
這種寫法好像一種 sql 語句,它其實大部分語法就遵循了Xpath
XPath(全稱:XML Path Language)即 XML 路徑語言,它是一門在 XML 檔案中查詢資訊的語言,最初被用來搜尋 XML 檔案,同時它也適用於搜尋 HTML 檔案。因此,在爬蟲過程中可以使用 XPath 來提取相應的資料。
如果說 jsonpath 可以快速查詢json節點,那麼xpath就可以快速查詢dom節點
有興趣的還可以看一下xpath在前端的應用,參見: js用xpath定位獲取元素
本節教學:Xpath簡明教學(十分鐘入門)
Xpath Helper是一款瀏覽器外掛,可以便捷的自動生成查詢語句
據我所知,咱們上邊學了正則的方式查詢元素,弄了半天有xpath這麼個玩意,那上邊的不白學了
這章我看了,我以為學個爬蟲,還順便教我們駭客技術,所謂的抓包,就是在瀏覽器的開發者工具看網路請求記錄,看不起誰呢,我們是前端。下一章。
這章我看了,就是調了別人的介面,不用看。這章提到了一個術語,可能有的同學不知道:加鹽,簡單來說加鹽就是加密,是一種很初級的加密手段。老王曾經這麼跟我說的,加鹽,就是加點佐料,吃著就不一樣了。給一個明文加點佐料(鹽),也就是加鹽,這個明文就成了密文了。
這章我看了,還是調了別人的介面,不用看
import json,就完了
方法 | 說明 |
---|---|
json.dumps() | 將 Python 物件轉換成 JSON 字串。 |
json.loads() | 將 JSON 字串轉換成 Python 物件。 |
json.dump() | 將 Python 中的物件轉化成 JSON 字串儲存到檔案中。 |
json.load() | 將檔案中的 JSON 字串轉化成 Python 物件提取出來。 |
類似js中的 JSON.parse() 和 JSON.stringfy()
簡單來說,有些網站登入後使用cookie儲存登入狀態,並且在向伺服器請求時也攜帶cookie資訊,相信大家或多或少也做過類似的業務,有時我們使用 Authorization 或者 攜帶 token 的方式(大多數時候)。cookie和ua一樣,可以直接以字串形式填寫在header裡,
就是這樣
headers = {
"cookie": 'appmsglist_action_3228059900=card; RK=IC8o9cFlOq; ptcz=c4a3603f5d15ebc78f805034e793aaff8840473c18e1a6e595470b56b78ae125; ',
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.54"
}
如果一個網站必須登入才能爬到有用的資料,那麼你可以試一下這個方法,你會快速的收穫成就感(我學到這已經幫公司寫了一個公眾號爬蟲了)
執行緒這個概念對我們來說太複雜了,我不學了,不過跟著這章教學可以快速做出一個多執行緒爬蟲
本節教學 Python多執行緒爬蟲詳解
美味濃湯:Beautiful Soup 簡稱 BS4(其中 4 表示版本號)是一個 Python 第三方庫
Beautiful Soup 將 HTML 檔案轉換成一個樹形結構,比xpath好用一點點,各有千秋
bs4還提供了直接的css選擇器和標籤選擇器,是真正比較直觀的一個解析器
本節教學 Python BS4解析庫用法詳解
Selenium 作為一款 Web 自動化測試框架,提供了諸多操作瀏覽器的方法。基本上可以實現任何 瀏覽器操作,模擬人手操作,例如:點選、輸入、拖動、調整瀏覽器視窗大小(是的)、各種鍵盤事件。這章提到了「無介面瀏覽器」,也就是常說的(我不常說,不知道誰常說)無頭瀏覽器
這章我看了,屬於結丹期的功法,我也不會,就不講了,靈根好的同學可以自行修煉。
至此,你已經達到了python爬蟲築基期修為,現在你可以 爬普通的網頁和帶登入驗證的網頁(對於凡人來說,你已經無所不能了)
總結:python好,真好,寫出來第一個有用的爬蟲程式時,幸福感滋兒一下就上來了(乾淨又衛生)。
學完這些,我們甚至還可以寫介面測試了,後端甩給你一個圖片AI識別的介面,讓你把這 兩千張圖 測一下,我反手一個python指令碼,跑了一個小時,完事。
老闆問我能不能把公眾號的文章同步到公司官網,沒問題,一個小時寫了個爬蟲,十秒同步完成。
老闆還是不滿意,能不能每更新一次就自動同步到官網,沒問題,這個叫定時增量爬蟲,一個半小時足夠了,部署到伺服器,定時執行。
python真是太美好啦,我感覺我已經無所不能了。
俗話說的好:爬蟲學的好,牢飯吃到飽。所以大家沒事別老研究爬蟲,影響自己的仕途。