X0
HTTP(HyperText Transfer Protocol)超文本傳輸協(xié)議,是web服務(wù)器到web瀏覽器之間傳輸?shù)耐ㄐ乓?guī)則。
0x01
HTTP協(xié)議目前最新版本是1.1,HTTP是一種無狀態(tài)的協(xié)議,只能由客戶端發(fā)起,服務(wù)器端不能主動向客戶端發(fā)送數(shù)據(jù)。
應(yīng)答模型:
Request請求
客戶端=============》服務(wù)端
《============
Response響應(yīng)
0x02 HTTP請求
包括三個部分:1、請求行; 2、請求頭; 3、請求正文。
實(shí)例:
GET /notification/notification_count/ HTTP/1.1 請求行
Host: mp.xxxxxx.com 請求頭
User-Agent: Mozilla/5.0 (X11; Linux i686; rv:52.0) Gecko/20100101 Firefox/52.0 (User-Agent代表瀏覽器標(biāo)識。)
Accept: application/json, text/javascript, */*; q=0.01 正文
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://mp.toutiao.com/profile_v2/publish
X-Requested-With: XMLHttpRequest
圖例brupsuite:
使用python socket測試http響應(yīng)的效果:
import socket
t_host="www.toutiao.com"
t_port=80
client=socket.socket()
client.connect((t_host,t_port))
client.send("GET / HTTP/1.1\r\nHost:toutiao.com\r\n\r\n")
response=client.recv(4096)
print response
HTTP/1.1 502 Bad Gateway //響應(yīng)行 HTTP的版, 狀態(tài)碼 502,消息是Bad Gateway
Server: Tengine //響應(yīng)頭 由服務(wù)器向客戶端發(fā)送
Content-Length: 0
Connection: keep-alive
Via: cache5.cn218[0,502-257,M], cache4.cn218[14,1,502001]
X-Swift-Error: dns domain not exist
Timing-Allow-Origin: *
EagleId: 790e0d0415057759521686693e
........由于response獲取的字節(jié)有限下面是響應(yīng)正文,是服務(wù)器向客戶端發(fā)送的HTML數(shù)據(jù)。
EOF:下一遍我將講述HTTP的請求方法,請期待。
碼如下:
import requests from bs4 import BeautifulSoup import pandas as pd #下面是請求數(shù)據(jù) url="https://www.163.com/" #設(shè)置請求網(wǎng)址為搜索網(wǎng)址 response=requests.get(url) #對163網(wǎng)站就行g(shù)et請求并將請求結(jié)果賦值給response response.encoding="GBK" #設(shè)置編碼為GBK格式的 html=response.text #獲取網(wǎng)頁的html源代碼并賦值給html #下面是解析數(shù)據(jù) soup=BeautifulSoup(html) content=soup.findAll('div') #查找所有的div標(biāo)簽內(nèi)容并賦值給content print(content) #打印content
代碼運(yùn)行結(jié)果如下圖所示:
多朋友都聽說過Python的大名,而Python也擁有眾多的爬蟲框架,其中最簡單的莫過于requests-html了。它和著名的網(wǎng)絡(luò)請求庫requests是同一個作者,著重于XML數(shù)據(jù)提取,可以說是最簡單的爬蟲框架了。
安裝這個類庫非常簡單,直接通過pip就可以安裝了。
pip install requests-html
requests-html用起來也十分簡單,下面是一個簡單例子。照例說明一下,第一段引入了HTMLSession用于創(chuàng)建連接,獲取網(wǎng)頁數(shù)據(jù)。第二段創(chuàng)建連接,獲取了我的簡書用戶頁面。第三段用xpath語法獲取了網(wǎng)頁上的用戶名,最后打印出來。
from requests_html import HTMLSession
session=HTMLSession()
response=session.get(
'https://www.jianshu.com/u/7753478e1554')
username=response.html.xpath(
'//a[@class="name"]/text()', first=True)
print(username)
看起來是不是很簡單?沒錯,確實(shí)很簡單,接下來還有一些更加有趣的功能。
編寫爬蟲之前還要做一件事情,就是分析網(wǎng)頁的結(jié)構(gòu)。這個工作其實(shí)也很簡單,打開你要訪問的網(wǎng)頁,按F12打開開發(fā)人員工具,可以看到最左邊有這么一個按鈕。點(diǎn)擊這個按鈕,然后點(diǎn)擊網(wǎng)頁上你想要查看的網(wǎng)頁元素,然后你就可以發(fā)現(xiàn)這個元素對應(yīng)的相關(guān)源代碼已經(jīng)為你定位完畢了。
定位按鈕
通過這個功能,我們就可以輕松的分析網(wǎng)頁,然后通過它的結(jié)構(gòu)來編寫爬蟲了。
上面的response.html即是網(wǎng)頁的根節(jié)點(diǎn)HTML節(jié)點(diǎn),在節(jié)點(diǎn)對象上可以調(diào)用一些方法來檢索數(shù)據(jù)。最常用的方法是find方法,它通過CSS選擇器來定位數(shù)據(jù)。對于上面的例子,可以用find方法改寫第三段。
因?yàn)樗胁檎曳椒ǚ祷氐慕Y(jié)果都是列表,所以如果你確定只需要查找一個,就將first參數(shù)設(shè)為真來只返回第一個結(jié)果。find方法返回的仍然是一個節(jié)點(diǎn),如果只需要節(jié)點(diǎn)的內(nèi)容,調(diào)用其text屬性即可。
用戶名對應(yīng)的HTML結(jié)構(gòu)如圖所示。
代碼如下。
username = response.html.find('a.name', first=True).text
除了find方法之外,還可以使用xpath方法用xpath語法來查找節(jié)點(diǎn),正如第一個例子那樣。我個人比較喜歡xpath語法,CSS選擇器雖然更加流行一些,但是寫出來的效果有點(diǎn)怪,不如xpath工整。
同樣是這個頁面,看看如何獲取我的簡書的個人簡介。網(wǎng)頁代碼如圖所示。
代碼如下。
description=response.html.xpath(
'//div[@class="description"]/div[@class="js-intro"]/text()', first=True)
CSS選擇器和XPATH語法都不是本篇的主要內(nèi)容,如果你這方面不太熟悉,最好去看一下相關(guān)的教程。當(dāng)然如果大家有什么疑問的話,也可以提出來。假如大家想看的話,我也可以專門寫一篇文章介紹一下這些語法知識。
有些網(wǎng)頁利用了前后端分離技術(shù)開發(fā)的,需要瀏覽器渲染才能完整顯示。如果用爬蟲去看的話,只能顯示一部分內(nèi)容。這時(shí)候就需要瀏覽器渲染頁面,才能獲取完整的頁面。用requests-html的話,這個過程非常簡單。
首先先來看看一個需要渲染網(wǎng)頁的例子。下面的代碼訪問了我的簡書用戶頁面,然后嘗試獲取我的所有文章。但是如果你運(yùn)行這個例子的話,就會發(fā)現(xiàn)只能獲取前幾項(xiàng)。因?yàn)楹啎捻撁嬲且粋€典型的需要瀏覽器渲染的頁面,爬蟲獲取到的網(wǎng)頁是不完整的。
from requests_html import HTMLSession
session=HTMLSession()
headers={
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.119 Safari/537.36'
}
url='https://www.jianshu.com/u/7753478e1554'
r=session.get(url, headers=headers)
for a in r.html.xpath('//ul[@class="note-list"]/li/div[@class="content"]/a[@class="title"]'):
title=a.text
link=f'https://www.jianshu.com{a.attrs["href"]}'
print(f'《{title}》,{link}')
那么如何渲染網(wǎng)頁來獲取完整的結(jié)果呢?其實(shí)非常簡單,在查詢HTML節(jié)點(diǎn)之前,調(diào)用render函數(shù)即可。
render函數(shù)來使用瀏覽器渲染
原理也非常簡單,第一次調(diào)用render的時(shí)候,requests-html會在本地下載一個chromium瀏覽器,用它來渲染網(wǎng)頁。如此一來,我們就可以獲取到渲染之后的頁面了。
但是對于簡書這個例子來說還是有些問題,因?yàn)槿绻阍跒g覽器里打開這個網(wǎng)頁的話,會發(fā)現(xiàn)一些文章在瀏覽器下滑頁面的時(shí)候才開始渲染。不過聰慧的作者早就考慮到這種情況了,render函數(shù)支持下滑的參數(shù),設(shè)定之后,就會模擬瀏覽器下滑操作,從而解決了這個問題。
r.html.render(scrolldown=50, sleep=0.2)
不論上面的r.html還是find/xpath函數(shù)返回的結(jié)果,它們都是節(jié)點(diǎn)對象。除了上面介紹的幾個提取數(shù)據(jù)的方法以外,節(jié)點(diǎn)對象還有以下一些屬性,在我們提取數(shù)據(jù)的時(shí)候也有很大作用。
相較于專業(yè)的爬蟲框架scrapy,或者僅用于解析XML的解析庫BeautifulSoup。requests-html可以是說恰到好處,它沒有前者那么難學(xué),也不像后者還需要搭配HTTP請求庫才能使用。如果你手頭需要臨時(shí)抓取幾個網(wǎng)頁,那么requests-html就是你最好的選擇。
*請認(rèn)真填寫需求信息,我們會在24小時(shí)內(nèi)與您取得聯(lián)系。