[python爬蟲] Selenium定向爬取海量精美圖片及搜索引擎雜談

        我自認爲這是本身寫過博客中一篇比較優秀的文章,同時也是在深夜凌晨2點滿懷着激情和愉悅之心完成的。首先經過這篇文章,你能學到如下幾點:
        1.能夠了解Python簡單爬取圖片的一些思路和方法
        2.學習Selenium自動、測試分析動態網頁和正則表達式的區別和共同點
        3.瞭解做者最近學習得比較多的搜索引擎和知識圖譜的總體框架
        4.同時做者最近找工做,裏面的一些雜談和建議也許對即將成爲應屆生的你有所幫助
        5.固然,最重要的是你也能夠嘗試使用這個爬蟲去爬取本身比較喜歡的圖片
        總之,但願文章對你有所幫助。若是做者又不足之處或錯誤的地方,還請海涵~

javascript

一. Python定向爬取海量圖片

        運行效果以下圖所示:
        這是從遊訊圖庫中爬取圖片(很是不錯的網站,推薦你們去瀏覽),其它網站方法相似去修改。運行py文件後,輸入「極品飛車」能夠爬取主題相關的圖集。css

        程序源代碼以下圖所示:html

  1 # -*- coding: utf-8 -*-
  2 """
  3 Crawling pictures by selenium and urllib
  4 url: http://pic.yxdown.com/list/0_0_1.html
  5 Created on 2015-10-02 @author: Eastmount CSDN 
  6 """  
  7   
  8 import time          
  9 import re          
 10 import os  
 11 import sys
 12 import urllib
 13 import shutil
 14 import datetime
 15 from selenium import webdriver      
 16 from selenium.webdriver.common.keys import Keys      
 17 import selenium.webdriver.support.ui as ui      
 18 from selenium.webdriver.common.action_chains import ActionChains  
 19   
 20 #Open PhantomJS  
 21 driver = webdriver.PhantomJS(executable_path="G:\phantomjs-1.9.1-windows\phantomjs.exe")  
 22 #driver = webdriver.Firefox()
 23 wait = ui.WebDriverWait(driver,10)  
 24 
 25 #Download one Picture
 26 def loadPicture(pic_url, pic_path):
 27     pic_name = os.path.basename(pic_url) #delete path, get the filename
 28     urllib.urlretrieve(pic_url, pic_path + pic_name)
 29 
 30 #Visit the picture page and get <script>(.*?)</script>  original
 31 def getScript(elem_url,path):
 32     print elem_url
 33     print path
 34     '''
 35     #Error: Message: Error Message => 'Element does not exist in cache'
 36     driver.get(elem_url)
 37     pic_url = driver.find_element_by_xpath("//div[@id='wrap']/div/div[2]/a")
 38     print pic_url.text
 39     '''
 40     #By urllib to download the original pics
 41     count = 1
 42     html_content = urllib.urlopen(elem_url).read()
 43     html_script = r'<script>(.*?)</script>'
 44     m_script = re.findall(html_script,html_content,re.S|re.M)
 45     for script in m_script:
 46         res_original = r'"original":"(.*?)"' #原圖
 47         m_original = re.findall(res_original,script)
 48         for pic_url in m_original:
 49             loadPicture(pic_url, path)
 50             count = count + 1
 51     else:
 52         print 'Download ' + str(count) + ' Pictures'
 53     
 54 #Get the Title of the URL
 55 def getTitle(key, url):
 56     try:
 57         #print key,type(key)
 58         count = 0
 59         print 'Function getTitle(key,url)'
 60         driver.get(url)
 61         wait.until(lambda driver: driver.find_element_by_xpath("//div[@class='masonry']/div/div[2]/a")) 
 62         elem_title = driver.find_elements_by_xpath("//div[@class='masonry']/div/div[2]/a")
 63         for title in elem_title:
 64             #title.text-unicode  key-str=>unicode
 65             #print key,title.text
 66             elem_url = title.get_attribute("href")
 67             if key in title.text:
 68                 #print key,title.text
 69                 path="E:\\Picture_DM\\"+title.text+"\\"
 70                 if os.path.isfile(path):  #Delete file
 71                     os.remove(path)
 72                 elif os.path.isdir(path): #Delete dir
 73                     shutil.rmtree(path,True)
 74                 os.makedirs(path)         #create the file directory
 75                 count = count + 1
 76                 #print elem_url
 77                 getScript(elem_url,path)  #visit pages 
 78                 
 79     except Exception,e:
 80         print 'Error:',e
 81     finally:
 82         print 'Find ' + str(count) + ' pages with key\n'
 83     
 84 #Enter Function
 85 def main():
 86     #Create Folder
 87     basePathDirectory = "E:\\Picture_DM"
 88     if not os.path.exists(basePathDirectory):
 89         os.makedirs(basePathDirectory)
 90 
 91     #Input the Key for search  str=>unicode=>utf-8
 92     key = raw_input("Please input a key: ").decode(sys.stdin.encoding)
 93     print 'The key is : ' + key
 94 
 95     #Set URL List  Sum:1-73 Pages
 96     print 'Ready to start the Download!!!\n\n'
 97     starttime = datetime.datetime.now() 
 98     num=1
 99     while num<=73:
100         url = 'http://pic.yxdown.com/list/0_0_'+str(num)+'.html'
101         print ''+str(num)+'','url:'+url
102         #Determine whether the title contains key
103         getTitle(key,url)
104         time.sleep(2)
105         num = num + 1
106     else:
107         print 'Download Over!!!'
108 
109     #get the runtime
110     endtime = datetime.datetime.now()
111     print 'The Running time : ',(endtime - starttime).seconds
112         
113 main()

        該程序的基本框架以下圖所示:三個圖標Python+Phantomjs+Seleniumjava

        參考:[python學習] 簡單爬取圖片網站圖庫中圖片 其基本步驟爲:
        第一步:循環遍歷圖集列表URL
        main()函數中循環輸入列表url,並調用getTitle(key,url)判斷主題(title)中是否包含輸入的關鍵詞(key),如"極品飛車"。
        這裏由於遊訊圖庫存在第一個BUG,圖集共73頁,url採用順序形式存儲,每頁存在不少主題(title);固然不少網站都是這樣的,如CSDN博客、CSDN下載、搜狐博客等。
        http://pic.yxdown.com/list/0_0_1.html
        http://pic.yxdown.com/list/0_0_73.html

        第二步:經過Selenium和Phantomjs尋找路徑爬取主題和URL
        以下圖所示,在函數getTitle()中經過selenium訪問無界面的瀏覽器Phantomjs,再遍歷HTML的DOM樹結構。python

        其中核心代碼以下:
        driver.find_elements_by_xpath("//div[@class='masonry']/div/div[2]/a")
        它是Selenium按照路徑定位元素,其中DOM樹表示尋找class='masonry'的div,而後是子div,第二個div,最後是<a target='_blank',此處能夠爬取主題title.text和屬性title.get_attribute("href")。對應源碼:程序員

        <div class='masonry'>
        <div class='conbox'>
            <div></div><div class='cbmiddle'>                                                //div[2]
                <a target="_blank"href="/html/6299.html" class="proimg">  //URL
                    <img src="http://yxdown.com/xxx.jpg" alt="...韓國女主播...">
                    <p><span>1440人看過</span> <em>8張</em></p>
                    <b class="imgname">...韓國女主播....</b>                              //主題
                 </a>
            </div>
        </div>
        <div class='conbox'>第二個主題</div>
       <div class='conbox'>第二個主題</div>
           ....
        </div>

        同時獲取的href屬性 自動補齊,如:http://pic.yxdown.com/html/6299.html
        此處的driver.find_elements_by_xpath方法就比傳統的正則表達式好,同時它返回一個List。後面第三部分會詳細介紹下Selenium經常使用的方法。在raw_input輸入關鍵字比較過程當中若是存在中文亂碼問題,參考這篇文章

        第三步:根據主題建立文件夾並去到具體頁面爬取圖片
        經過比較關鍵詞key是否包含在主題title,如"主播"。若是在則建立該文件夾,同時移除同名文件:web

        if os.path.isfile(path):   #Delete file
            os.remove(path)
        elif os.path.isdir(path):#Delete dir
           shutil.rmtree(path,True)
        os.makedirs(path)       #create the file directory

        再調用getScript(elem_url,path)函數去爬取所在頁面的圖集

        第四步:經過正則表達式獲取圖片url
        此時去到具體的圖集如:http://pic.yxdown.com/html/5533.html#p=1
        你有兩種方法獲取圖片,第一種方法是經過Selenium模擬鼠標操做,點擊"查看原圖"再另存爲圖片或者獲取源碼<img src="http://xxx.jpg">屬性,再或者是獲取"查看原圖"的當前url,driver.current_url。
        <a href="javascript:;" onclick="return false;" id="Original">查看原圖</a>
        第二種方法是因爲遊訊圖庫的第二個bug,它把全部圖片都保存在<script></script>,則經過urllib2獲取原圖original便可。
        res_original = r'"original":"(.*?)"' #原圖
        m_original = re.findall(res_original,script)

        第五步:最後調用函數loadPicture(pic_url, pic_path)下載圖片便可正則表達式

