Python網絡數據採集入門教程

Python網絡數據採集入門教程

在這篇文章中,我們將介紹Python提供的幾乎所有的網絡數據採集工具,你可以將本文看作是我們的《終極網絡數據採集指南》的系列文章。我們將從最基本的工具到最先進的工具進行介紹,並將涵蓋每一個的利弊。當然,我們並不能涵蓋我們討論的每個工具的所有方面,但是這篇文章應該足以讓你瞭解哪些工具可以做什麼,以及何時使用哪些工具。

注意:當我在這篇博客文章中談論Python時,你應該假設我談論的是Python3。

0)網絡基礎知識

互聯網是非常複雜的: 在瀏覽器中查看一個簡單的網頁涉及到許多底層技術和概念。我並不打算解釋所有的東西,但是為了從網絡中提取數據,我將向你展示一些你必須理解的最重要的東西。

超文本傳輸協議(HTTP)

HTTP使用一個客戶機/服務器模型,其中一個HTTP客戶機(瀏覽器、你的Python程序、curl和Requests等)打開一個連接並向一個HTTP服務器(Nginx和Apache等)發送一條消息(“我想看那個頁面:/product”)。

然後,該服務器使用一個響應(例如HTML代碼)進行回答並關閉連接。HTTP被稱為無狀態協議,因為每個事務(請求/響應)都是獨立的。例如,FTP是有狀態協議。

基本上,當你在瀏覽器中輸入一個網址時,HTTP請求看起來是這樣的:

Python網絡數據採集入門教程

在這個請求的第一行,你可以看到很多東西:

  • 這裡使用了GET 動詞或方法,這表示我們是從特定的路徑(: /product/)請求數據的。還有其他的HTTP動詞,你可以在這裡看到完整的列表。
  • HTTP協議的版本,在本教程中我們將專注HTTP 1.
  • 多個標頭字段

以下是最重要的標頭字段:

  • Host: 服務器的域名,如果沒有指定端口號,則默認為80。
  • User-Agent: 包含客戶端發起的請求的信息,包括操作系統信息。在本例中,它是我的OSX系統上的網絡瀏覽器(Chrome)。這個標頭很重要,因為它要被用於統計(有多少用戶訪問了我的手機網站或桌面網站)或用於防止任何來自機器人的違規行為。因為這些標頭是由客戶端發送的,所以可以對它進行修改(稱為“標頭欺騙”),這正是我們使用scraper所要做的——使scraper看起來像一個普通的網絡瀏覽器。
  • Accept: 可接受的作為響應的內容類型。有很多不同的內容類型和子類型:text/plain、text/html、image/jpeg和application/json等。
  • Cookie : name1=value1;name2=value2... ,此標頭字段包含一個名稱-值對列表。它被稱為會話cookies,用於存儲數據。Cookies是網站用來驗證用戶身份, 和/或在你的瀏覽器中存儲數據的工具。例如,當你填寫了一個登錄表單時,服務器將檢查你輸入的憑據是否正確,如果正確,它將進行重定向並將一個會話cookie注入你的瀏覽器。然後,你的瀏覽器會將此cookie與隨後的每個請求一起發送到該服務器。
  • Referrer: Referrer標頭包含跳轉到實際URL頁面的源URL地址。這個標頭很重要,因為網站使用這個標頭來根據用戶來源來改變自身的行為。例如,許多新聞網站都有付費訂閱,你只能瀏覽文章的10%,但如果用戶來自像Reddit這樣的新聞聚合器,網站就會讓你瀏覽全部內容。它們使用referrer來檢查這個。有時,我們將不得不欺騙這個標頭來獲得我們想要提取的內容。

標頭列表中還有很多字段,你可以在這裡找到完整的標頭列表:https://en.wikipedia.org/wiki/List_of_HTTP_header_fields。

服務器會像這樣進行響應:

Python網絡數據採集入門教程

在第一行,我們有一個新的信息,HTTP代碼 200 OK。這意味著此請求已經成功。對於請求標頭來說,有很多HTTP代碼,分為四個常見類:2XX表示請求成功、3XX表示重定向、4XX表示請求異常(最出名的是404 Not found)和5XX表示服務器錯誤。

然後,如果你使用網絡瀏覽器發送此HTTP請求,瀏覽器將解析HTML代碼,獲取所有最終前端資源(Javascript文件、CSS文件、圖像等),並將結果呈現到主窗口。

