[記錄][python]python爬蟲,下載某圖片網站的全部圖集

  

隨筆僅用於學習交流,轉載時請註明出處,http://www.cnblogs.com/CaDevil/p/5958770.html

 

  該隨筆是記錄個人第一個python程序,一個爬去指定圖片站點的全部圖集,如今仍是一個很是簡陋的單線程程序。下一步是改寫成多線程,雖然python多線程被詆譭得一塌糊塗。同時加上異常處理。html

  近來練習python程序,仿照別人的爬蟲寫一個本身的爬蟲來練練手。在編寫的過程當中遇到各類問題,中文編碼、請求不到html等問題。撰寫該隨筆的目的是將所遇到的問題記錄下來,並提供相應的解決方法。固然這些解決方法是參照其餘人提供的,東抄抄西抄抄,^_^。python

   先大體描述下代碼過程當中遇到的問題: 隨筆僅用於學習交流,轉載時請註明出處,http://www.cnblogs.com/CaDevil/p/5958770.html 服務器

  •  html中文解碼

  雖然beautifulsoup默認的編碼方式是utf-8,並且國內部分站點的編碼方式是utf-8。仍是須要手工設置一下中文的編碼方式。多線程

  在BeautifulSoup中手工設置編碼方式以下所示app

encoding = "gb18030"
soup = BeautifulSoup(html,from_encoding=encoding)  

  

  •  list的append和extend使用 隨筆僅用於學習交流,轉載時請註明出處,http://www.cnblogs.com/CaDevil/p/5958770.html

  查詢相關資料,list中的append是向list插入一個值,extend則是將一個list插入另外一個list中;dom

  若要將list1併入list2中,則使用list2.extend(list1);ide

  若向list中插入值的話,使用list.append(vale)學習

 

  •  beautifulsoup返回的值,能夠直接查找符合條件的節點

   beautifulsoup返回的值是一顆語法樹,結果與html dom結構差很少[這個地方有些保留,我目前不是太瞭解dom結構],經過find和find_all去查找相應的標籤。前者返回一個標籤的對象,後者返回list,該list的值是多個對象。編碼

 

  •  將urllib.urlretrieve()儘可能假裝成一個用戶。

  使用 urlretrieve以前,將發送的http請求作些簡單的假裝,儘可能假裝成爲一個用戶,避免站點不響應下載請求。若不設置的話,經過wireshark,能夠查看到下載請求的user-agent的值與python有關,服務器可能會將下載請求給忽略掉。同時還能夠添加上referer,有些站點經過referer來判斷盜鏈。若不設置的話,下載的圖片全是防盜鏈提示圖片。 隨筆僅用於學習交流,轉載時請註明出處,http://www.cnblogs.com/CaDevil/p/5958770.html url

        #假裝一下下載的http請求,不然有些站點不響應下載請求。
        #不設置的話,下載請求中的user-agent爲python+版本號
        urllib.URLopener.version = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36 SE 2.X MetaSr 1.0'
        #下載圖片到指定目錄中,保留圖片在服務器上的文件名
        urllib.urlretrieve(imgurl,downloadpath)

  

  廢話有些多,上代碼。爲了不宣傳圖片站點的嫌疑,不放該站點的連接。 代碼僅用於學習交流。

import urllib2
import io
import random
import urllib
from bs4 import BeautifulSoup
import re
import os

import sys
reload(sys)
sys.setdefaultencoding('utf8')

def getHtml(url):
    #儘量讓爬蟲顯示爲一個正經常使用戶。若不設置,則發送的請求中,user-agent顯示爲Python+版本
    user_agent = [
        'Mozilla/5.0 (Windows NT 5.2) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.122 Safari/534.30',
        'Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0',
        'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET4.0E; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C)',
        'Opera/9.80 (Windows NT 5.1; U; zh-cn) Presto/2.9.168 Version/11.50',
        'Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1',
        'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET4.0E; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C)'        
    ]
    #設置網頁編碼格式,解碼獲取到的中文字符
    encoding = "gb18030"
    #構造http請求頭,設置user-agent
    header = {"User-Agent":random.choice(user_agent)}
    #構造發送請求
    request = urllib2.Request(url,headers=header)
    #發送請求,獲取服務器響應回來的html頁面
    html = urllib2.urlopen(request).read()
    #使用beautifulSoup處理的html頁面,相似dom
    soup = BeautifulSoup(html,from_encoding=encoding)
    return soup

# 獲取整個站點全部圖集的頁碼
def getPageNum(url):
    soup = getHtml(url)
    # 直接在站點首頁獲取全部圖集的總頁碼
    nums=soup.find_all('a',class_='page-numbers')
    # 除掉「下一頁」的連接,並獲取到最後一頁
    totlePage = int(nums[-2].text)
    return totlePage

#獲取指定頁面下圖集名稱和連接
def getPicNameandLink(url):
    
    soup = getHtml(url)
    meun = []
    #相似html dom對象,直接查找id爲「pins」的ul標籤,返回的結果是一個dom對象
    targetul = soup.find("ul",id="pins")
    if targetul:    
        #獲取該ul下全部的超連接,返回值的類型是list,find_all中第二個參數表示某個指定標籤的屬性
        pic_list = targetul.find_all("a",target="_blank")
        if pic_list:
           # 遍歷全部指定的標籤a
            for pic in pic_list:
                #獲取圖集的連接
                link = pic["href"]
                picturename = ""
                #找到標籤a中,「class」爲「lazy」的img標籤。
                #find中,第二個參數表示某個指定標籤的屬性。
                #在python中class是保留字,全部標籤的class屬性的名稱爲「class_」
                img = pic.find("img",class_='lazy')
                if img:
                    # 保證中文字符可以正常轉碼。
                    picturename = unicode(str(img["alt"]))
                else:
                    continue
                #插入圖集名稱和對應的url
                meun.append([picturename,link])    
        
        return meun
    return None

#function獲取全部的圖集名稱
def getallAltls(url):
    totalpage = getPageNum(url)
    #獲取首頁中全部的圖集名稱。首頁的url和其餘頁面不一樣,沒有page
    meun = getPicNameandLink(url)
    #循環遍歷全部的圖集頁面,獲取圖集名稱和連接
    for pos in range(2,totalpage):
        currenturl = url + "/page/" + str(pos)
        #getPicNameandLink()返回的值是一個list。
        #當一個list插入到另外一個list中時,使用extend。
        #如果插入一個值時,能夠用append
        meun.extend(getPicNameandLink(currenturl))
    
    return meun
    
# 獲取從首頁到指定頁面全部的圖集名稱和連接
def getparAltls(url,page):
    meun = getPicNameandLink(url)
        
    for pos in range(2,page):
        currenturl = url + "/page/" + str(pos)
        meun.extend(getPicNameandLink(currenturl))
        
    return meun

#獲取單個相冊內圖片頁碼
def getSinglePicNum(url):
    soup = getHtml(url)
    #pagenavi仍是一個對象(Tag),能夠經過find_all找出指定標籤出來
    pagenavi = soup.find("div",class_="pagenavi")
    pagelink = pagenavi.find_all("a")
    
    num = int(pagelink[-2].text)
    return num


#下載單個相冊中的全部圖片
def getSinglePic(url,path):
    totalPageNum = getSinglePicNum(url)
    #從第一頁開始,下載單個圖集中全部的圖片
    #range()第二個參數是範圍值的上限,循環時不包括該值
    #須要加1以保證讀取到全部頁面。
    for i in range(1,totalPageNum + 1):
        currenturl = url + "/" + str(i)
        downloadpic(currenturl,path)
       
#下載單個頁面中的圖片 
def downloadpic(url,path):
    soup = getHtml(url)
    #找出指定圖片所在父容器div
    pageimg = soup.find("div",class_="main-image")
    
    if pageimg:
        #找出該div容器中的img,該容器中只有一個img
        img = pageimg.find("img")
        #獲取圖片的url
        imgurl = img["src"]
        #獲取圖片的文件名
        restring = r'[A-Za-z0-9]+\.jpg'
        reimgname = re.findall(restring,imgurl)
        
        #將圖片保存在指定目錄下
        path = str(path)
        if path.strip() == "":
            downloadpath = reimgname[0]
        else:
            downloadpath = path + "/" + reimgname[0]
        #假裝一下下載的http請求,不然有些站點不響應下載請求。
        #不設置的話,下載請求中的user-agent爲python+版本號
        urllib.URLopener.version = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36 SE 2.X MetaSr 1.0'
        #下載圖片到指定目錄中,保留圖片在服務器上的文件名
        urllib.urlretrieve(imgurl,downloadpath)
    
def downimgofsite(url,path = ""):
    
    path = str(path)
    #獲取全部圖集的名稱和連接
    meun_list = getallAltls(url)
    directorypath = ""
    
    for meun in meun_list:
        directoryname = meun[0]
        if path.strip() != "":
            directorypath = path + "/" + directoryname
        else:
            directorypath = os.getcwd + "/" + directoryname
        
        if not os.path.exists(directorypath):
            os.makedirs(directorypath)
        
        getSinglePic(meun[1], directorypath)
        

if __name__ == "__main__":
   
    
   # page = 8
    url = "XXXXX"
    menu = getallAltls(url)
    #menu = getparAltls(url, page)  
    
    f = open("tsts.txt","a")
    for i in menu:
        f.write(str(unicode(i[0]))+"\t"+str(i[1])+"\n")
    f.close()
       
    
View Code
相關文章
相關標籤/搜索