1. 程式人生 > >Python 基礎爬蟲簡介(測試環境為 Python 2.7)

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程式所在的目錄下。可能之後大家用的時候發現不好使了,那是因為網站維護者變更了某些元素、標籤什麼的,到時候我門需要對應的修改下程式碼,才能更好的工作。
再再說一句,為了簡化程式碼,我將程式碼中的各種判斷異常的語句都去掉了,大家一定要注意啊,特別是建立目錄的時候,如果目錄已經存在,程式執行就會出錯的,所以大家用的時候,只需要新增上相應的判斷語句就好啦。