網路爬蟲的大體流程其實就是解析網頁,爬取網頁,儲存資料。三個方法,就完成了對網頁的爬取,並不是很困難。以下是自己對流程的一些理解和總結,如有錯誤,歡迎指正。
首先,我們要了解我們要爬取的網頁,以豆瓣為例,我們要了解模擬瀏覽器頭部資訊,來偽裝成瀏覽器。以及爬取的內容是什麼,方便我們在後面爬取的過程中用正規表示式匹配內容,以便爬取。
首先我們開啟我們需要爬取的網頁,f12開啟開發者模式,在network中找到發出的請求,獲取我們想要的頭部資訊。
其中模擬瀏覽器的頭部資訊我們通常使用urllib庫,主要是裡面的request類。我們先定義一個物件req,然後獲取其中的頭部資訊,用urllib.request.Request方法對獲取的頭部資訊進行封裝並儲存到req物件中,程式碼如下:
req = urllib.request.Request(url=url,data=data,headers=headers,method="POST")
然後再用urllib.request.urlopen獲取網頁原始碼,程式碼如下
response = urllib.request.urlopen(req)
之後再設定一個物件進行儲存,程式碼如下:
html = response.read().decode("utf-8")
總體程式碼:
import urllib.request
import urllib.parse
url = "http://httpbin.org/post"
data = bytes(urllib.parse.urlencode({"name":"eric"}),encoding='utf-8')
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.50",
"X-Amzn-Trace-Id": "Root=1-63f48078-2f75544f15e5c54a7b905e25"
}
req = urllib.request.Request(url=url,data=data,headers=headers,method="POST")
response = urllib.request.urlopen(req)
#print(response.read().decode("utf-8"))
html = response.read().decode("utf-8")
因為我們爬取的網頁不止一頁,例如爬取豆瓣影視top250,京東評論,這些都會分頁,我們爬取會連續爬取很多頁,所以我們通常將這一步設為一個方法askUrl(),用於獲取單個指定url網頁的內容。另外,有些網頁會有相應的防禦措施,我們有可能會爬取失敗,所以,我們通常會try catch來保證程式碼能夠執行,整體程式碼如下:
def askUrl(url):
head = { #模擬瀏覽器頭部資訊,向豆瓣伺服器傳送訊息
"User-Agent": "Mozilla / 5.0(Linux; Android 6.0; Nexus 5 Build / MRA58N) AppleWebKit / 537.36(KHTML, like Gecko) Chrome / 110.0.0.0 Mobile Safari / 537.36 Edg / 110.0.1587.50"
}
#使用者代理:告訴豆瓣伺服器我們是什麼型別的機器、瀏覽器,本質上是告訴伺服器,我們可以接受什麼樣的檔案內容
request = urllib.request.Request(url,headers=head)
html = ""
try:
response = urllib.request.urlopen(request)
html = response.read().decode("utf-8")
# print(html)
except urllib.error.URLError as e:
if hasattr(e,"code"):
print(e.code)
if hasattr(e,"reason"):
print(e.reason)
return html
另外,我們還要在網頁中找到我們需要爬取內容的標籤,同樣是開發者模式,點選箭頭,在網頁中選取要爬取的內容,在最下面就能看到所在的標籤層次。如下圖:
現在我們有了網頁的原始碼,但是我們想要的只是網頁內容的一部分,這時我們就需要解析網頁的資料,利用正規表示式匹配我們想要的內容,並將其儲存下來。這時我們主要用到bs4中的BeautifulSoup庫。我們首先定義一個物件soup,利用BeautifulSoup解析我們上一步獲得的網頁原始碼,並儲存在soup中,程式碼如下:
soup = BeautifulSoup(html,"html.parser")
隨後我們利用findall方法,查詢符合要求的字串。因為網頁大多是一個個div的組合,而且爬取的第一頁和之後的頁數都有一定的共性,所以我們直接for迴圈來爬取。這個時候就要我們自己上一步找所在的標籤了。這裡我用爬取豆瓣舉例,我先定義變數,再利用compile方法獲取想要內容的正規表示式並儲存在變數中。
#影片詳情的規則
findLink = re.compile(r'<a href="(.*?)"')
又因為爬取的內容比較多,所以我們設定getData方法,在方法中我們先定義一個列表,用來儲存我們爬取的資料,然後爬取一頁資料,放到for迴圈中爬取需要的頁數。
#影片詳情的規則
findLink = re.compile(r'<a href="(.*?)"')
#影片圖片的規則
findImgSrc = re.compile(r'<img.*src="(.*?)"',re.S)
def getData(baseurl):
datalist = []
for i in range(0,10):
url = baseurl + str(i * 25)
html = askUrl(url)
# 2.逐一解析資料
soup = BeautifulSoup(html,"html.parser")
for item in soup.find_all("div",class_ = "item"): #查詢符合要求的字串,形成列表
# print(item) #測試:檢視電影item全部資訊
# break
data = []
item = str(item)
#影片詳情的連結
link = re.findall(findLink,item)[0] #re庫通過正規表示式查詢指定的字串
data.append(link) #新增連結
imgSrc = re.findall(findImgSrc,item)[0]
data.append(imgSrc) #新增圖片
datalist.append(data) #把處理好的一部電影資訊放入dataList
# print(datalist)
return datalist
這裡巢狀了for迴圈語句,實戰中如何巢狀來爬取需要的內容我認為是個難點,這裡需要我們多注意,多思考。
我們可以將資料儲存到excel和資料庫中,我以excel來舉例,其實都是大同小異。其中excel需要xwlt庫,我們先建立workbook物件,再利用其建立工作表:
workbook = xlwt.Workbook(encoding="utf-8",style_compression=0)
worksheet = workbook.add_sheet("豆瓣電影top250",cell_overwrite_ok=True)
然後我們在工作表中寫入資料:
col = ("電影詳情連結","圖片連結","影片中文名","影片外國名","評分","評價數","概況","相關資訊")
for i in range(0,8):
worksheet.write(0,i,col[i]) #列名
for i in range(0,250):
print("第%d條"%(i+1))
data = datalist[i]
for j in range(0,8):
worksheet.write(i+1,j,data[j])
這邊需要注意的是,如果儲存到資料庫中,將內容轉換切割又是一個難點,也需要我們多注意,多思考。之後我們儲存資料表即可:
workbook.save(savepath)
通常我們把儲存資料單獨寫成一個方法,方便程式碼觀看和重用。
我們在main方法中執行前面三個方法即可,我們就爬取了我們想要的內容。爬取的流程並不難理解,其中的難點在於對爬取內容的處理,例如如何找到爬取內容,如何匹配,如何分割儲存。另外想要看原始碼的可以看我這一篇部落格:
手把手教你網路爬蟲(爬取豆瓣電影top250,附帶原始碼)
兩篇部落格一起學習分析,才能更好的理解掌握,如果對程式碼中用的方法不理解,可以看我分類中python+爬蟲學習的模組,裡面記錄了我學習的過程和程式碼講解。還有我學習是看的b站課程:
Python課程天花板,Python入門+Python爬蟲+Python資料分析5天專案實操/Python基礎.Python教學,老師講的比我的部落格要細緻很多,我的部落格只是自己的總結理解,與大家交流學習。