摘要:爬蟲也可以稱為爬蟲不知從何時起,這門語言和爬蟲就像一對戀人,二者如膠似漆,形影不離,你中有我我中有你,一提起爬蟲,就會想到,一說起,就會想到人工智能和爬蟲所以,一般說爬蟲的時候,大部分程序員潛意識里都會聯想為爬蟲,為什么會這樣,我覺得有兩個
爬蟲也可以稱為Python爬蟲
不知從何時起,Python這門語言和爬蟲就像一對戀人,二者如膠似漆 ,形影不離,你中有我、我中有你,一提起爬蟲,就會想到Python,一說起Python,就會想到人工智能……和爬蟲
所以,一般說爬蟲的時候,大部分程序員潛意識里都會聯想為Python爬蟲,為什么會這樣,我覺得有兩個原因:
Python生態極其豐富,諸如Request、Beautiful Soup、Scrapy、PySpider等第三方庫實在強大
Python語法簡潔易上手,分分鐘就能寫出一個爬蟲(有人吐槽Python慢,但是爬蟲的瓶頸和語言關系不大)
任何一個學習Python的程序員,應該都或多或少地見過甚至研究過爬蟲,我當時寫Python的目的就非常純粹——為了寫爬蟲。所以本文的目的很簡單,就是說說我個人對Python爬蟲的理解與實踐,作為一名程序員,我覺得了解一下爬蟲的相關知識對你只有好處,所以讀完這篇文章后,如果能對你有幫助,那便再好不過
什么是爬蟲爬蟲是一個程序,這個程序的目的就是為了抓取萬維網信息資源,比如你日常使用的谷歌等搜索引擎,搜索結果就全都依賴爬蟲來定時獲取
看上述搜索結果,除了wiki相關介紹外,爬蟲有關的搜索結果全都帶上了Python,前人說Python爬蟲,現在看來果然誠不欺我~
爬蟲的目標對象也很豐富,不論是文字、圖片、視頻,任何結構化非結構化的數據爬蟲都可以爬取,爬蟲經過發展,也衍生出了各種爬蟲類型:
通用網絡爬蟲:爬取對象從一些種子 URL 擴充到整個 Web,搜索引擎干的就是這些事
垂直網絡爬蟲:針對特定領域主題進行爬取,比如專門爬取小說目錄以及章節的垂直爬蟲
增量網絡爬蟲:對已經抓取的網頁進行實時更新
深層網絡爬蟲:爬取一些需要用戶提交關鍵詞才能獲得的 Web 頁面
不想說這些大方向的概念,讓我們以一個獲取網頁內容為例,從爬蟲技術本身出發,來說說網頁爬蟲,步驟如下:
模擬請求網頁資源
從HTML提取目標元素
數據持久化
什么是爬蟲,這就是爬蟲:
"""讓我們根據上面說的步驟來完成一個簡單的爬蟲程序""" import requests from bs4 import BeautifulSoup target_url = "http://www.baidu.com/s?wd=爬蟲" # 第一步 發起一個GET請求 res = requests.get(target_url) # 第二步 提取HTML并解析想獲取的數據 比如獲取 title soup = BeautifulSoup(res.text, "lxml") # 輸出 soup.title.text title = soup.title.text # 第三步 持久化 比如保存到本地 with open("title.txt", "w") as fp: fp.write(title)
加上注釋不到20行代碼,你就完成了一個爬蟲,簡單吧
怎么寫爬蟲網頁世界多姿多彩、億萬網頁資源供你選擇,面對不同的頁面,怎么使自己編寫的爬蟲程序夠穩健、持久,這是一個值得討論的問題
俗話說,磨刀不誤砍柴工,在開始編寫爬蟲之前,很有必要掌握一些基本知識:
網頁的結構是HTML,爬蟲的目標就是解析HTML,獲取目標字段并保存
客戶端展現的網頁由瀏覽器渲染,客戶端和服務端的信息交互依靠HTTP協議
這兩句描述體現了一名爬蟲開發人員需要掌握的基本知識,不過一名基本的后端或者前端工程師都會這些哈哈,這也說明了爬蟲的入門難度極低,從這兩句話,你能思考出哪些爬蟲必備的知識點呢?
基本的HTML知識,了解HTML才方便目標信息提取
基本的JS知識 ,JS可以異步加載HTML
了解CSS Selector、XPath以及正則,目的是為了提取數據
了解HTTP協議,為后面的反爬蟲斗爭打下基礎
了解基本的數據庫操作,為了數據持久化
有了這些知識儲備,接下來就可以選擇一門語言,開始編寫自己的爬蟲程序了,還是按照上一節說的三個步驟,然后以Python為例,說一說要在編程語言方面做那些準備:
網頁請求:內置有urllib庫,第三方庫的話,同步請求可以使用requests,異步請求使用aiohttp
分析HTML結構并提取目標元素:CSS Selector和XPath是目前主流的提取方式,第三方庫可以使用Beautiful Soup或者PyQuery
數據持久化:目標數據提取之后,可以將數據保存到數據庫中進行持久化,MySQL、MongoDB等,這些都有對應的庫支持,當然你也可以保存在硬盤,誰硬盤沒點東西對吧(滑稽臉)
掌握了上面這些,你大可放開手腳大干一場,萬維網就是你的名利場,去吧~
我覺得對于一個目標網站的網頁,可以分下面四個類型:
單頁面單目標
單頁面多目標
多頁面單目標
多頁面多目標
具體是什么意思呢,可能看起來有點繞,但明白這些,你之后寫爬蟲,只要在腦子里面過一遍著網頁對應什么類型,然后套上對應類型的程序(寫多了都應該有一套自己的常用代碼庫),那寫爬蟲的速度,自然不會慢
單頁面單目標
通俗來說,就是在這個網頁里面,我們的目標就只有一個,假設我們的需求是抓取這部 電影-肖申克的救贖 的名稱,首先打開網頁右鍵審查元素,找到電影名稱對應的元素位置,如下圖所示:
在某個單一頁面內,看目標是不是只有一個,一眼就能看出標題的CSS Selector規則為:#content > h1 > span:nth-child(1),然后用我自己寫的常用庫,我用不到十行代碼就能寫完抓取這個頁面電影名稱的爬蟲:
import asyncio from ruia import Item, TextField class DoubanItem(Item): title = TextField(css_select="#content > h1 > span:nth-child(1)") async_func = DoubanItem.get_item(url="https://movie.douban.com/subject/1292052/") item = asyncio.get_event_loop().run_until_complete(async_func) print(item.title)
多頁面多目標就是此情況下多個url的衍生情況
單頁面多目標
假設現在的需求是抓取 豆瓣電影250 第一頁中的所有電影名稱,你需要提取25個電影名稱,因為這個目標頁的目標數據是多個item的,因此目標需要循環獲取,這就是所謂的單頁面多目標了:
import asyncio from ruia import Item, TextField class DoubanItem(Item): target_item = TextField(css_select="div.item") title = TextField(css_select="span.title") async def clean_title(self, title): if isinstance(title, str): return title else: return "".join([i.text.strip().replace("xa0", "") for i in title]) async_func = DoubanItem.get_items(url="https://movie.douban.com/top250") items = asyncio.get_event_loop().run_until_complete(async_func) for item in items: print(item)
多頁面多目標
多頁面多目標是上述單頁面多目標情況的衍生,在這個問題上來看,此時就是獲取所有分頁的電影名稱
from ruia import TextField, Item, Request, Spider class DoubanItem(Item): """ 定義爬蟲的目標字段 """ target_item = TextField(css_select="div.item") title = TextField(css_select="span.title") async def clean_title(self, title): if isinstance(title, str): return title else: return "".join([i.text.strip().replace("xa0", "") for i in title]) class DoubanSpider(Spider): start_urls = ["https://movie.douban.com/top250"] concurrency = 10 async def parse(self, res): etree = res.html_etree pages = ["?start=0&filter="] + [i.get("href") for i in etree.cssselect(".paginator>a")] for index, page in enumerate(pages): url = self.start_urls[0] + page yield Request( url, callback=self.parse_item, metadata={"index": index}, request_config=self.request_config ) async def parse_item(self, res): items_data = await DoubanItem.get_items(html=res.html) res_list = [] for item in items_data: res_list.append(item.title) return res_list if __name__ == "__main__": DoubanSpider.start()
如果網絡沒問題的話,會得到如下輸出:
注意爬蟲運行時間,1s不到,這就是異步的魅力
用Python寫爬蟲,就是這么簡單優雅,諸位,看著網頁就思考下:
是什么類型的目標類型
用什么庫模擬請求
怎么解析目標字段
怎么存儲
一個爬蟲程序就成型了,順便一提,爬蟲這東西,可以說是防君子不防小人,robots.txt大部分網站都有(它的目的是告訴爬蟲什么可以爬取什么不可以爬取,比如:https://www.baidu.com/robots.txt),各位想怎么爬取,自己衡量
如何進階不要以為寫好一個爬蟲程序就可以出師了,此時還有更多的問題在前面等著你,你要含情脈脈地看著你的爬蟲程序,問自己三個問題:
爬蟲抓取數據后是正當用途么?
爬蟲會把目標網站干掉么?
爬蟲會被反爬蟲干掉么?
前兩個關于人性的問題在此不做過多敘述,因此跳過,但你們如果作為爬蟲工程師的話,切不可跳過
會被反爬蟲干掉么?
最后關于反爬蟲的問題才是你爬蟲程序強壯與否的關鍵因素,什么是反爬蟲?
當越來越多的爬蟲在互聯網上橫沖直撞后,網頁資源維護者為了防止自身數據被抓取,開始進行一系列的措施來使得自身數據不易被別的程序爬取,這些措施就是反爬蟲
比如檢測IP訪問頻率、資源訪問速度、鏈接是否帶有關鍵參數、驗證碼檢測機器人、ajax混淆、js加密等等
對于目前市場上的反爬蟲,爬蟲工程師常有的反反爬蟲方案是下面這樣的:
不斷試探目標底線,試出單IP下最優的訪問頻率
構建自己的IP代理池
維護一份自己常用的UA庫
針對目標網頁的Cookie池
需要JS渲染的網頁使用無頭瀏覽器進行代碼渲染再抓取
一套破解驗證碼程序
扎實的JS知識來破解混淆函數
爬蟲工程師的進階之路其實就是不斷反反爬蟲,可謂艱辛,但換個角度想也是樂趣所在
關于框架
爬蟲有自己的編寫流程和標準,有了標準,自然就有了框架,像Python這種生態強大的語言,框架自然是多不勝數,目前世面上用的比較多的有:
Scrapy
PySpider
Portia
這里不過多介紹,框架只是工具,是一種提升效率的方式,看你選擇
說明任何事物都有兩面性,爬蟲自然也不例外,因此我送諸位一張圖,關鍵時刻好好想想
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/42963.html
摘要:這篇文章的題目有點大,但這并不是說我自覺對爬蟲這塊有多大見解,我只不過是想將自己的一些經驗付諸于筆,對于如何寫一個爬蟲框架,我想一步一步地結合具體代碼來講述如何從零開始編寫一個自己的爬蟲框架年到如今,我花精力比較多的一個開源項目算是了,這是 showImg(https://segmentfault.com/img/remote/1460000018513379); 這篇文章的題目有點大...
摘要:下面代碼會存在什么問題,如何改進一行代碼輸出之間的所有偶數。簡述進程之間如何通信多路復用的作用模型的區別什么是并發和并行解釋什么是異步非阻塞的作用面試題說說你知道的命令如何查看某次提交修改的內容答案掃碼下面的二維碼訂閱即可獲取。 引言 最近在刷面試題,所以需要看大量的 Python 相關的面試題,從大量的題目中總結了很多的知識,同時也對一些題目進行拓展了,但是在看了網上的大部分面試題不...
摘要:今晨起來翻了翻排行榜,發現前天發的文章早已被擠出全站熱榜,但卻意外發現自己已經站上了作者周榜的亞軍寶座。作為一個草根初習者一個月沖上周榜亞軍實屬不易,也不是我刻意準備想沖榜而全是意外。 今晨起來翻了翻CDSN排行榜,發現前天發的文章早已被擠出全站熱榜,但卻意外發現自己已經站上了作者周榜的亞軍...
摘要:兩日前,發了一篇吐槽,莫名的火了一把。關于的第一個,其實就是聲明一個常量,不允許變更。另外對象迭代這里出自,阮一峰大神寫的入門指南,對象篇。 兩日前,發了一篇吐槽,莫名的火了一把。經過大家的建議與鼓勵,于是修改了簡歷,開始了重新投遞,2天后接到第一份面試邀請。 此文為個人面試經歷,QA問答過程與總結,不透露面試公司及面試人員,內容真實,如果有面試過我的大佬看到博客,歡迎指出問題。 循序...
閱讀 3977·2021-09-22 16:03
閱讀 5309·2021-09-22 15:40
閱讀 1190·2021-09-06 15:02
閱讀 865·2019-08-30 15:53
閱讀 2215·2019-08-29 15:35
閱讀 1105·2019-08-23 18:22
閱讀 3333·2019-08-23 16:06
閱讀 643·2019-08-23 12:27