<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何構(gòu)建一個通用的垂直爬蟲平臺?

          共 10006字,需瀏覽 21分鐘

           ·

          2021-02-05 08:58

          閱讀本文大約需要15~20分鐘。?
          本文章內(nèi)容較多,非常干貨!如果手機(jī)閱讀體驗(yàn)不好,建議先收藏后到 PC 端閱讀。
          之前做爬蟲時,在公司設(shè)計(jì)開發(fā)了一個通用的垂直爬蟲平臺,后來在公司做了內(nèi)部的技術(shù)分享,這篇文章把整個爬蟲平臺的設(shè)計(jì)思路整理了一下,分享給大家。
          寫一個爬蟲很簡單,寫一個可持續(xù)穩(wěn)定運(yùn)行的爬蟲也不難,但如何構(gòu)建一個通用化的垂直爬蟲平臺?
          這篇文章,我就來和你分享一下,一個通用垂直爬蟲平臺的構(gòu)建思路。

          爬蟲簡介

          首先介紹一下,什么是爬蟲?
          搜索引擎是這樣定義的:
          網(wǎng)絡(luò)爬蟲(又被稱為網(wǎng)頁蜘蛛,網(wǎng)絡(luò)機(jī)器人),是一種按照一定的規(guī)則,自動地抓取網(wǎng)頁信息的程序或者腳本。
          很簡單,爬蟲就是指定規(guī)則自動采集數(shù)據(jù)的程序腳本,目的在于拿到想要的數(shù)據(jù)。
          而爬蟲主要分為兩大類:
          • 通用爬蟲(搜索引擎)
          • 垂直爬蟲(特定領(lǐng)域)
          由于第一類的開發(fā)成本較高,所以只有搜索引擎公司在做,如谷歌、百度等。
          而大多數(shù)企業(yè)在做的都是第二類,成本低、數(shù)據(jù)價值高。
          例如一家做電商的公司只需要電商領(lǐng)域有價值的數(shù)據(jù),那開發(fā)一個只采集電商領(lǐng)域數(shù)據(jù)的爬蟲平臺,意義較大。
          我要和你分享的主要是針對第二類,垂直爬蟲平臺的設(shè)計(jì)思路。

          如何寫爬蟲

          首先,從最簡單的開始,我們先了解一下如何寫一個爬蟲?

          簡單爬蟲

          開發(fā)爬蟲最快的語言一般是 Python,它的代碼寫起來非常少。我們以抓取豆瓣書籍頁面為例,來寫一個簡單的程序。
          #?coding:?utf8

          """簡單爬蟲"""

          import?requests
          from?lxml?import?etree

          def?main():
          ????#?1.?定義頁面URL和解析規(guī)則
          ????crawl_urls?=?[
          ????????'https://book.douban.com/subject/25862578/',
          ????????'https://book.douban.com/subject/26698660/',
          ????????'https://book.douban.com/subject/2230208/'
          ????]
          ????parse_rule?=?"http://div[@id='wrapper']/h1/span/text()"

          ????for?url?in?crawl_urls:
          ????????#?2.?發(fā)起HTTP請求
          ????????response?=?requests.get(url)

          ????????#?3.?解析HTML
          ????????result?=?etree.HTML(response.text).xpath(parse_rule)[0]

          ????????#?4.?保存結(jié)果
          ????????print?result

          if?__name__?==?'__main__':
          ????main()
          這個爬蟲比較簡單,大致流程為:
          1. 定義頁面URL和解析規(guī)則
          2. 發(fā)起HTTP請求
          3. 解析HTML,拿到數(shù)據(jù)
          4. 保存數(shù)據(jù)
          任何爬蟲,要想獲取網(wǎng)頁上的數(shù)據(jù),都是經(jīng)過這幾步。
          當(dāng)然,這個簡單爬蟲效率比較低,是采用同步抓取的方式,只能抓完一個網(wǎng)頁,再去抓下一個,有沒有可以提高效率的方式呢?

          異步爬蟲

          我們進(jìn)行優(yōu)化,由于爬蟲的抓取請求都是阻塞在網(wǎng)絡(luò) IO 上,所以我們可以使用異步的方式來優(yōu)化,例如多線程或協(xié)程并行抓取網(wǎng)頁數(shù)據(jù),這里用 Python 的協(xié)程來實(shí)現(xiàn)。
          #?coding:?utf8

          """協(xié)程版本爬蟲,提高抓取效率"""

          from?gevent?import?monkey
          monkey.patch_all()

          import?requests
          from?lxml?import?etree
          from?gevent.pool?import?Pool

          def?main():
          ????#?1.?定義頁面URL和解析規(guī)則
          ????crawl_urls?=?[
          ????????'https://book.douban.com/subject/25862578/',
          ????????'https://book.douban.com/subject/26698660/',
          ????????'https://book.douban.com/subject/2230208/'
          ????]
          ????rule?=?"http://div[@id='wrapper']/h1/span/text()"

          ????#?2.?抓取
          ????pool?=?Pool(size=10)
          ????for?url?in?crawl_urls:
          ????????pool.spawn(crawl,?url,?rule)

          ????pool.join()

          def?crawl(url,?rule):
          ????#?3.?發(fā)起HTTP請求
          ????response?=?requests.get(url)

          ????#?4.?解析HTML
          ????result?=?etree.HTML(response.text).xpath(rule)[0]

          ????#?5.?保存結(jié)果
          ????print?result

          if?__name__?==?'__main__':
          ????main()
          經(jīng)過優(yōu)化,我們完成了異步版本的爬蟲代碼。
          有了這些基礎(chǔ)知識之后,我們看一個完整的例子,如何抓取一個整站數(shù)據(jù)?

          整站爬蟲

          #?coding:?utf8

          """整站爬蟲"""

          from?gevent?import?monkey
          monkey.patch_all()

          from?urlparse?import?urljoin

          import?requests
          from?lxml?import?etree
          from?gevent.pool?import?Pool
          from?gevent.queue?import?Queue

          base_url?=?'https://book.douban.com'

          #?種子URL
          start_url?=?'https://book.douban.com/tag/?view=type&icn=index-sorttags-all'

          #?解析規(guī)則
          rules?=?{
          ????#?標(biāo)簽頁列表
          ????'list_urls':?"http://table[@class='tagCol']/tbody/tr/td/a/@href",
          ????#?詳情頁列表
          ????'detail_urls':?"http://li[@class='subject-item']/div[@class='info']/h2/a/@href",
          ????#?頁碼
          ????'page_urls':?"http://div[@id='subject_list']/div[@class='paginator']/a/@href",
          ????#?書名
          ????'title':?"http://div[@id='wrapper']/h1/span/text()",
          }

          #?定義隊(duì)列
          list_queue?=?Queue()
          detail_queue?=?Queue()

          #?定義協(xié)程池
          pool?=?Pool(size=10)

          def?crawl(url):
          ????"""首頁"""
          ????response?=?requests.get(url)
          ????list_urls?=?etree.HTML(response.text).xpath(rules['list_urls'])
          ????for?list_url?in?list_urls:
          ????????list_queue.put(urljoin(base_url,?list_url))

          def?list_loop():
          ????"""采集列表頁"""
          ????while?True:
          ????????list_url?=?list_queue.get()
          ????????pool.spawn(crawl_list_page,?list_url)

          def?detail_loop():
          ????"""采集詳情頁"""
          ????while?True:
          ????????detail_url?=?detail_queue.get()
          ????????pool.spawn(crawl_detail_page,?detail_url)

          def?crawl_list_page(list_url):
          ????"""采集列表頁"""
          ????html?=?requests.get(list_url).text
          ????detail_urls?=?etree.HTML(html).xpath(rules['detail_urls'])
          ????#?詳情頁
          ????for?detail_url?in?detail_urls:
          ????????detail_queue.put(urljoin(base_url,?detail_url))

          ????#?下一頁
          ????list_urls?=?etree.HTML(html).xpath(rules['page_urls'])
          ????for?list_url?in?list_urls:
          ????????list_queue.put(urljoin(base_url,?list_url))

          def?crawl_detail_page(list_url):
          ????"""采集詳情頁"""
          ????html?=?requests.get(list_url).text
          ????title?=?etree.HTML(html).xpath(rules['title'])[0]
          ????print?title

          def?main():
          ????#?1.?標(biāo)簽頁
          ????crawl(start_url)
          ????#?2.?列表頁
          ????pool.spawn(list_loop)
          ????#?3.?詳情頁
          ????pool.spawn(detail_loop)
          ????#?開始采集
          ????pool.join()

          if?__name__?==?'__main__':
          ????main()
          我們想要抓取豆瓣圖書的整站數(shù)據(jù),執(zhí)行的流程是:
          1. 找到入口,也就是從書籍標(biāo)簽頁進(jìn)入,提取所有標(biāo)簽 URL
          2. 進(jìn)入每個標(biāo)簽頁,提取所有列表 URL
          3. 進(jìn)入每個列表頁,提取每一頁的詳情URL和下一頁列表 URL
          4. 進(jìn)入每個詳情頁,拿到書籍信息
          5. 如此往復(fù)循環(huán),直到數(shù)據(jù)抓取完畢
          這就是抓取一個整站的思路,很簡單,無非就是分析我們?yōu)g覽網(wǎng)站的行為軌跡,用程序來進(jìn)行自動化的請求、抓取。
          理想情況下,我們應(yīng)該能夠拿到整站的數(shù)據(jù),但實(shí)際情況是,對方網(wǎng)站往往會采取防爬蟲措施,在抓取一段時間后,我們的 IP 就會被封禁。
          那如何突破這些防爬措施,拿到數(shù)據(jù)呢?我們繼續(xù)優(yōu)化代碼。

          防反爬的整站爬蟲

          #?coding:?utf8

          """防反爬的整站爬蟲"""

          from?gevent?import?monkey
          monkey.patch_all()

          import?random
          from?urlparse?import?urljoin

          import?requests
          from?lxml?import?etree
          import?gevent
          from?gevent.pool?import?Pool
          from?gevent.queue?import?Queue

          base_url?=?'https://book.douban.com'

          #?種子URL
          start_url?=?'https://book.douban.com/tag/?view=type&icn=index-sorttags-all'

          #?解析規(guī)則
          rules?=?{
          ????#?標(biāo)簽頁列表
          ????'list_urls':?"http://table[@class='tagCol']/tbody/tr/td/a/@href",
          ????#?詳情頁列表
          ????'detail_urls':?"http://li[@class='subject-item']/div[@class='info']/h2/a/@href",
          ????#?頁碼
          ????'page_urls':?"http://div[@id='subject_list']/div[@class='paginator']/a/@href",
          ????#?書名
          ????'title':?"http://div[@id='wrapper']/h1/span/text()",
          }

          #?定義隊(duì)列
          list_queue?=?Queue()
          detail_queue?=?Queue()

          #?定義協(xié)程池
          pool?=?Pool(size=10)

          #?定義代理池
          proxy_list?=?[
          ????'118.190.147.92:15524',
          ????'47.92.134.176:17141',
          ????'119.23.32.38:20189',
          ]

          #?定義UserAgent
          user_agent_list?=?[
          ????'Mozilla/5.0?(Windows?NT?6.1)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/41.0.2228.0?Safari/537.36',
          ????'Mozilla/5.0?(Windows?NT?6.1;?WOW64;?rv:40.0)?Gecko/20100101?Firefox/40.1',
          ????'Mozilla/5.0?(Macintosh;?Intel?Mac?OS?X?10_9_3)?AppleWebKit/537.75.14?(KHTML,?like?Gecko)?Version/7.0.3?Safari/7046A194A',
          ????'Mozilla/5.0?(Windows?NT?6.1;?WOW64;?Trident/7.0;?AS;?rv:11.0)?like?Gecko',
          ]

          def?fetch(url):
          ????"""發(fā)起HTTP請求"""
          ????proxies?=?random.choice(proxy_list)
          ????user_agent?=?random.choice(user_agent_list)
          ????headers?=?{'User-Agent':?user_agent}
          ????html?=?requests.get(url,?headers=headers,?proxies=proxies).text
          ????return?html

          def?parse(html,?rule):
          ????"""解析頁面"""
          ????return?etree.HTML(html).xpath(rule)

          def?crawl(url):
          ????"""首頁"""
          ????html?=?fetch(url)
          ????list_urls?=?parse(html,?rules['list_urls'])
          ????for?list_url?in?list_urls:
          ????????list_queue.put(urljoin(base_url,?list_url))

          def?list_loop():
          ????"""采集列表頁"""
          ????while?True:
          ????????list_url?=?list_queue.get()
          ????????pool.spawn(crawl_list_page,?list_url)

          def?detail_loop():
          ????"""采集詳情頁"""
          ????while?True:
          ????????detail_url?=?detail_queue.get()
          ????????pool.spawn(crawl_detail_page,?detail_url)

          def?crawl_list_page(list_url):
          ????"""采集列表頁"""
          ????html?=?fetch(list_url)
          ????detail_urls?=?parse(html,?rules['detail_urls'])

          ????#?詳情頁
          ????for?detail_url?in?detail_urls:
          ????????detail_queue.put(urljoin(base_url,?detail_url))

          ????#?下一頁
          ????list_urls?=?parse(html,?rules['page_urls'])
          ????for?list_url?in?list_urls:
          ????????list_queue.put(urljoin(base_url,?list_url))

          def?crawl_detail_page(list_url):
          ????"""采集詳情頁"""
          ????html?=?fetch(list_url)
          ????title?=?parse(html,?rules['title'])[0]
          ????print?title

          def?main():
          ????#?1.?首頁
          ????crawl(start_url)
          ????#?2.?列表頁
          ????pool.spawn(list_loop)
          ????#?3.?詳情頁
          ????pool.spawn(detail_loop)
          ????#?開始采集
          ????pool.join()

          if?__name__?==?'__main__':
          ????main()
          這個版本的代碼與之前不同的是,在發(fā)起 HTTP 請求時,加上了隨機(jī)代理 IP 和請求頭 UserAgent,這也是突破防爬措施的常用手段。使用這些手段,加上一些質(zhì)量高的代理 IP,應(yīng)對一些小網(wǎng)站的數(shù)據(jù)抓取,不在話下。
          當(dāng)然,這里只為了展示一步步寫爬蟲、優(yōu)化爬蟲的思路,來達(dá)到抓取數(shù)據(jù)的目的,現(xiàn)實(shí)情況的抓取與反爬比想象中的更復(fù)雜,需要具體場景具體分析。

          現(xiàn)有問題

          經(jīng)過上面這幾步,我們想要哪個網(wǎng)站的數(shù)據(jù),分析網(wǎng)站網(wǎng)頁結(jié)構(gòu),寫出代碼應(yīng)該不成問題。
          但是,抓幾個網(wǎng)站可以這么寫,但抓幾十個、幾百個網(wǎng)站,你還能寫下去嗎?
          當(dāng)我們要采集的網(wǎng)站越來越多,編寫的爬蟲腳本也會越來越多,維護(hù)起來也會變得困難。由此暴露出來的問題包括:
          • 爬蟲腳本繁多,管理和維護(hù)困難
          • 爬蟲規(guī)則定義零散,可能會重復(fù)開發(fā)
          • 爬蟲都是后臺腳本,沒有監(jiān)控
          • 爬蟲腳本輸出的數(shù)據(jù)格式不統(tǒng)一,可能是文件,也可能也數(shù)據(jù)庫
          • 業(yè)務(wù)要想使用爬蟲的數(shù)據(jù)比較困難,沒有統(tǒng)一的對接入口
          這些問題都是我們在爬蟲越寫越多的情況下,難免會遇到的問題。
          此時,我們迫切需要一個更好的解決方案,來更好地開發(fā)爬蟲,所以爬蟲平臺應(yīng)運(yùn)而生。
          那么如何設(shè)計(jì)一個通用化的垂直爬蟲平臺呢?

          平臺架構(gòu)

          我們來分析每個爬蟲的共同點(diǎn),結(jié)果發(fā)現(xiàn):寫一個爬蟲無非就是規(guī)則、抓取、解析、入庫這幾步,那我們可不可以把每一塊分別拆開呢?
          根據(jù)這個思路,我們可以把爬蟲平臺設(shè)計(jì)成如下圖:

          我們的爬蟲平臺包括的模塊有
          • 配置服務(wù):包括抓取頁面配置、解析規(guī)則配置、數(shù)據(jù)清洗配置
          • 采集服務(wù):只專注網(wǎng)頁的下載,并配置防爬策略
          • 代理服務(wù):持續(xù)提供穩(wěn)定、可用的代理 IP
          • 清洗服務(wù):針對爬蟲采集到的數(shù)據(jù)進(jìn)行進(jìn)一步清洗和規(guī)整
          • 數(shù)據(jù)服務(wù):爬蟲數(shù)據(jù)的展示,以及業(yè)務(wù)系統(tǒng)對接
          我們把一個爬蟲的每一個環(huán)節(jié),拆開做成一個個單獨(dú)的服務(wù)模塊,各模塊各司其職,每個模塊之間通過 API 或 消息隊(duì)列進(jìn)行通信。
          這樣做的好處是,每個模塊維護(hù)只維護(hù)自己領(lǐng)域的功能,而且每個模塊可獨(dú)立升級和優(yōu)化,不影響其他模塊。
          下面我們來看一下每個模塊具體是如何設(shè)計(jì)的。

          詳細(xì)設(shè)計(jì)

          配置服務(wù)

          配置服務(wù)模塊,此模塊主要包括采集 URL 的配置、頁面解析規(guī)則的配置、數(shù)據(jù)清洗規(guī)則的配置。
          我們把爬蟲的規(guī)則從爬蟲腳本中抽離出來,單獨(dú)配置與維護(hù),這樣做的好處是便于重用和管理。
          由于此模塊只專注配置管理,那我們可以對配置規(guī)則進(jìn)一步拆開,可以支持各種方式的數(shù)據(jù)解析模式,主要包含以下幾種:
          • 正則解析規(guī)則
          • CSS解析規(guī)則
          • XPATH解析規(guī)則
          每種解析規(guī)則模式,只配置對應(yīng)的表達(dá)式即可。
          采集服務(wù)可以寫一個配置解析器,與配置服務(wù)進(jìn)行對接,這個配置解析器內(nèi)部實(shí)現(xiàn)各種模式具體的解析邏輯。
          數(shù)據(jù)清洗規(guī)則配置,主要包含每個頁面采集數(shù)據(jù)后,針對這個頁面字段做進(jìn)一步清洗和規(guī)整化的配置規(guī)則。例如采集服務(wù)抓取到的數(shù)據(jù)包含特殊字符,在采集服務(wù)中不會做進(jìn)一步處理,而是放到清洗服務(wù)中去處理,具體的清洗規(guī)則可以自定義,常見的有刪除某些特殊字符、特殊字段類型轉(zhuǎn)換等等。

          采集服務(wù)

          此服務(wù)模塊比較純粹,就是寫爬蟲邏輯。我們可以像之前那樣開發(fā)、調(diào)試、運(yùn)行爬蟲腳本那樣,在此模塊來開發(fā)和調(diào)試爬蟲邏輯。
          但之前的方式只能在命令行腳本中編寫爬蟲程序,然后調(diào)試運(yùn)行,有沒有一種好的方案可以把它做成可視化的呢?
          我們調(diào)研了市面上 Python 語言實(shí)現(xiàn)的,比較好的爬蟲框架,發(fā)現(xiàn)?pyspider?符合我們的需求,此框架的特點(diǎn):
          • 支持分布式
          • 配置可視化
          • 可周期采集
          • 支持優(yōu)先級
          • 任務(wù)可監(jiān)控
          pyspider架構(gòu)圖如下:

          正所謂站在巨人的肩膀上,這個框架基本可以滿足我們的需求,但為了更好地實(shí)現(xiàn)我們的爬蟲平臺,我們決定對其進(jìn)行二次開發(fā),并增強(qiáng)一些組件,使爬蟲開發(fā)成本更低,更符合我們的業(yè)務(wù)規(guī)則。
          二次開發(fā)的功能主要包括:
          • 開發(fā)配置解析器,對接配置服務(wù),可以解析配置服務(wù)的多種規(guī)則模式
          • spider handler模塊定制爬蟲模板,并把爬蟲任務(wù)進(jìn)行分類,定義成模板,降低開發(fā)成本
          • fetcher模塊新增代理 IP 調(diào)度機(jī)制,對接代理服務(wù),并增加代理 IP 調(diào)度策略
          • result_worker模塊把輸出結(jié)果定制化,用來對接清洗服務(wù)
          基于這個開源框架,并且增強(qiáng)其組件的方式,我們可以做出一個分布式、可視化、任務(wù)可監(jiān)控、可生成爬蟲模板的采集服務(wù)模塊。
          這個模塊的功能,只專注于網(wǎng)頁數(shù)據(jù)的采集。

          代理服務(wù)

          做爬蟲的都知道,代理是突破防抓的常用手段,如何獲取穩(wěn)定、持續(xù)的代理呢?
          代理服務(wù)這個模塊,就是用來實(shí)現(xiàn)這個功能的。
          此模塊內(nèi)部維護(hù)代理 IP 的質(zhì)量和數(shù)量,并輸出給采集服務(wù),供其采集使用。
          該模塊主要包括兩部分:
          • 免費(fèi)代理
          • 付費(fèi)代理

          免費(fèi)代理

          免費(fèi)代理 IP 主要由我們自己的代理采集程序采集獲得,大致思路為:
          • 收集代理源
          • 定時采集代理
          • 測試代理
          • 輸出可用代理
          具體的實(shí)現(xiàn)邏輯可以參考我之前寫的這篇文章:如何搭建一個爬蟲代理服務(wù)?

          付費(fèi)代理

          免費(fèi)代理的質(zhì)量和穩(wěn)定性相對較差,對于采集防爬比較厲害的網(wǎng)站,還是不夠用。
          這時我們會購買一些付費(fèi)代理,專門用于采集這類防爬的網(wǎng)站,此代理 IP 一般為高匿代理,并定時更新。
          免費(fèi)代理 IP + 付費(fèi)代理 IP,通過 API 的方式提供給采集服務(wù)。

          清洗服務(wù)

          清洗服務(wù)這個模塊比較簡單,主要接收采集服務(wù)輸出的數(shù)據(jù),然后根據(jù)對應(yīng)的規(guī)則執(zhí)行清洗邏輯。
          例如網(wǎng)頁字段與數(shù)據(jù)庫字段歸一轉(zhuǎn)換,特殊字段清洗定制化等等。
          這個服務(wù)模塊運(yùn)行了很多 Worker,最終把輸出結(jié)果輸送到數(shù)據(jù)服務(wù)。

          數(shù)據(jù)服務(wù)

          數(shù)據(jù)服務(wù)這個模塊,會接收最終清洗后的結(jié)構(gòu)化數(shù)據(jù),統(tǒng)一入庫。且針對其他業(yè)務(wù)系統(tǒng)需要的數(shù)據(jù)進(jìn)行統(tǒng)一推送輸出:
          主要功能包括:
          • 數(shù)據(jù)平臺展示
          • 數(shù)據(jù)推送
          • 數(shù)據(jù)API

          解決的問題

          好了,經(jīng)過以上爬蟲平臺的構(gòu)建,我們基本解決了最開始困擾的幾個問題,現(xiàn)在的爬蟲平臺可以實(shí)現(xiàn)的功能包括:
          • 爬蟲腳本統(tǒng)一管理、配置可視化
          • 爬蟲模板快速生成爬蟲代碼,降低開發(fā)成本
          • 采集進(jìn)度可監(jiān)控、易跟蹤
          • 采集的數(shù)據(jù)統(tǒng)一輸出
          • 業(yè)務(wù)系統(tǒng)使用爬蟲數(shù)據(jù)更便捷

          爬蟲技巧

          最后,分享一下做爬蟲時候的一些技巧,從整體上來說,其實(shí)核心思想就一個:盡可能地模擬人的行為
          主要包括以下幾方面:
          • 隨機(jī) UserAgent 模擬不同的客戶端(github有UserAgent庫,非常全面)
          • 隨機(jī)代理 IP(高匿代理 + 代理調(diào)度策略)
          • Cookie池(針對需要登錄的采集行為)
          • JavaScript渲染頁面(使用無界面瀏覽器加載網(wǎng)頁獲取數(shù)據(jù))
          • 驗(yàn)證碼識別(OCR、機(jī)器學(xué)習(xí))
          當(dāng)然,做爬蟲是一個相互博弈的過程,有時沒必要硬碰硬,遇到問題換個思路也是一種解決辦法。例如,對方的移動客戶端防抓厲害,那去看一看對方的PC站可不可以搞一下?WAP端是否可以嘗試一下?在有限的成本拿到數(shù)據(jù)才是爬蟲的目的。
          爬蟲做的越來越多時,你就會發(fā)現(xiàn),這是一個策略和技巧同樣重要的領(lǐng)域。
          以上就是構(gòu)建一個垂直爬蟲平臺的設(shè)計(jì)思路,從最簡單的爬蟲腳本,到寫越來越多的爬蟲,到難以維護(hù),再到整個爬蟲平臺的構(gòu)建,一步步都是遇到問題解決問題的產(chǎn)物,在我們真正發(fā)現(xiàn)核心問題時,解決思路也就不難了。

          更多閱讀



          2020 年最佳流行 Python 庫 Top 10


          2020 Python中文社區(qū)熱門文章 Top 10


          5分鐘快速掌握 Python 定時任務(wù)框架

          特別推薦




          點(diǎn)擊下方閱讀原文加入社區(qū)會員

          瀏覽 39
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费看韩国毛片 | 在线免费看亚洲区中文字幕 | 艹逼视频在线免费观看 | 一级a性色生活久久无 | 韩国免费一级a一片在线播放 |