在接下來的部分中,我們將看一些使用Python執行HTTP請求,並從響應中提取我們想要的數據的不同方法。

1)手動打開一個socket(套接字)併發送HTTP請求

Socket

在Python中執行HTTP請求的最基本方法是打開一個socket並手動發送HTTP請求。

Python網絡數據採集入門教程

現在我們有了HTTP響應,從它裡面提取數據的最基本方法是使用正則表達式。

正則表達式

正則表達式(RE或Regex)是字符串的搜索模式。使用regex,你可以在一個更大的文本體中搜索特定的字符/單詞。

例如,你可以識別網絡頁面中的所有電話號碼。你還可以替換某些項,例如,你可以將HTML中格式糟糕的所有大寫標記替換為小寫標記。你還可以校驗一些輸入…

正則表達式使用的模式是從左到右應用的。每個源字符只使用一次。你可能想知道為什麼在進行網絡數據挖掘時瞭解正則表達式很重要?

總之,有各種不同的Python模塊可以來解析HTML,你可以使用XPath和CSS選擇器。

在一個理想的語義世界中,數據是易於機器讀取,信息被嵌入到相關的HTML元素中,並帶有有意義的屬性。

但是現實世界是混亂的,你經常會在一個p元素中發現大量的文本。當你想在這個巨大的文本中提取一個特定的數據時,例如價格、日期或名稱等,你必須使用正則表達式。

注意:這裡有一個很棒的網站來測試你的正則表達式: https://regex101.com/ ,和一個很棒的博客(https://www.rexegg.com/ )來了解更多關於它們的信息,這篇文章將只涵蓋你可以使用regexp做的事情的一小部分。

當有這類數據時,正則表達式可以很有用:

Python網絡數據採集入門教程

我們可以使用一個Xpath表達式來選擇這個文本節點,然後使用這種正則表達式來提取價格:

Python網絡數據採集入門教程

要提取一個HTML標記內的文本,使用正則表達式很煩人,但卻是可行的:

Python網絡數據採集入門教程

正如你所看到的,你可以使用一個socket手動發送HTTP請求,並使用正則表達式解析響應,但是這很複雜,而且有更高級的API可以使這項任務更容易。

2) urllib3 和 LXML

免責聲明: 在Python的urllib中很容易迷失方向。urllib和urllib2是標準庫的一部分,你還可以找到urllib3。urllib2在python3中被分成多個模塊,而且urllib3可能隨時就不會成為標準庫的一部分。這整個令人困惑的東西將成為一篇博客文章的主題。在本部分中,我選擇只討論urllib3,因為它在Python世界中被廣泛使用,只舉兩個例子,比如被pip和requests庫使用。

Urllib3一個高級包,它允許你對一個HTTP請求做幾乎任何你想做的事情。它允許我們用更少的代碼行來做上面用socket所做的事情。

Python網絡數據採集入門教程

這比socket版本更簡潔。不僅如此,該API非常簡單易懂,你可以輕鬆地做許多事情,比如添加HTTP標頭、使用代理、POST表單等。

例如,如果我們決定設置一些標頭並使用一個代理,我們只需要這樣做。

Python網絡數據採集入門教程

看到了嗎?完全相同的代碼行數,但是,有一些事情urllib3處理起來並不容易,例如,如果我們想添加一個cookie,我們必須手動創建相應的標頭並將其添加到請求中。

還有一些事情urllib3可以做,但requests做不了。有的事情是requests不能做的,例如池和代理池的創建和管理、重試策略的控制。

簡單地說,urllib3在抽象方面介於requests和socket之間,儘管它比socket更接近requests。

這一次,為了解析響應,我們將使用lxml包和XPath表達式。

XPath

Xpath是一種使用路徑表達式來選擇XML文檔(或HTML文檔)中的節點或節點集的技術。與文檔對象模型一樣,Xpath自1999年以來一直是一個W3C標準。即使Xpath本身不是一種編程語言,但它也允許你編寫可以直接訪問一個特定節點或特定節點集的表達式,而無需遍歷整個HTML樹(或XML樹)。

你可以將XPath看作regexp,但主要是針對XML/HMTL。

要用XPath從一個HTML文檔中提取數據,我們需要三個東西:

  • 一個HTML 文檔
  • 一些XPath 表達式
  • 一個可以運行這些表達式的XPath 引擎

