Python应用实战- 爬虫基础入门知识必会
0.爬蟲基礎(chǔ)流程
把爬蟲的過程模塊化,基本上可以歸納為以下幾個步驟:
-
[√] 分析網(wǎng)頁URL:打開你想要爬取數(shù)據(jù)的網(wǎng)站,然后尋找真實(shí)的頁面數(shù)據(jù)URL地址;
-
[√] 請求網(wǎng)頁數(shù)據(jù):模擬請求網(wǎng)頁數(shù)據(jù),這里我們介紹requests庫的使用;
-
[√] 解析網(wǎng)頁數(shù)據(jù):根據(jù)請求獲得的網(wǎng)頁數(shù)據(jù)我們用不同的方式解析成我們需要用的數(shù)據(jù)(如果網(wǎng)頁數(shù)據(jù)為html源碼,我們用Beautiful Soup、xpath和re正則表達(dá)式三種解析;若網(wǎng)頁數(shù)據(jù)為json格式,我們可以直接用字典列表等基礎(chǔ)知識處理)
-
[√] 存儲網(wǎng)頁數(shù)據(jù):一般來說,解析后的數(shù)據(jù)是比較結(jié)構(gòu)化的,可以保存為txt、csv、json或excel等文本,亦或者可以存儲在數(shù)據(jù)庫如MySql、MongoDB或SqlLite中。
1.分析網(wǎng)頁URL
當(dāng)我們有一個目標(biāo)網(wǎng)站,有時候會發(fā)現(xiàn)對于靜態(tài)網(wǎng)頁,我們只需要把網(wǎng)頁地址欄中的URL傳到get請求中就可以直接取到網(wǎng)頁的數(shù)據(jù)。但如果這是動態(tài)網(wǎng)頁,我們便無法通過簡單的傳遞網(wǎng)頁地址欄的URL給get請求來獲取網(wǎng)頁數(shù)據(jù),往往這個時候,我們進(jìn)行翻頁的時候還會發(fā)現(xiàn)網(wǎng)頁地址欄中的URL是不會發(fā)生變化的。
接下來,我們來分別介紹這兩種情況下如何獲取真實(shí)的頁面數(shù)據(jù)URL地址。
1.1 靜態(tài)網(wǎng)頁
對于靜態(tài)網(wǎng)頁來說,其實(shí)網(wǎng)頁地址欄中的URL就是我們需要的。
以?貝殼二手房網(wǎng)(https://bj.ke.com/ershoufang/) 為例,我們可以看到進(jìn)行翻頁(如到第2頁)的時候網(wǎng)頁地址欄的URL變?yōu)榱?https://bj.ke.com/ershoufang/pg2/)。類型這種情況,多半就是靜態(tài)網(wǎng)頁了,而且翻頁的URL規(guī)律十分明顯。
1.2 動態(tài)網(wǎng)頁
對于動態(tài)網(wǎng)頁來說,我們一般可以通過以下幾個步驟找到真實(shí)URL地址:
需要按“F12”進(jìn)入到瀏覽器的開發(fā)者模式;
點(diǎn)擊“Network”—>XHR或JS或者你全部查找看;
進(jìn)行翻頁(可能是點(diǎn)擊下一頁或者下滑加載更多);
觀察第2步中name模塊的內(nèi)容變化,尋找。
以?虎牙星秀區(qū)(https://www.huya.com/g/xingxiu) 為例,我們可以看到進(jìn)行翻頁(如到第2頁)的時候網(wǎng)頁地址欄的URL沒有發(fā)生任何改變。
為了便于找到真實(shí)的URL地址,我們可以在開發(fā)者模式中找以下截圖中的幾點(diǎn),preview是預(yù)覽結(jié)果,可以便于我們進(jìn)行匹配定位具體的Name。
虎牙星秀區(qū)
當(dāng)我們定位到具體的Name后,右側(cè)選擇Headers可以查看到請求網(wǎng)頁需要的相關(guān)參數(shù)信息,而且比較好擬清其變化規(guī)律。以虎牙星秀為例,其真實(shí)URL地址及變化規(guī)律如下:
URL= 'https://www.huya.com/cache.php?m=LiveList&do=getLiveListByPage&gameId=1663&tagAll=0&page=2'
基礎(chǔ) url 地址如下:
url?=?'https://www.huya.com/cache.php’請求參數(shù)parames如下:
parames?=?{'m':?'LiveList','do':?'getLiveListByPage','gameId':?1663,'tagAll':?0,'page':?2,?#?翻頁變化的就是這個參數(shù)}真實(shí)URL地址
2.請求網(wǎng)頁數(shù)據(jù)
當(dāng)我們確定了真實(shí)數(shù)據(jù)的URL后,這里便可以用requests的get或post方法進(jìn)行請求網(wǎng)頁數(shù)據(jù)。
關(guān)于requests庫的更多使用方式,大家可以前往(https://requests.readthedocs.io/zh_CN/latest/)查看。
2.1 發(fā)送get請求
In?[1]:?import?requestsIn?[2]:?url?=?'https://bj.ke.com/ershoufang/'In?[3]:?r?=?requests.get(url)In?[4]:?type(r) Out[4]:?requests.models.ResponseIn?[5]:?r.status_code Out[5]:?200我們得到的是一個Response對象,如果我們想要獲取網(wǎng)頁數(shù)據(jù),可以使用text或content屬性來獲取,另外如果獲取的網(wǎng)頁數(shù)據(jù)是json格式的則可以使用Requests 中內(nèi)置的 **json()**解碼器方法,助你處理json 數(shù)據(jù)。
-
r.text:字符串類型的數(shù)據(jù),一般網(wǎng)頁數(shù)據(jù)為文本類用此屬性
-
r.content:二進(jìn)制類型的數(shù)據(jù),一般網(wǎng)頁數(shù)據(jù)為視頻或者圖片時用此屬性
-
r.json():json數(shù)據(jù)解碼,一般網(wǎng)頁數(shù)據(jù)為json格式時用此方法
對于一些動態(tài)網(wǎng)頁,請求的網(wǎng)址是基礎(chǔ)url和關(guān)鍵字參數(shù)組合而成,這個時候我們可以使用?params?關(guān)鍵字參數(shù),以一個字符串字典來提供這些參數(shù)。
In?[6]:?url?=?'https://www.huya.com/cache.php'...:?parames?=?{...:?????'m':?'LiveList',...:?????'do':?'getLiveListByPage',...:?????'gameId':?1663,...:?????'tagAll':?0,...:?????'page':?2,?#?翻頁變化的就是這個參數(shù)...:?????}...:?...:?r?=?requests.get(url,?params=parames)In?[7]:?r.url Out[7]:?'https://www.huya.com/cache.php?m=LiveList&do=getLiveListByPage&gameId=1663&tagAll=0&page=2'2.2 發(fā)送post請求
通常,你想要發(fā)送一些編碼為表單形式的數(shù)據(jù)——非常像一個 HTML 表單。要實(shí)現(xiàn)這個,只需簡單地傳遞一個字典給 data 參數(shù)。你的數(shù)據(jù)字典在發(fā)出請求時會自動編碼為表單形式:
>>>?payload?=?{'key1':?'value1',?'key2':?'value2'}>>>?r?=?requests.post("http://httpbin.org/post",?data=payload)很多時候你想要發(fā)送的數(shù)據(jù)并非編碼為表單形式的。如果你傳遞一個?string?而不是一個?dict,那么數(shù)據(jù)會被直接發(fā)布出去。
>>>?import?json>>>?url?=?'https://api.github.com/some/endpoint' >>>?payload?=?{'some':?'data'}>>>?r?=?requests.post(url,?data=json.dumps(payload))此處除了可以自行對?dict?進(jìn)行編碼,你還可以使用?json?參數(shù)直接傳遞,然后它就會被自動編碼。
>>>?url?=?'https://api.github.com/some/endpoint' >>>?payload?=?{'some':?'data'}>>>?r?=?requests.post(url,?json=payload)2.3 定制請求頭
在模擬請求時,如果不設(shè)置請求頭的話是比較容易被網(wǎng)站發(fā)現(xiàn)是來自爬蟲腳本,一些網(wǎng)站會對這種模擬請求進(jìn)行拒絕。因此我們可以簡單設(shè)置一下請求頭做偽裝,一般是設(shè)置瀏覽器。
headers?=?{"User-Agent":?"Mozilla/5.0?(Windows?NT?10.0;?Win64;?x64)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/87.0.4280.66?Safari/537.36",} r?=?requests.get(url,?headers=headers)其實(shí),對于請求頭還可以設(shè)置很多參數(shù),具體大家可以在實(shí)際爬蟲過程中在開發(fā)者模式看看里面的請求頭模塊進(jìn)行分析處理。
虎牙星秀請求頭
2.4 響應(yīng)碼
我們在 2.1 中看到獲取響應(yīng)碼的是通過?r.status_code屬性,一般來說如果 返回 數(shù)字?200,則表示成功獲取了網(wǎng)頁數(shù)據(jù)。
響應(yīng)碼分為五種類型,由它們的第一位數(shù)字表示:1xx:信息,請求收到,繼續(xù)處理 2xx:成功,行為被成功地接受、理解和采納 3xx:重定向,為了完成請求,必須進(jìn)一步執(zhí)行的動作 4xx:客戶端錯誤,請求包含語法錯誤或者請求無法實(shí)現(xiàn) 5xx:服務(wù)器錯誤,服務(wù)器不能實(shí)現(xiàn)一種明顯無效的請求
3.解析數(shù)據(jù)
上面有提到我們請求的網(wǎng)頁數(shù)據(jù)有Html源碼文本或者是json字符串文本,兩者的解析方式不同。以下我們分別進(jìn)行簡單說明,大家在實(shí)際操作中視情況而定即可。
3.1 網(wǎng)頁html文本解析
對于網(wǎng)頁html文本來說,這里介紹Beautiful Soup、xpath和re正則表達(dá)式三種解析方法。
以貝殼二手房最新房源(https://bj.ke.com/ershoufang/co32/)為例,其html源碼如下,我們通過get請求后的數(shù)據(jù)進(jìn)行解析。
貝殼二手房
3.1.1 Beautiful Soup
關(guān)于Beautiful Soup庫的更多使用方式,大家可以前往查看(https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/)
首先安裝pip install beautifulsoup4。
我們將網(wǎng)頁html文本內(nèi)容r.text當(dāng)作第一個參數(shù)傳給BeautifulSoup對象,該對象的第二個參數(shù)為解析器的類型(這里使用lxml),此時就完成了BeaufulSoup對象的初始化。然后,將這個對象賦值給soup變量。
from?bs4?import?BeautifulSoup import?requestsurl?=?'https://bj.ke.com/ershoufang/co32/' r?=?requests.get(url) soup?=?BeautifulSoup(r.text,?'lxml')房源名稱
獲取房源的名稱的代碼如下:
#?獲取全部房源?所在的節(jié)點(diǎn) sellList?=?soup.find(class_="sellListContent") #?獲取全部房源節(jié)點(diǎn)列表 lis?=?sellList.find_all('li',class_="clear") #?選取第一個房源節(jié)點(diǎn) div?=?lis[0].find('div',class_="info?clear") #?采集房源名稱 title?=?div.find('div',class_="title") print(title.text) 明春西園?2室1廳?南?北房源其他信息大家可以自己處理,強(qiáng)化學(xué)習(xí)!
3.1.2 xpath
XPath,全稱 XML Path Language,即 XML 路徑語言,它是一門在 XML 文檔中查找信息的語言。
首先安裝lxmlpip install lxml。
常見的規(guī)則如下:
| nodename | 選取此節(jié)點(diǎn)的所有子節(jié)點(diǎn) |
| / | 從當(dāng)前節(jié)點(diǎn)選取直接子節(jié)點(diǎn) |
| // | 從當(dāng)前節(jié)點(diǎn)選取子孫節(jié)點(diǎn) |
| . | 選取當(dāng)前節(jié)點(diǎn) |
| .. | 選取當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn) |
| @ | 選取屬性 |
首先導(dǎo)入 lxml 庫的 etree 模塊,然后聲明一段 HTML 文本,調(diào)用 HTML 類進(jìn)行初始化,成功構(gòu)造一個 XPath 解析對象。
from?lxml?import?etree import?requestsurl?=?'https://bj.ke.com/ershoufang/co32/' r?=?requests.get(url) html?=?etree.HTML(r.text)右鍵可獲取xpath
通過copy獲取的xpath://*[@id="beike"]/div[1]/div[4]/div[1]/div[4]/ul/li[1]/div/div[1]/a
#?獲取?全部房源所在節(jié)點(diǎn)?ul,根據(jù)屬性匹配精準(zhǔn)查找 ul?=?html.xpath('.//ul[@class="sellListContent"]')[0] #?獲取房源列表 lis?=?ul.xpath('.//li[@class="clear"]') #?選取第一個房源節(jié)點(diǎn) li?=?lis[0] #?獲取其房源名稱 li.xpath('./div/div[1]/a/text()') ['明春西園?2室1廳?南?北']其他房源信息,大家可以自行處理,強(qiáng)化學(xué)習(xí)!
3.1.3 re正則
關(guān)于re正則解析網(wǎng)頁html大家也可以前往查看此前發(fā)布的文章《對著爬蟲網(wǎng)頁HTML學(xué)習(xí)Python正則表達(dá)式re》。
#?找到房源名稱所在的前后字符,然后組成正則表達(dá)式 re.findall(r'<a?class="VIEWDATA?CLICKDATA?maidian-detail"?title="(.*?)"',r.text,re.S)[0] '明春西園?2室1廳?南?北'3.2 json文本解析
在requests提供了r.json(),可以用于json數(shù)據(jù)解碼,一般網(wǎng)頁數(shù)據(jù)為json格式時用此方法。除此之外,還可以通過json.loads()和eval()方法進(jìn)行處理,具體可以參考此前文章《Python爬取美團(tuán)網(wǎng)數(shù)據(jù)這么簡單,別再說你不會了哦!》。
json文本解析
url?=?'https://www.huya.com/cache.php' parames?=?{'m':?'LiveList','do':?'getLiveListByPage','gameId':?1663,'tagAll':?0,'page':?2,?#?翻頁變化的就是這個參數(shù)}r?=?requests.get(url,?params=parames) data?=?r.json() type(data) dict如此解析后得到的數(shù)據(jù)就是字典,然后我們在看看字典中哪些字段是我們需要的,取出即可。
4.存儲數(shù)據(jù)
當(dāng)我們獲取了到想要的數(shù)據(jù)后,便可以寫入本地了。
對于文本類數(shù)據(jù),可以通過csv模塊或pandas模塊進(jìn)行寫入到本地csv文件或excel文件;同時也可以用pymysql模塊寫入到數(shù)據(jù)庫或者sqlite寫入到本地數(shù)據(jù)庫。
對于視頻或者圖片,可以open一個文件然后寫入二進(jìn)制內(nèi)容后保存本地亦可。
關(guān)于存儲數(shù)據(jù)大家可以結(jié)合實(shí)際案例進(jìn)行學(xué)習(xí)。
總結(jié)
以上是生活随笔為你收集整理的Python应用实战- 爬虫基础入门知识必会的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Panda处理文本和时序数据?首选向量化
- 下一篇: Python办公自动化,对文件进行自由操