如何用 Python 實現 Web 抓取?
【編者按】本文作者為 Blog Bowl 聯合創始人 Shaumik Daityari,主要介紹 Web 抓取技術的基本實現原理和方法。文章系國內 ITOM 管理平臺 OneAPM 編譯呈現,以下為正文。
隨著電子商務的蓬勃發展,筆者近年越來越著迷於比價應用。我在網路上(甚至線下)的每次購買,都是在各大電商網站深入調研後的結果。
筆者常用的比價應用包括:RedLaser, ShopSavvy 以及 BuyHatke。這些應用有效提高了價格透明度,進而為消費者節省了可觀的時間。
但是,你是否想過,這些應用如何得到那些重要資料?通常,它們會藉助 Web 抓取技術來完成該任務。
Web 抓取的定義
Web 抓取是抽取網路資料的過程。只要藉助合適的工具,任何你能看到的資料都可以進行抽取。在本文中,我們將重點介紹自動化抽取過程的程式,幫助你在較短時間內收集大量資料。除了筆者前文提到的用例,抓取技術的用途還包括:SEO 追蹤、工作追蹤、新聞分析以及筆者的最愛——社交媒體的情感分析!
一點提醒
在開啟 Web 抓取的探險之前,請確保自己瞭解相關的法律問題。許多網站在其服務條款中明確禁止對其內容進行抓取。例如,Medium 網站就寫道:“遵照網站 robots.txt 檔案中的規定進行的爬取操作(Crawling)是可接受的,但是我們禁止抓取(Scraping)操作。”對不允許抓取的網站進行抓取可能會使你進入他們的黑名單!與任何工具一樣,Web 抓取也可能用於複製網站內容之類的不良目的。此外,由 Web 抓取引起的法律訴訟也不在少數。
設定程式碼
在充分了解小心行事的必要之後,讓我們開始學習 Web 抓取。其實,Web 抓取可以通過任何程式語言實現,在不久之前,我們使用 Node 實現過。在本文中,考慮到其簡潔性與豐富的包支援,我們將使用 Python 實現抓取程式。
Web 抓取的基本過程
當你開啟網路中的某個站點時,就會下載其 HTML 程式碼,由你的 web 瀏覽器對其進行分析與展示。該 HTML 程式碼包含了你所看到的所有資訊。因此,通過分析 HTML 程式碼就能得到所需資訊(比如價格)。你可以使用正規表示式在資料海洋中搜尋你需要的資訊,也可以使用函式庫來解釋 HTML,同樣也能得到需要資料。
在 Python 中,我們將使用一個名為靚湯(Beautiful Soup)的模組對 HTML 資料進行分析。你可以藉助 pip 之類的安裝程式安裝之,執行如下程式碼即可:
pip install beautifulsoup4
或者,你也可以根據原始碼進行構建。在該模組的文件說明頁,可以看到詳細的安裝步驟。
安裝完成之後,我們大致會遵循以下步驟實現 web 抓取:
- 向 URL 傳送請求
- 接收響應
- 分析響應以尋找所需資料
作為演示,我們將使用筆者的部落格 http://dada.theblogbowl.in/
. 作為目標 URL。
前兩個步驟相對簡單,可以這樣完成:
from urllib import urlopen#Sending the http requestwebpage = urlopen('http://my_website.com/').read()
接下來,將響應傳給之前安裝的模組:
from bs4 import BeautifulSoup#making the soup! yummy ;)soup = BeautifulSoup(webpage, "html5lib")
請注意,此處我們選擇了 html5lib
作為解析器。根據 BeautifulSoup 的文件,你也可以為其選擇不同的解析器。
解析 HTML
在將 HTML 傳給 BeautifulSoup 之後,我們可以嘗試一些指令。譬如,檢查 HTML 標記程式碼是否正確,可以驗證該頁面的標題(在 Python 直譯器中):
>>> soup.title<title>Transcendental Tech Talk</title>>>> soup.title.text
u'Transcendental Tech Talk'
>>>
接下來,開始抽取頁面中的特定元素。譬如,我想抽取部落格中文章標題的列表。為此,我需要分析 HTML 的結構,這一點可以藉助 Chrome 檢查器完成。其他瀏覽器也提供了類似的工具。
使用 Chrome 檢查器檢查某個頁面的 HTML 結構
如你所見,所有文章標題都帶有 h3
標籤與兩個類屬性:post-title
與 entry-title
類。因此,用 post-title
類搜尋所有 h3
元素就能得到該頁的文章標題列表。在此例中,我們使用 BeautifulSoup 提供的 find_all
函式,並通過 class_
引數確定所需的類:
>>> titles = soup.find_all('h3', class_ = 'post-title') #Getting all titles>>> titles[0].textu'\nKolkata #BergerXP IndiBlogger meet, Marketing Insights, and some Blogging Tips\n'>>>
只通過 post-title
類進行條目搜尋應該可以得到相同的結果:
>>> titles = soup.find_all(class_ = 'post-title') #Getting all items with class post-title>>> titles[0].textu'\nKolkata #BergerXP
IndiBlogger meet, Marketing Insights, and some Blogging Tips\n'>>>
如果你想進一步瞭解條目所指的連結,可以執行下面的程式碼:
>>> for title in titles:... # Each title is in the form of <h3 ...><a href=...>Post Title<a/></h3>... print title.find("a").get("href")...http://dada.theblogbowl.in/2015/09/kolkata-bergerxp-indiblogger-meet.html
http://dada.theblogbowl.in/2015/09/i-got-published.html
http://dada.theblogbowl.in/2014/12/how-to-use-requestput-or-requestdelete.html
http://dada.theblogbowl.in/2014/12/zico-isl-and-atk.html...>>>
BeautifulSoup 內建了許多方法,可以幫助你玩轉 HTML。其中一些方法列舉如下:
>>> titles[0].contents
[u'\n', <a href="http://dada.theblogbowl.in/2015/09/kolkata-bergerxp-indiblogger-meet.html">Kolkata #BergerXP IndiBlogger meet, Marketing Insights, and some Blogging Tips</a>, u'\n']>>>
請注意,你也可以使用 children
屬性,不過它有點像生成器:
>>> titles[0].parent<div class="post hentry uncustomized-post-template">\n<a name="6501973351448547458"></a>\n<h3 class="post-title entry-title">\n<a href="http://dada.theblogbowl.in/2015/09/kolkata-bergerxp-indiblogger-meet.html">Kolkata #BergerXP IndiBlogger ...
>>>
你也可以使用正規表示式搜尋 CSS 類,對此,本文件有詳細的介紹。
使用 Mechanize 模擬登入
目前為止,我們做的只是下載一個頁面進而分析其內容。然而,web 開發者可能遮蔽了非瀏覽器發出的請求,或者有些網站內容只能在登入之後讀取。那麼,我們該如何處理這些情況呢?
對於第一種情況,我們需要在向頁面傳送請求時模擬一個瀏覽器。每個 HTTP 請求都包含一些相關的資料頭(header),其中包含了訪客瀏覽器、作業系統以及螢幕大小之類的資訊。我們可以改變這些資料頭,偽裝為瀏覽器傳送請求。
至於第二種情況,為了訪問帶有訪客限制的內容,我們需要登入該網站,使用 cookie 保持會話。下面,讓我們來看看在偽裝成瀏覽器的同時,如何完成這一點。
我們將藉助 cookielib
模組使用 cookie 管理會話。此外,我們還將用到 mechanize
,後者可以使用 pip 之類的安裝程式進行安裝。
我們會通過 Blog Bowl 這個頁面進行登入,並訪問通知頁面。下面的程式碼通過行內註釋進行了解釋:
import mechanize
import cookielib
from urllib import urlopen
from bs4 import BeautifulSoup# Cookie Jarcj = cookielib.LWPCookieJar()
browser = mechanize.Browser()
browser.set_cookiejar(cj)
browser.set_handle_robots(False)
browser.set_handle_redirect(True)# Solving issue #1 by emulating a browser by adding HTTP headersbrowser.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')]# Open Login Pagebrowser.open("http://theblogbowl.in/login/")# Select Login form (1st form of the page)browser.select_form(nr = 0)# Alternate syntax - browser.select_form(name = "form_name")# The first <input> tag of the form is a CSRF token# Setting the 2nd and 3rd tags to email and passwordbrowser.form.set_value("email@example.com", nr=1)
browser.form.set_value("password", nr=2)# Logging inresponse = browser.submit()# Opening new page after loginsoup = BeautifulSoup(browser.open('http://theblogbowl.in/notifications/').read(), "html5lib")
通知頁面的結構
# Print notificationsprint soup.find(class_ = "search_results").text
登入進通知頁面後的結果
結語
許多開發者會告訴你:你在網路上看到的任何資訊都可以被抓取。通過這篇文章,你學會了如何輕鬆抽取登入後才能看到的內容。此外,如果你的 IP 遭到了遮蔽,你可以掩蓋自己的 IP 地址(或選用其他地址)。同時,為了看起來像是人類在訪問,你應該在請求之間保留一定的時間間隔。
隨著人們對資料的需求不斷增長,web 抓取(不論原因好壞)技術在未來的應用只會更加廣泛。也因此,理解其原理是相當重要的,不管你是為了有效利用該技術,還是為了免受其坑害。
OneAPM 能幫您檢視 Python 應用程式的方方面面,不僅能夠監控終端的使用者體驗,還能監控伺服器效能,同時還支援追蹤資料庫、第三方 API 和 Web 伺服器的各種問題。想閱讀更多技術文章,請訪問 OneAPM 官方技術部落格。
本文轉自 OneAPM 官方部落格
原文地址:https://www.sitepoint.com/web-scraping-for-beginners/
相關文章
- 使用python進行web抓取PythonWeb
- 如何用Python爬資料?(一)網頁抓取Python網頁
- Python實現拼多多商品資訊抓取方法Python
- 如何用Web Scraper抓取巨潮資訊網全站樂視相關pdf檔案Web
- 如何用python實現郵箱傳送資訊Python
- 萌新如何用Python實現人臉替換?Python
- 如何用 Java 實現 Web 應用中的定時任務?JavaWeb
- 如何用 Downie 自定義模式抓取視訊模式
- 如何用OpenCV在Python中實現人臉檢測OpenCVPython
- 如何用Python實現多工版的udp聊天器PythonUDP
- 萬字教你如何用 Python 實現線性規劃Python
- 如何用Python實現iPhone X的人臉解鎖功能?PythoniPhone
- 自學python一週,看我如何用python實現黑客帝國字母雨Python黑客
- Python實現簡單網頁圖片抓取完整程式碼例項Python網頁
- 用python實現的抓取騰訊視訊所有電影的爬蟲Python爬蟲
- 如何用iptables實現NAT(zt)
- Python Web實戰:Python+Django+MySQL實現基於Web版的增刪改查PythonWebDjangoMySql
- Python培訓分享:python如何用cookie實現自動模擬登入?PythonCookie
- 如何用 Python 實現超級瑪麗的介面和狀態機?Python
- 教你如何用python實現學生通訊錄管理系統Python
- golang實現抓取IP地址的蜘蛛程式Golang
- 如何用Redis實現搜尋介面Redis
- 如何用 Redis 實現分散式鎖Redis分散式
- 如何用 UDP 實現可靠傳輸?UDP
- 如何用css實現"等高佈局"。CSS
- python抓取網頁Python網頁
- 用Delphi實現遠端螢幕抓取 (轉)
- python使用JWT(json web token)實現驗證PythonJWTJSONWeb
- 如何用Python爬蟲實現百度圖片自動下載?Python爬蟲
- 如何用html實現圓形雲臺HTML
- 教你如何用 Java 實現非同步呼叫Java非同步
- 面試官:如何用LinkedHashMap實現LRU面試HashMap
- 如何用RabbitMQ實現延遲佇列MQ佇列
- 如何用JavaScript實現2+2=5?JavaScript
- 如何用es5實現繼承繼承
- 如何用Go快速實現規則引擎Go
- 如何用Css3實現Switch元件CSSS3元件
- 如何用canvas實現大波紋灌水效果Canvas