1. 程式人生 > 實用技巧 >山東創睦網路科技有限公司:網路爬蟲/相關工具與知識

山東創睦網路科技有限公司:網路爬蟲/相關工具與知識

  • 網路爬蟲

  • 網路爬蟲(web crawler), 以前經常稱為網路蜘蛛(spider), 是按照一定的規則自動瀏覽全球資訊網並獲取資訊的機器人程式(或叫指令碼), 曾經被廣泛的應用於網際網路搜尋引擎. 使用過網際網路和瀏覽器的人都知道, 網頁中除了提供使用者閱讀的文字資訊之外, 還包含一些超連結. 網路爬蟲系統正是通過網頁中的超連結資訊不斷獲得網路上的其他頁面. 正因為如此, 網路資料採集的過程就像一個爬蟲或者蜘蛛在網路上漫遊, 所有才被形象的稱之為網路爬蟲或者網路蜘蛛.

  • 爬蟲的應用領域
  • 在理想的狀態下, 所有的ICP(internet Content Provider) 都應該為自己的網路提供API介面來共享它們允許其他程式獲取的資料, 在這種情況下爬蟲就不是必需品, 國內比較有名的電商平臺(如淘寶, 京東等), 社交平臺(如QQ/微博/微信等)這些網站都提供了自己的Open Api, 但是這類Open Api通常會對可以抓取的資料頻率進行限制. 對於大多數的公司而言, 計時的獲取行業相關資料就是企業生存的重要環節之一, 然而大部分企業在行業資料方面的匱乏是其與生俱來的短板, 合理的利用爬蟲來獲取資料並從中提取出有價值的資訊是至關重要的. 當然爬蟲還有很多重要的應用靈玉, 以下列舉了其中一部分.

  • 1.搜尋引擎
    2.新聞聚合
    3.社交應用
    4.輿情監控
    5.行業資料12345
  • 合法性和背景調研

  • 爬蟲合法性探討
  • 1.網路爬蟲領域目前還屬於拓荒階段,雖然網際網路世界已經通過自己的遊戲規則建立起一定的道德規範(Robots協議,全稱是'網路爬蟲排除標準'),但在法律部分還在建立和完善中,也就是說,現在這個領域暫時還是灰色地帶.
    2.'法不禁止即為許可',如果爬蟲就像瀏覽器一樣獲取的是前端顯示的資料(網頁上的公開資訊),而不是網站後臺的私密敏感資訊,就不太擔心法律法規的約束,因為目前大資料產業鏈的發展速度遠遠超過了法律的完善程度.
    3.在爬取網站的時候,需要限制自己的爬蟲遵守Robots協議,同時控制網路爬蟲程式的抓取資料的速度,在使用資料的時候,必須要尊重網站的智慧財產權(從Web2.0時代開始,雖然Web上的資料很多都是由使用者提供的,但是網站平臺是投入了運營成本的,當用戶在註冊和釋出呢日用時,平臺通常就已經獲取了對資料的所有權,使用權和分發權).如果違反了這些規定,在打官司的時候敗訴機率就非常高.123
  • Rbots.txt檔案
  • 大多數網站都會定義robots.txt檔案, 下面以淘寶的robots.txt檔案為例, 看看該網站對爬蟲有哪些限制

  • User-agent:Baiduspider
    Allow:/article
    Allow:/oshtml
    Disallow:/product/
    Disallow:/

    User-Agent:Googlebot
    Allow:/article
    Allow:/oshtml
    Allow:/product
    Allow:/spu
    Allow:/dianpu
    Allow:/oversea
    Allow:/list
    Disallow:/

    User-agent:Bingbot
    Allow:/article
    Allow:/oshtml
    Allow:/product
    Allow:/spu
    Allow:/dianpu
    Allow:/oversea
    Allow:/list
    Disallow:/

    User-Agent:360Spider
    Allow:/article
    Allow:/oshtml
    Disallow:/

    User-Agent:Yisouspider
    Allow:/article
    Allow:/oshtml
    Disallow:/

    User-Agent:Sogouspider
    Allow:/article
    Allow:/oshtml
    Allow:/product
    Disallow:/

    User-Agent:Yahoo!Slurp
    Allow:/product
    Allow:/spu
    Allow:/dianpu
    Allow:/oversea
    Allow:/list
    Disallow:/

    User-Agent:*
    Disallow:/12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  • 注意上面robots.txt第一段的最後一行, 通過設定’Disallow:/’禁止百度爬蟲訪問除了’Allow’規定頁面外的其他所有頁面. 因此當你在百度搜索’淘寶’的時候, 搜尋結果下方會出現: ‘由於該網站的rebots.txt檔案存在限制指令(限制搜尋引擎抓取). 系統無法提供該頁面的內容描述.’, 百度作為一個搜尋引擎, 至少在表面上遵守了淘寶網的robots.txt協議, 所以使用者不能從百度上搜索到淘寶內部的產品資訊.

      • 網路爬蟲

      • 網路爬蟲(web crawler), 以前經常稱為網路蜘蛛(spider), 是按照一定的規則自動瀏覽全球資訊網並獲取資訊的機器人程式(或叫指令碼), 曾經被廣泛的應用於網際網路搜尋引擎. 使用過網際網路和瀏覽器的人都知道, 網頁中除了提供使用者閱讀的文字資訊之外, 還包含一些超連結. 網路爬蟲系統正是通過網頁中的超連結資訊不斷獲得網路上的其他頁面. 正因為如此, 網路資料採集的過程就像一個爬蟲或者蜘蛛在網路上漫遊, 所有才被形象的稱之為網路爬蟲或者網路蜘蛛.

      • 爬蟲的應用領域
      • 在理想的狀態下, 所有的ICP(internet Content Provider) 都應該為自己的網路提供API介面來共享它們允許其他程式獲取的資料, 在這種情況下爬蟲就不是必需品, 國內比較有名的電商平臺(如淘寶, 京東等), 社交平臺(如QQ/微博/微信等)這些網站都提供了自己的Open Api, 但是這類Open Api通常會對可以抓取的資料頻率進行限制. 對於大多數的公司而言, 計時的獲取行業相關資料就是企業生存的重要環節之一, 然而大部分企業在行業資料方面的匱乏是其與生俱來的短板, 合理的利用爬蟲來獲取資料並從中提取出有價值的資訊是至關重要的. 當然爬蟲還有很多重要的應用靈玉, 以下列舉了其中一部分.

      • 1.搜尋引擎
        2.新聞聚合
        3.社交應用
        4.輿情監控
        5.行業資料12345
      • 合法性和背景調研

      • 爬蟲合法性探討
      • 1.網路爬蟲領域目前還屬於拓荒階段,雖然網際網路世界已經通過自己的遊戲規則建立起一定的道德規範(Robots協議,全稱是'網路爬蟲排除標準'),但在法律部分還在建立和完善中,也就是說,現在這個領域暫時還是灰色地帶.
        2.'法不禁止即為許可',如果爬蟲就像瀏覽器一樣獲取的是前端顯示的資料(網頁上的公開資訊),而不是網站後臺的私密敏感資訊,就不太擔心法律法規的約束,因為目前大資料產業鏈的發展速度遠遠超過了法律的完善程度.
        3.在爬取網站的時候,需要限制自己的爬蟲遵守Robots協議,同時控制網路爬蟲程式的抓取資料的速度,在使用資料的時候,必須要尊重網站的智慧財產權(從Web2.0時代開始,雖然Web上的資料很多都是由使用者提供的,但是網站平臺是投入了運營成本的,當用戶在註冊和釋出呢日用時,平臺通常就已經獲取了對資料的所有權,使用權和分發權).如果違反了這些規定,在打官司的時候敗訴機率就非常高.123
      • Rbots.txt檔案
      • 大多數網站都會定義robots.txt檔案, 下面以淘寶的robots.txt檔案為例, 看看該網站對爬蟲有哪些限制

      • User-agent:Baiduspider
        Allow:/article
        Allow:/oshtml
        Disallow:/product/
        Disallow:/

        User-Agent:Googlebot
        Allow:/article
        Allow:/oshtml
        Allow:/product
        Allow:/spu
        Allow:/dianpu
        Allow:/oversea
        Allow:/list
        Disallow:/

        User-agent:Bingbot
        Allow:/article
        Allow:/oshtml
        Allow:/product
        Allow:/spu
        Allow:/dianpu
        Allow:/oversea
        Allow:/list
        Disallow:/

        User-Agent:360Spider
        Allow:/article
        Allow:/oshtml
        Disallow:/

        User-Agent:Yisouspider
        Allow:/article
        Allow:/oshtml
        Disallow:/

        User-Agent:Sogouspider
        Allow:/article
        Allow:/oshtml
        Allow:/product
        Disallow:/

        User-Agent:Yahoo!Slurp
        Allow:/product
        Allow:/spu
        Allow:/dianpu
        Allow:/oversea
        Allow:/list
        Disallow:/

        User-Agent:*
        Disallow:/12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
      • 注意上面robots.txt第一段的最後一行, 通過設定’Disallow:/’禁止百度爬蟲訪問除了’Allow’規定頁面外的其他所有頁面. 因此當你在百度搜索’淘寶’的時候, 搜尋結果下方會出現: ‘由於該網站的rebots.txt檔案存在限制指令(限制搜尋引擎抓取). 系統無法提供該頁面的內容描述.’, 百度作為一個搜尋引擎, 至少在表面上遵守了淘寶網的robots.txt協議, 所以使用者不能從百度上搜索到淘寶內部的產品資訊.

      • 相關工具介紹

      • 在開始講解爬蟲之前,我們稍微對HTTP(超文字傳輸協議)做一些回顧,因為我們在網頁上看到的內容通常是瀏覽器執行HTML語言得到的結果,而HTTP就是傳輸HTML資料的協議。HTTP是構建於TCP(傳輸控制協議)之上應用級協議,它利用了TCP提供的可靠的傳輸服務實現了Web應用中的資料交換。按照維基百科上的介紹,設計HTTP最初的目的是為了提供一種釋出和接收HTML頁面的方法,也就是說這個協議是瀏覽器和Web伺服器之間傳輸的資料的載體。關於這個協議的詳細資訊以及目前的發展狀況,大家可以閱讀阮一峰老師的《HTTP 協議入門》《網際網路協議入門》系列以及《圖解HTTPS協議》進行了解,下圖是我在2009年9月10日凌晨4點在四川省網路通訊技術重點實驗室用開源協議分析工具Ethereal(抓包工具WireShark的前身)擷取的訪問百度首頁時的HTTP請求和響應的報文(協議資料),由於Ethereal擷取的是經過網路介面卡的資料,因此可以清晰的看到從物理鏈路層到應用層的協議資料。

      • HTTP請求(請求行+請求頭+空行+[訊息體]):

      • HTTP響應(響應行+響應頭+空行+訊息體):

      • 相關工具
      • Chrome Developer Tools

        開發推薦使用谷歌瀏覽器, 這是谷歌的開發者工具

      • POSTMAN(郵差)

      • HTTPie

        $http--headerhttp://www.scu.edu.cn
        HTTP/1.1200OK
        Accept-Ranges:bytes
        Cache-Control:private,max-age=600
        Connection:Keep-Alive
        Content-Encoding:gzip
        Content-Language:zh-CN
        Content-Length:14403
        Content-Type:text/html
        Date:Sun,27May201815:38:25GMT
        ETag:"e6ec-56d3032d70a32-gzip"
        Expires:Sun,27May201815:48:25GMT
        Keep-Alive:timeout=5,max=100
        Last-Modified:Sun,27May201813:44:22GMT
        Server:VWebServer
        Vary:User-Agent,Accept-Encoding
        X-Frame-Options:SAMEORIGIN
      • BuiltWith(python自帶的模組): 識別網站使用的技術

        >>>
        >>>importbuiltwith
        >>>builtwith.parse('http://www.bootcss.com/')
        {'web-servers':['Nginx'],'font-scripts':['FontAwesome'],'javascript-frameworks':['Lo-dash','Underscore.js','Vue.js','Zepto','jQuery'],'web-frameworks':['TwitterBootstrap']}

        >>>
        >>>importssl
        >>>ssl._create_default_https_context=ssl._create_unverified_context
        >>>builtwith.parse('https://www.jianshu.com/')
        {'web-servers':['Tengine'],'web-frameworks':['TwitterBootstrap','RubyonRails'],'programming-languages':['Ruby']}
      • python-whois(python自帶的模組): 查詢網站的所有者

      • robotparser: 解析robots.txt的工具

      • >>>fromurllibimportrobotparser>>>parser=robotparser.RobotFileParser()>>>parser.set_url('https://www.taobao.com/robots.txt')>>>parser.read()>>>parser.can_fetch('Hellokitty','http://www.taobao.com/article')False>>>parser.can_fetch('Baiduspider','http://www.taobao.com/article')True>>>parser.can_fetch('Baiduspider','http://www.taobao.com/product')False12345678910
      • 一個簡單的爬蟲

      • 一個基本的爬蟲通常分為資料採集(網頁下載), 資料處理(網頁解析)和資料儲存(將有用的資訊持久化) 三個部分的內容, 當然更為高階的爬蟲在資料採集和處理時會使用併發程式設計或分散式技術, 其中可能還包括排程器和後臺管理程式(監控爬蟲的工作狀態以及檢查資料爬取的結果)

        • HTTPie

          $http--headerhttp://www.scu.edu.cn
          HTTP/1.1200OK
          Accept-Ranges:bytes
          Cache-Control:private,max-age=600
          Connection:Keep-Alive
          Content-Encoding:gzip
          Content-Language:zh-CN
          Content-Length:14403
          Content-Type:text/html
          Date:Sun,27May201815:38:25GMT
          ETag:"e6ec-56d3032d70a32-gzip"
          Expires:Sun,27May201815:48:25GMT
          Keep-Alive:timeout=5,max=100
          Last-Modified:Sun,27May201813:44:22GMT
          Server:VWebServer
          Vary:User-Agent,Accept-Encoding
          X-Frame-Options:SAMEORIGIN
        • BuiltWith(python自帶的模組): 識別網站使用的技術

          >>>
          >>>importbuiltwith
          >>>builtwith.parse('http://www.bootcss.com/')
          {'web-servers':['Nginx'],'font-scripts':['FontAwesome'],'javascript-frameworks':['Lo-dash','Underscore.js','Vue.js','Zepto','jQuery'],'web-frameworks':['TwitterBootstrap']}

          >>>
          >>>importssl
          >>>ssl._create_default_https_context=ssl._create_unverified_context
          >>>builtwith.parse('https://www.jianshu.com/')
          {'web-servers':['Tengine'],'web-frameworks':['TwitterBootstrap','RubyonRails'],'programming-languages':['Ruby']}
        • python-whois(python自帶的模組): 查詢網站的所有者

        • robotparser: 解析robots.txt的工具

        • >>>fromurllibimportrobotparser>>>parser=robotparser.RobotFileParser()>>>parser.set_url('https://www.taobao.com/robots.txt')>>>parser.read()>>>parser.can_fetch('Hellokitty','http://www.taobao.com/article')False>>>parser.can_fetch('Baiduspider','http://www.taobao.com/article')True>>>parser.can_fetch('Baiduspider','http://www.taobao.com/product')False12345678910
        • 一個簡單的爬蟲

        • 一個基本的爬蟲通常分為資料採集(網頁下載), 資料處理(網頁解析)和資料儲存(將有用的資訊持久化) 三個部分的內容, 當然更為高階的爬蟲在資料採集和處理時會使用併發程式設計或分散式技術, 其中可能還包括排程器和後臺管理程式(監控爬蟲的工作狀態以及檢查資料爬取的結果)

        • 設定抓取目標(種子頁面)並獲取網頁.

        • 當伺服器無法訪問時, 設定重試次數.

        • 在需要的時候設定使用者代理(否則無法訪問頁面)

        • 對獲取的頁面進行必要的解碼操作

        • 通過正則表示式獲取頁面中的連結

        • 對連結進行進一步的處理(獲取頁面並重覆上面的操作)

        • 將有用的資訊進行持久化(以備後續的處理)

        • 設定包裝類進行重試次數
        • classRetry(object):

          def__init__(self,*,retry_times=3,wait_secs=5,errors=(Exception,)):
          self.retry_times=retry_times
          self.wait_secs=wait_secs
          self.errors=errorsdef__call__(self,fn):

          defwrapper(*args,**kwargs):

          try:returnfn(*args,**kwargs)exceptself.errorsase:
          logging.error(e)
          sleep((random()+1)*self.wait_secs)returnwrapperclassSpider(object):

          def__init__(self):
          self.status=SpiderStatus.IDEL@Retry()
          deffetch(self,current_url,*,user_agent=None,proxies=None,charsets=('utf-8',)):
          thread_name=current_thread().name
          print(f'[{thread_name}:{current_url}]')
          headers={'user-agent':user_agent}ifuser_agentelse{}
          resp=requests.get(current_url,headers=headers,proxies=proxies)returndecode_page(resp.content,charsets=charsets)ifresp.status_code==200elseNone1234567891011121314151617181920212223242526272829303132
        • 3 設定代理,隱藏真實身份
        • #例項1:
          defget_html(url):
          #這裡我們給url請求,偽裝了一個請求頭,表示我是一個瀏覽器(也可以偽裝成移動端)
          resp=requests.get(url,headers={'user-agent':'Mozilla/5.0(iPhone;CPUiPhoneOS10_3likeMacOSX)AppleWebKit/602.1.50(KHTML,likeGecko)CriOS/56.0.2924.75Mobile/14E5239eSafari/602.1'})returnresp#例項2:
          defget_html(url):
          #這裡我們的url請求,偽裝成百度的爬蟲
          resp=requests.get(url,headers={'user-agent':'Baiduspider'})returnresp#例項3:
          defmain():
          這裡我使用了代理的IP,隱藏了自己的真實ip
          headers={'user-agent':'Baiduspider'}#隱藏自己的身份IP
          proxies={#代理IP'http':'36.22.76.233:35390',
          'http':'61.135.217.7:80'
          }
          base_url='https://www.zhihu.com'
          seed_url=urljoin(base_url,'explore')

          resp=requests.get(seed_url,headers=headers,proxies=proxies)1234567891011121314151617181920212223242526
        • 常見的偽裝 ‘user-agent’:
          1.Android
          * Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19
          * Mozilla/5.0 (Linux; U; Android 4.0.4; en-gb; GT-I9300 Build/IMM76D) * * * AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
          * Mozilla/5.0 (Linux; U; Android 2.2; en-gb; GT-P1000 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
          2.Firefox
          * Mozilla/5.0 (Windows NT 6.2; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0
          * Mozilla/5.0 (Android; Mobile; rv:14.0) Gecko/14.0 Firefox/14.0
          3.Google Chrome
          * Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36
          * Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19
          4.iOS
          * Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3
          * Mozilla/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/3A101a Safari/419.3

        • 4 - 6解碼/正則匹配內容/bs4抓取資料/持久化儲存
        • fromurllib.errorimportURLErrorfromurllib.requestimporturlopenimportreimportpymysqlimportsslfrompymysqlimportError#通過指定的字符集對頁面進行解碼(不是每個網站都將字符集設定為utf-8)defdecode_page(page_bytes,charsets=('utf-8',)):
          page_html=None
          forcharsetincharsets:try:
          page_html=page_bytes.decode(charset)break
          exceptUnicodeDecodeError:pass
          #logging.error('Decode:',error)
          returnpage_html#獲取頁面的HTML程式碼(通過遞迴實現指定次數的重試操作)defget_page_html(seed_url,*,retry_times=3,charsets=('utf-8',)):
          page_html=None
          try:
          page_html=decode_page(urlopen(seed_url).read(),charsets)exceptURLError:#logging.error('URL:',error)
          ifretry_times>0:returnget_page_html(seed_url,retry_times=retry_times-1,
          charsets=charsets)returnpage_html#從頁面中提取需要的部分(通常是連結也可以通過正則表示式進行指定)defget_matched_parts(page_html,pattern_str,pattern_ignore_case=re.I):
          pattern_regex=re.compile(pattern_str,pattern_ignore_case)returnpattern_regex.findall(page_html)ifpage_htmlelse[]#開始執行爬蟲程式並對指定的資料進行持久化操作defstart_crawl(seed_url,match_pattern,*,max_depth=-1):
          conn=pymysql.connect(host='localhost',port=3306,
          database='crawler',user='root',
          password='123456',charset='utf8')try:withconn.cursor()ascursor:
          url_list=[seed_url]#通過下面的字典避免重複抓取並控制抓取深度
          visited_url_list={seed_url:0}whileurl_list:
          current_url=url_list.pop(0)
          depth=visited_url_list[current_url]ifdepth!=max_depth:
          page_html=get_page_html(current_url,charsets=('utf-8','gbk','gb2312'))
          links_list=get_matched_parts(page_html,match_pattern)
          param_list=[]forlinkinlinks_list:iflinknotinvisited_url_list:
          visited_url_list[link]=depth+1
          page_html=get_page_html(link,charsets=('utf-8','gbk','gb2312'))
          headings=get_matched_parts(page_html,r'<h1>(.*)<span')ifheadings:
          param_list.append((headings[0],link))
          cursor.executemany('insertintotb_resultvalues(default,%s,%s)',
          param_list)
          conn.commit()exceptError:pass
          #logging.error('SQL:',error)
          finally:
          conn.close()defmain():
          ssl._create_default_https_context=ssl._create_unverified_context
          start_crawl('http://sports.sohu.com/nba_a.shtml',r'<a[^>]+test=a\s[^>]*href=["\'](.*?)["\']',
          max_depth=2)if__name__=='__main__':
          main()
          • 注意事項:
            1. 處理相對連結. 有的時候我們從頁面中獲取的連結不是一個完整的絕對連結而是一個相對連結. 在這種情況下需要將其與URL字首進行拼接(urllib,parse中的urljoin函式可以完成此項操作).
            2. 設定dialing服務. 有些網站會限制訪問的區域(例如美國的Netfix遮蔽了很多國家的訪問), 有些爬蟲需要隱藏自己的身份, 在這種情況下可以設定代理伺服器(urllib.request中的ProxyHandler就是用來進行此項操作)
            3. 限制下載速度. 如果我們的爬蟲獲取頁面的速度過快, 可能就會面臨被封禁或者產生’損害動產’的風險(這個可能會導致吃官司且敗訴), 可以在兩次下載之間新增延時從而對爬蟲進行限速.
            4. 避免爬蟲陷阱. 有些網站會動態生成頁面內容, 這回導致產生無限多的頁面(例如線上萬年曆等), 可以通過記錄到達當前頁面經過了多少個連結(連結深度) 來解決該問題, 當達到實現設定的最大深度時爬蟲就不再想佇列中新增該網頁中的連結了.
            5. SSL相關問題, 在使用urlopen開啟一個HTPPS連線時會驗證一次SSL整數, 如果不作出處理會產生錯誤提示”SSL:CERTIFICATE_VERIFY_FAILED”, 可以通過以下兩種方式進行解決:

          • 使用未經驗證的上下文

          • importssl

            request=urllib.request.Request(url='...',headers={...})
            context=ssl._create_unverified_context()
            web_page=urllib.request.urlopen(request,context=context

          • 設定全域性的取消證書驗證

            importssl
            ssl._create_default_https_context=ssl._create_unverified_context

智慧營銷總部官網 智慧營銷官網 ;智慧營銷官網 ;智慧營銷官網