我自認爲這是本身寫過博客中一篇比較優秀的文章,同時也是在深夜凌晨2點滿懷着激情和愉悅之心完成的。首先經過這篇文章,你能學到如下幾點:
1.能夠了解Python簡單爬取圖片的一些思路和方法
2.學習Selenium自動、測試分析動態網頁和正則表達式的區別和共同點
3.瞭解做者最近學習得比較多的搜索引擎和知識圖譜的總體框架
4.同時做者最近找工做,裏面的一些雜談和建議也許對即將成爲應屆生的你有所幫助
5.固然,最重要的是你也能夠嘗試使用這個爬蟲去爬取本身比較喜歡的圖片
總之,但願文章對你有所幫助。若是做者又不足之處或錯誤的地方,還請海涵~
javascript
運行效果以下圖所示:
這是從遊訊圖庫中爬取圖片(很是不錯的網站,推薦你們去瀏覽),其它網站方法相似去修改。運行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:之後有機會本身研究研究,而且本身再寫一些更強大的智能爬取吧!
前面我在Python爬蟲這個專題中講述了不少關於Selenium的文章,包括爬取百度百科InfoBox、配置安裝過程等。下面是簡單的Selenium定位元素的介紹:
1.定位元素方法
官網地址:http://selenium-python.readthedocs.org/locating-elements.html
這裏有各類策略用於定位網頁中的元素(locate elements),你能夠選擇最適合的方案,Selenium提供了一下方法來定義一個頁面中的元素:
下面是查找多個元素(這些方法將返回一個列表):
除了上面給出的公共方法,這裏也有兩個在頁面對象定位器有用的私有方法。這兩個私有方法是find_element和find_elements。
經常使用方法是經過xpath相對路徑進行定位,同時CSS也是比較好的方法。舉例:
定位username元素的方法以下:
[1] 第一個form元素經過一個input子元素,name屬性和值爲username實現
[2] 經過id=loginForm值的form元素找到第一個input子元素
[3] 屬性名爲name且值爲username的第一個input元素
2.driver接口獲取值
經過WebElement接口能夠獲取經常使用的值,這些值一樣很是重要。
詳見:http://www.cnblogs.com/eastmount/p/4810690.html
安裝過程:http://blog.csdn.net/eastmount/article/details/47785123
(By:Eastmount 2015-10-2 早上9點 http://blog.csdn.net/eastmount/)