首先,我們將使用由於urllib3所得到的HTML,我們只想從谷歌主頁中提取所有鏈接,因此我們將使用一個簡單的XPath表達式://a,並使用LXML來運行它。LXML是一個支持XPATH的快速且易於使用的XML和HTML處理庫。

安裝:

Python網絡數據採集入門教程

下面是前一段代碼之後的代碼:

Python網絡數據採集入門教程

輸出應該是這樣的:

Python網絡數據採集入門教程

你必須記住,這個示例非常非常簡單,並沒有真正向你展示XPath可以有多麼強大(注意:這個XPath表達式應該改為 //a/@href,以避免必須對links進行迭代才能獲得它們的href)。

如果你想了解更多關於XPath的知識,你可以閱讀這篇很好的介紹(https://librarycarpentry.org/lc-webscraping/02-xpath/index.html )。LXML文檔也編寫得很好,是一個很好的起點(https://lxml.de/tutorial.html )。

XPath表達式(像regexp一樣)非常強大,是從HTML中提取信息的最快方法之一,而且與regexp一樣,XPath很快就會變得混亂、難於閱讀和維護。

3) requests 和 BeautifulSoup

Python網絡數據採集入門教程

Requests是python包中的王者,擁有超過1100萬的下載量,是Python中使用最廣泛的包。

安裝:

Python網絡數據採集入門教程

使用Requests包發出一個請求(沒有評論)真的很簡單:

Python網絡數據採集入門教程

使用Requests可以很容易地執行POST請求,處理cookie,查詢參數…

Hacker News認證

假設我們想要創建一個工具來自動向Hacker news或任何其他論壇(比如Buffer)提交我們的博客文章。在發佈我們的鏈接之前,我們需要對這些網站進行認證。這就是我們要使用Requests 和 BeautifulSoup所做的事情!

下面是Hacker News的登錄表單和相關的DOM:

Python網絡數據採集入門教程

這個表單上有三個 標記,第一個標記有一個隱藏類型和一個“goto”名稱,另外兩個標記是用戶名和密碼。

如果你在你的Chrome瀏覽器中提交此表單,你會看到有很多事情正在發生:一個重定向和一個cookie正在被設置。這個cookie將由Chrome在隨後的每個請求中進行發送,以便服務器知道你是經過身份驗證的。

使用Requests做這些很容易,它將自動為我們處理重定向,並且可以使用Session對象處理cookies。

接下來我們需要的是BeautifulSoup,它是一個Python庫,可以幫助我們解析服務器返回的HTML,以確定我們是否登錄了。

安裝:

Python網絡數據採集入門教程

因此,我們所要做的就是將這三個輸入連同我們的憑證一起POST到/login端點,並檢查是否存在一個只在登錄後才顯示的元素:

Python網絡數據採集入門教程

為了瞭解更多關於BeautifulSoup的信息,我們可以嘗試提取主頁上的每個鏈接。

順便說一下,Hacker News提供了一個功能強大的API,所以我們以它為例,但是你應該使用這個API而不是進行抓取!

我們需要做的第一件事是檢查Hacker New的主頁,以瞭解我們將必須選擇的結構和不同的CSS類:

我們可以看到所有的文章都在一個

中,所以我們需要做的第一件事就是選擇所有這些標記。這使用以下代碼可以很容易做到:
Python網絡數據採集入門教程

然後對於每個鏈接,我們將提取它的id, title, url和rank:

Python網絡數據採集入門教程

正如你所看到的,Requests和BeautifulSoup是通過發佈表單來提取數據和自動化不同內容的優秀庫。如果你想做大規模的網絡數據挖據項目,你仍然可以使用Requests,但是你需要自己處理很多事情。

當你需要抓取很多網頁時,有很多事情你必須處理:

  • 找到一種並行化代碼的方法使其更快
  • 處理錯誤
  • 存儲結果
  • 過濾結果
  • 終止你的請求避免服務器過載

幸運的是,有一些工具可以為我們處理這些事情。

4) Scrapy

Python網絡數據採集入門教程

Scrapy是一個功能強大的Python 數據挖掘框架。它提供了許多功能來異步下載網絡頁面、處理和保存它。它能處理多線程、爬行(從一個鏈接到另一個鏈接以找到網站中的每個URL的過程)、站點地圖爬行等等。

