Python 基礎爬蟲簡介(測試環境為 Python 2.7)
1、什麼是爬蟲?
爬蟲是一種自動訪問網際網路,並提取資料的一個程式。歸根結底,所謂爬蟲,不過是我們用Python語言編寫的一個小程式而已。
針對的問題:有些網頁需要我們登陸後才能訪問,而有些網頁則不需要。動態登陸頁面由Ajax非同步載入實現,往往針對此類頁面的抓取較為複雜。本例只是針對於一些不需要登入的靜態網頁的抓取。
2、實現一個簡單的爬蟲,需要以下幾個方面:
(1)、 爬蟲的排程端:用來啟動爬蟲、終止爬蟲或監視爬蟲的執行情況。
(2)、 URL管理器:來對將要爬取的URL和已經爬取過的URL進行管理。從URL管理器中我們可以取得一個待爬取的URL將其傳送給網頁下載器。
(3)、 網頁下載器:將指定的URL下載下來,儲存為一個本地檔案或字串。這個字串或本地檔案(其實還是一個字串)將會被傳送給網頁解析器進行解析。
(4)、 網頁解析器:網頁解析器能解析出網頁中有價值的資料資訊,並且每一個網頁中又包含了許多指向其他網頁的URL,這些URL被解析出後,可以補充到我們的URL管理器中。
URL管理器、網頁下載器和網頁解析器形成一個迴圈,只有有相關聯的URL存在,便可以一直執行下去。
這個簡單的爬蟲程式的執行過程是怎樣的呢,我們可以簡單的看一下。
這裡用的是
Beautiful Soup是一個可以從HTML或XML檔案中提取資料的Python庫.它能夠通過你喜歡的轉換器實現慣用的文件導航,查詢,修改文件的方式.Beautiful Soup會幫你節省數小時甚至數天的工作時間。
Soup.find(引數1,引數2,引數3)方法。
Soup.findAll(引數1,引數2,引數3)方法。
兩者的引數是一樣的,find方法,只會搜尋出滿足第一個要求的節點,findAll方法會搜尋出所有滿足要求的節點。搜尋到節點之後,我們就可以訪問節點的名稱、屬性和文字。
我們在搜尋時,我們可以通過節點的名稱進行搜尋,也可以通過節點的屬性和文字進行搜尋。
================================================================
urllib和urllib2。
urllib可以用來提供了urllib.urlretrieve(url,path,callBackFunc)方法,可以將遠端伺服器上的資源下載到本地。
urllib2可以用來接受Request物件作為引數,從而可以控制HTTP Request的header部。但是有些功能模組卻是隻有urllib獨有,所有我們經常可以看到urllib與urllib2共存在一個專案中。
本例中,所有的程式碼均為個人純手打,如有雷同,純屬巧合。先附上一張程式執行的效果圖。(不能超過2M,真惱人!)
詳細程式碼如下:
# -*- coding: cp936 -*-
from bs4 import BeautifulSoup # 網頁解析
import urllib # 資源下載
import urllib2 # 網頁讀取
import re # 正則匹配所需要
import os # 系統庫
import time # 時間庫
i = 0 # 表示下載的時第幾張圖片
def getHtml(url):
# headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0)Gecko/20100101 Firefox/23.0'} #偽造HTTP報頭
# 針對很多網站,為了防止爬蟲,會拒絕爬蟲請求,這時候就需要我們去偽造http中的Header項了
# Header不會寫的可以上網上找一個,一般是可以用的
send_headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 6.2; rv:16.0) Gecko/20100101 Firefox/16.0',
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Connection':'keep-alive'
}
urls = urllib2.Request(url,headers=send_headers)
html = urllib2.urlopen(urls) # urllib.urlopen實際上返回一個類似檔案的物件
if html.getcode() == 200:
print ("已捕獲"),url,"目標站資料..."
return html
else:
print ("訪問出現錯誤...錯誤程式碼:"),html.getcode()
return None
def callBackFunc(block_Num,block_Size,total_Size):
"""
回撥函式
@block_Num: 已經下載的資料塊
@block_Size: 資料塊的大小
@total_Size: 遠端檔案的大小
"""
download_Percent = 100.0 * block_Num * block_Size / total_Size
if download_Percent > 100:
download_Percent = 100
print "正在下載第",i,"張圖片,已下載 %",download_Percent
if __name__ == '__main__': # 主函式
# 先將所有的目錄建立,與此同時儲存她們的URL指向
# 入口URL:https://www.mmonly.cc/gqbz/fjbz/ #唯一相簿之風景桌布
# 目錄URL格式:(https://www.mmonly.cc/gqbz/fjbz/129331.html)
# https://www.mmonly.cc/gqbz/fjbz/129268.html
"""<a target="_blank" href="https://www.mmonly.cc/gqbz/fjbz/129331.html">
<img width="234" alt="風景桌面桌布高清電腦圖片" src="https://t1.mmonly.cc/uploads/tu/201612/23/25.png"
original="https://t1.mmonly.cc/uploads/tu/201612/23/25.png">
</a>
"""
gate_URL = "https://www.mmonly.cc/gqbz/fjbz/" # 入口URL
html = getHtml(gate_URL) # 獲得目標網頁
html_Doc = html.read()
if html != None:
"""https://www.zhihu.com/question/19696249
----知乎 如何解決用 Beautiful Soup 抓取網頁卻得到亂碼的問題?
"""
soupHtml = BeautifulSoup(html_Doc,"lxml",from_encoding = "gb18030") #解析html,返回html的解析物件,編碼問題,臥槽!!!
# <div class="item_list infinite_scroll masonry" id="infinite_scroll">
# <img width="234" alt="電腦桌面桌布高清風景圖片" src="https://t1.mmonly.cc/uploads/tu/201612/47/47.png"
# original="https://t1.mmonly.cc/uploads/tu/201612/47/47.png">
divs = soupHtml.findAll('div', class_="ABox")
flag = 1
for div in divs:
#找到所有的div標籤後
div_Doc = str(div)
soupDiv = BeautifulSoup(div_Doc,"lxml",from_encoding = "gb18030")
if soupDiv.find('img') != None: # 從中篩選出我們需要的資料資訊
tag_img = soupDiv.find('img')
#filename = tag_img['alt'] # 指定資料夾名稱,亂碼問題,真心難倒我啦,,,,換個名字吧
filename = "Background"+str(time.time())
tag_a = soupDiv.find('a')
img_direction_url = tag_a['href']
os.mkdir(filename) # 建立目錄
print "已建立目錄"
print filename
print "開始下載資源..."
img_Html = getHtml(img_direction_url) # 進入圖片目錄下
img_Doc = img_Html.read()
#<li id="nl"><a href="130130_3.html">下一頁</a></li>
while True:
i = i + 1
soup_Img_Doc = BeautifulSoup(img_Doc,"lxml",from_encoding = "gb18030")
#<li class="pic-down h-pic-down"><a target="_blank" class="down-btn"
#href="https://t1.mmonly.cc/uploads/tu/201612/47/1-160320194503.jpg">檢視原圖</a></li>
download_btn = soup_Img_Doc.find('a',class_="down-btn")
img_url = download_btn['href']
print "需要下載的圖片URL",img_url
_path_ = os.path.abspath(filename) # 指定建立的資料夾路徑
path = os.path.join(_path_,img_url[-6:]) # 圖片的完整路徑
urllib.urlretrieve(img_url,path,callBackFunc)
if i == 3: # 如過下載完畢,就返回
break
else:
#https://www.mmonly.cc/gqbz/fjbz/130130.html
img_Tag_a = soup_Img_Doc.find('a',href=re.compile(r"\d_?.html"))
#print "img_Tag_a的內容:",img_Tag_a
#print "img_Tag_a的href屬性值為: ",img_Tag_a['href']
img_direction_url = "https://www.mmonly.cc/gqbz/fjbz/"+img_Tag_a['href']
img_Html = getHtml(img_direction_url)
img_Doc = img_Html.read()
i = 0
else:
print ("獲取失敗...")
我指出這裡的幾個問題:
首先,我爬取的這個網頁是唯1相簿-風景桌布 大家在使用時一定要注意網頁的編碼格式,python 2.7對中文的支援實在讓我很難受,可能時這個例子不是很好的原因就在於這個網址是用gb2312編碼的。
其次就是我只是爬取了部分資源,因為全部下載的話,時間太久了,這個專案只是給大家入個門,瞭解一下python爬蟲的基本概念久很成功啦。
最後就是我附上的原始碼只要執行後,就可以將網頁上的圖片下載到該python程式所在的目錄下。可能之後大家用的時候發現不好使了,那是因為網站維護者變更了某些元素、標籤什麼的,到時候我門需要對應的修改下程式碼,才能更好的工作。
再再說一句,為了簡化程式碼,我將程式碼中的各種判斷異常的語句都去掉了,大家一定要注意啊,特別是建立目錄的時候,如果目錄已經存在,程式執行就會出錯的,所以大家用的時候,只需要新增上相應的判斷語句就好啦。