def loadPicture(pic_url, pic_path):
    pic_name = os.path.basename(pic_url) 
    urllib.urlretrieve(pic_url, pic_path + pic_name)

 

        總結:
        講到此處,整個爬蟲基本講述完畢。使用Selenium的優勢主要是:DOM樹結構爬取,可能Spider也是採用find_element_by_xpath()方法,都是相似的;第二個優勢是獲取動態JS、AJax的資源或文件。可是正則表達式也有它的好處和方便。
        前面我爲何畫了一副框架圖,主要是最近研究搜索引擎和知識圖譜比較多,因此這幅圖給人更直觀的感受。第二部分會詳細說到。
        同時,你可能會遇到以下錯誤,可能和加載響應有關:算法

 

二. 搜索引擎和知識圖譜雜談

       1.搜索引擎
        下面是《這就是搜索引擎·張俊林》裏面那張經典的框架圖。數據庫

        搜索引擎的一般是用戶輸入查詢詞,搜索引擎返回搜索結果。主要包括流程是:
        搜索引擎後臺計算系統
        搜索引擎的信息來源於互聯網網頁,經過網絡爬蟲將整個互聯網的信息獲取到本地,所以互聯網頁面中有很大部份內容是相同或類似的,「網頁去重」模塊會對此做出檢測並去除重複內容。
        以後,搜索引擎會對網頁進行解析,抽取出網頁主體內容及頁面中包含的指向其餘頁面的連接。爲加快響應用戶查詢的速度,網頁內容經過「倒排索引」這種高效查詢數據結構保存,網頁之間的連接關係也會保存。由於經過「連接分析」能夠判斷頁面的相對重要性,對於爲用戶提供準確的搜索結果幫助很大。
        同時因爲海量數據信息巨大,因此採用雲存儲與雲計算平臺做爲搜索引擎及相關應用的基礎支撐。上述是關於搜索引擎如何獲取及存儲海量的網頁相關信息,不須要進行實時計算,因此被看作是搜索引擎的後臺計算系統。

        搜索引擎前臺計算系統
        搜索引擎的最重要目的是爲用戶提供準確全面的搜索結果,如何響應用戶查詢並實時地提供準確結果構成了搜索引擎前臺計算系統。
        當搜索引擎接到用戶的查詢詞後,首先對查詢詞進行分析,但願可以結合查詢詞和用戶信息來正確推導用戶的真正搜索意圖。先在緩存中查找,緩存系統中存儲了不一樣的查詢意圖對應的搜索結果,若是能在緩存中找到知足用戶需求的信息,則直接返回給用戶,即節省資源又加快響應速度。若是緩存中不存在,則調用「網頁排序」模塊功能。
        「網頁排序」會根據用戶的查詢實時計算哪些網頁是知足用戶信息需求的,並排序輸出做爲搜索結果。而網頁排序中最重要的兩個因素是:內容類似性因素(哪些網頁和用戶查詢相關)和網頁的重要性因素(哪些網頁質量好或相對重要,經過連接分析結果得到)。而後網頁進行排序,做爲用戶查詢的搜索結果。
        同時,搜索引擎的「反做弊」模塊主要自動發現那些經過各類手段將網頁的搜索排名提升到與其網頁質量不相稱的位置,這會嚴重影響搜索體驗。如今也出現一種成功的新互聯網公司屏蔽搜索引擎公司爬蟲的現象,好比Facebook對Google的屏蔽,國內淘寶對百度的屏蔽,主要是商業公司之間的競爭策略,也可看作是垂直搜索和通用搜索的競爭。

        2.知識圖譜
        這是搜狗知立方知識圖譜的框架圖。詳見:文章

        知識圖譜(Knowledge Graph)於2012年5月首先由Google提出,其目標在於描述真實世界中存在的各類實體和概念,及實體、概念之間的關聯關係,從而改善搜索結果。緊隨其後,國內搜狗提出了「知立方」、微軟的Probase和百度的「知心」。其實質就是真正讓計算機去"理解"用戶的需求和搜索意圖。
        知立方數據庫構建包括本體構建(各種型實體挖掘、屬性名稱挖掘、編輯系統)、實例構建(純文本屬性、實體抽取、半結構化數據抽取)、異構數據整合(實體對齊、屬性值決策、關係創建)、實體重要度計算、推理完善數據。

        3.爬蟲框架猜測
        說了這麼多,你是否是還不知道我想表達什麼內容啊?

        我在設想若是上面那個Python圖片爬蟲添加如下幾點:
        (1)圖片來源不是定向的某個網站,而是開放的網絡、圖庫、數據庫
        (2)搜索中加入一些更復雜的搜索,利用一些NLP分詞技術處理
        (3)經過一些類似計算,採用更高效的VSM、聚類、神經網絡、人臉識別等,計算關鍵詞和圖片或標題的類似度,甚至實現百度圖片那種識別某張圖是某某明星
        (4)再創建倒排索引、連接分析加快檢索系統
        (5)海量圖片利用雲計算、雲存儲的支持,採用分佈式並行更高效的操做
        (6)實現圖片智能識別、圖片相關推薦,再根據不一樣用戶的log分析用戶的真正搜索意圖
        經過以上幾點是否是能實現一個智能的圖片知識計算引擎呢?谷歌、百度圖片那些智能應用是否是也是這樣的呢?感受很是有意思啊!
        PS:之後有機會本身研究研究,而且本身再寫一些更強大的智能爬取吧!

 

三. Selenium簡單基礎學習

        前面我在Python爬蟲這個專題中講述了不少關於Selenium的文章,包括爬取百度百科InfoBox、配置安裝過程等。下面是簡單的Selenium定位元素的介紹:
        1.定位元素方法
        官網地址:http://selenium-python.readthedocs.org/locating-elements.html
        這裏有各類策略用於定位網頁中的元素(locate elements),你能夠選擇最適合的方案,Selenium提供了一下方法來定義一個頁面中的元素:

  • find_element_by_id
  • find_element_by_name
  • find_element_by_xpath
  • find_element_by_link_text
  • find_element_by_partial_link_text
  • find_element_by_tag_name
  • find_element_by_class_name
  • find_element_by_css_selector

        下面是查找多個元素(這些方法將返回一個列表):

  • find_elements_by_name
  • find_elements_by_xpath
  • find_elements_by_link_text
  • find_elements_by_partial_link_text
  • find_elements_by_tag_name
  • find_elements_by_class_name
  • find_elements_by_css_selector

        除了上面給出的公共方法,這裏也有兩個在頁面對象定位器有用的私有方法。這兩個私有方法是find_element和find_elements。
        經常使用方法是經過xpath相對路徑進行定位,同時CSS也是比較好的方法。舉例:

[html]  view plain copy
 
  1. <html>  
  2.  <body>  
  3.   <form id="loginForm">  
  4.    <input name="username" type="text" />  
  5.    <input name="password" type="password" />  
  6.    <input name="continue" type="submit" value="Login" />  
  7.    <input name="continue" type="button" value="Clear" />  
  8.   </form>  
  9. </body>  
  10. <html>  

        定位username元素的方法以下:

[python]  view plain copy
 
  1. username = driver.find_element_by_xpath("//form[input/@name='username']")  
  2. username = driver.find_element_by_xpath("//form[@id='loginForm']/input[1]")  
  3. username = driver.find_element_by_xpath("//input[@name='username']")  

        [1] 第一個form元素經過一個input子元素,name屬性和值爲username實現
        [2] 經過id=loginForm值的form元素找到第一個input子元素
        [3] 屬性名爲name且值爲username的第一個input元素

        2.driver接口獲取值
        經過WebElement接口能夠獲取經常使用的值,這些值一樣很是重要。

  • size 獲取元素的尺寸
  • text 獲取元素的文本
  • get_attribute(name) 獲取屬性值
  • location 獲取元素座標,先找到要獲取的元素,再調用該方法
  • page_source 返回頁面源碼
  • driver.title 返回頁面標題
  • current_url 獲取當前頁面的URL
  • is_displayed() 設置該元素是否可見
  • is_enabled() 判斷元素是否被使用
  • is_selected() 判斷元素是否被選中
  • tag_name 返回元素的tagName

        詳見:http://www.cnblogs.com/eastmount/p/4810690.html
        安裝過程:http://blog.csdn.net/eastmount/article/details/47785123

 

