[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/)        

相关文章
相关标签/搜索