<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)建一個通用的Python爬蟲平臺?

          共 10031字,需瀏覽 21分鐘

           ·

          2021-02-23 13:53

          閱讀本文大約需要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)核心問題時,解決思路也就不難了。


          近期文章:



          更多Python技術(shù)文,可以關(guān)注上面公眾號

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

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  狠狠狠干 | 啪啪啪网站免费看 | 无码电影视频 | 太湾黄色一级网 | 2024无码视频 |