四. 找工做雜談:你只是看起來很努力


        最近找工做之餘看了《你只是看起來很努力》,很是喜歡裏面的故事,而這些故事彷彿就是本身的折射,倒映着咱們的身影,在此分享與君卿共勉,但願能引發你的共鳴。
        咱們看起來天天熬夜,卻只是拿着手機點了無數個贊;
        看起來在圖書館坐了一天,卻真的只是坐了一天;
        看起來買了不少書,只不過曬了個朋友圈;
        看起來天天很晚地離開辦公室,上班的時間卻在偷懶;
        那些所謂的努力時光,是真的頭腦風暴了,仍是,只是看起來很努力而已?
        任何沒有計劃的學習,都只是做秀而已;
        任何沒有走心的努力,都只是看起來很努力。
        牢記一句話:「全部的努力都不是給別人看的,不少時候,英雄都是孤獨的」。

        書中第一個故事就是一個女孩垂頭喪氣的對老師說:「老師,我考了四次四級,還沒過,到底是爲何?」看着學生滿滿的筆記,老師心想,看起來很努力啊,沒理由不經過啊!哎,這不就是活生生的本身嗎?本身四級六次才經過,六級還因爲分數過低被禁考。究其緣由…
        咱們總會陷入這樣一個怪圈:看似忙碌,實則焦慮。當咱們心血來潮想學習時,買了不少書,卻再也沒有翻開過;當咱們備受刺激想健身時,因而找了不少攻略,但再也沒有動過;當咱們在社交網絡上花費不少時間把認爲有用的東西另存爲時,直到你的硬盤存得滿滿當當,然而你卻沒有看過。咱們忙碌,卻沒有去了解那些精挑細選留下的內容;咱們花時間收集,卻忘了最重要的實際上是花時間去消化。你將會在一遍遍地逃避和自我安慰中變得惴惴不安,拖延和等待也終將擊垮你的鬥志。這就是我支教時分享過的一句話:「記筆記若是光記不看還不如不記」。
        不要看到別人作什麼好,就去嘗試作什麼,那些看起來的光鮮也有屬於他們本身的苦逼。固然,戰勝焦慮的最好辦法就是去作那些讓你焦慮的事情。但願你看完這幾句話以後,也會有所感悟,真切地作起身邊的每一件事。路仍是要一步步地走,能夠走得很慢,但卻不能中止。

        最近找工做也不是很順利,這也驗證了一點:
        努力的人不少,這個世界最不差的就是優秀的人,尤爲是程序員,除非你無可替代。優秀是不夠的,必定要卓越,多學點拿得出手的東西,不然你只會獲得一句「雖然你很優秀,但你運氣很差,這位置已經有人了」。
        若是你的簡歷上都是些會Java語言、MySQL、HTML、Python等,這並無什麼亮點。還不如:對Java虛擬內核有過研究、熟悉PHP什麼開發框架、MongoDB作過應用、Ajax\JavaScript異步消息傳輸、熟悉Socket\TCP通信、研究過SVM\神經網絡算法等。
         同時能內推的,儘可能找師兄師姐幫忙內推,筆試題目各式各樣,各類基礎並且較深的知識,包括OS、計算機網絡、數據庫、Linux、JavaScript、C++面向對象、算法等,因此推薦內推直接考察你的項目能力。若是實在沒有機會內推,就須要儘早的準備基礎知識,不然你會吃虧。通常8月、9月、10月高峯期,因此暑假6-7月就要開始準備了。同時推薦兩個地方:一個是LeetCode刷題,這個是真心的有用啊!還有一個就是牛客網刷基礎的選擇題。

        再強調一遍:這個世界優秀的人太多,你須要的是卓越!
        其實不論多忙,我都會堅持寫博客,我認爲這個過程並非學習了,而是休息放鬆的過程,並且可以讓我體會到分享的樂趣,很是開心~困得不行了
        總之,但願文章對你有所幫助,若是不喜歡個人這種雜亂的敘述方式,請不要噴我,畢竟花費了本身的一晚上經歷完成,尊重做者的勞動果實吧!歡迎隨便轉載~

       (By:Eastmount 2015-10-2 早上9點 http://blog.csdn.net/eastmount/)        

相關文章
相關標籤/搜索