Scrapy還有一種交互模式,稱為Scrapy Shell。使用Scrapy Shell,你可以非常快速地測試你的抓取代碼,比如XPath表達式或CSS選擇器。

Scrapy的缺點是它的學習曲線陡峭,需要學習的東西很多。

為了繼續我們關於Hacker news的示例,我們將編寫一個Scrapy Spider,它將抓取前15頁的結果,並將所有內容保存在一個CSV文件中。

你可以使用pip輕鬆安裝Scrapy:

Python網絡數據採集入門教程

然後你可以使用scrapy 命令行為我們的項目生成樣板代碼:

Python網絡數據採集入門教程

在hacker_news_scraper/spider中,我們將使用我們的爬蟲的代碼創建一個新的python文件:

Python網絡數據採集入門教程

在Scrapy中有很多約定,這裡我們定義了一個起始url數組。我們將通過Scrapy命令行使用屬性名來調用我們的Spider。

我們將在start_urls數組中的每個URL上調用解析方法:

然後,我們需要稍微調整一下Scrapy,以便我們的爬蟲在目標網站上表現良好。

Python網絡數據採集入門教程

你應該始終打開這個選項,它將通過分析響應時間和調整併發線程的數量來確保目標網站不會被你的爬蟲拖慢。

你可以使用Scrapy CLI並以不同的輸出格式(CSV, JSON, XML…)來運行這段代碼:

Python網絡數據採集入門教程

就是它!現在,你的所有鏈接都保存在一個格式良好的JSON文件中。

5) Selenium 和 Chrome—無UI模式

對於大規模的網絡抓取任務來說,Scrapy確實很好,但是如果你需要抓取用Javascript框架編寫的單頁面應用程序,那麼它就沒那麼好了,因為它無法呈現Javascript代碼。

抓取這些SPA可能很有挑戰性,因為它們通常涉及許多AJAX調用和websockets連接。如果性能是一個問題,你應該總是會嘗試重新生成Javascript代碼,這意味著你要使用瀏覽器檢查器手動檢查所有網絡調用,並複製包含有趣數據的AJAX調用。

在某些情況下,要獲得所需的數據涉及到太多的異步HTTP調用,而在無UI瀏覽器中呈現頁面可能更容易一些。

另一個很好的用例是對一個頁面進行截屏,這就是我們要對Hacker News主頁做的(再次!)

你可以使用pip安裝selenium包:

Python網絡數據採集入門教程

你還需要Chromedriver:

Python網絡數據採集入門教程

然後我們只需從selenium包中導入Webdriver,用headless=True配置Chrome,並設置窗口大小(不然截圖會非常小):

Python網絡數據採集入門教程

你應該會得到一個很好的主頁截圖:

你可以使用Selenium API和Chrome做更多的事情,比如:

  • 執行 Javascript
  • 填寫表單
  • 在元素上進行點擊
  • 使用CSS選擇器/ XPath表達式提取元素

Selenium和無UI模式下的Chrome是抓取你想要的任何信息的終極組合。你可以自動化任何你使用普通的Chrome瀏覽器所做的事情。

最大的缺點是Chrome需要大量的內存/ CPU性能。通過一些微調,你可以將每個Chrome實例的內存佔用減少到300-400mb,但每個實例仍然需要一個CPU核心。

如果你想同時運行幾個Chrome實例,你需要強大的服務器(成本會迅速上升)和持續的資源監控。

結論

下面是我們在本文中討論的每種技術的一個快速回顧表。如果你知道一些與本文相關的資源,請在評論中告訴我們。

Python網絡數據採集入門教程

我希望本文的概述能夠幫助你有效地選擇Python數據挖掘工具,並希望你在閱讀本文時能夠學到一些東西。

我在這篇文章中討論的所有內容都是我用來構建ScrapingNinja的東西,也就是這裡提到的最簡單的網絡數據挖掘API。如果你不想浪費太多的時間設置一切的話,就趕緊去測試我們的解決方案吧,第一個1k 次API調用是免費的!

我在這篇文章中提到的每一個工具都將是我未來的一個特定博文的主題,我將在其中進行詳細討論。

不要猶豫,請及時在評論中告訴我你想知道關於數據挖掘的什麼知識,我將在下一篇文章中討論它。

爬爬更健康!~

英文原文:https://www.daolf.com/posts/web-scraping-101-python/

"


分享到:


相關文章: