如何用 Python 實現 Web 抓取?

【編者按】本文做者爲 Blog Bowl 聯合創始人 Shaumik Daityari,主要介紹 Web 抓取技術的基本實現原理和方法。文章系國內 ITOM 管理平臺 OneAPM 編譯呈現,如下爲正文。css

如何用 Python 實現 Web 抓取?

隨着電子商務的蓬勃發展,筆者近年愈來愈着迷於比價應用。我在網絡上(甚至線下)的每次購買,都是在各大電商網站深刻調研後的結果。html

筆者經常使用的比價應用包括:RedLaser, ShopSavvy 以及 BuyHatke。這些應用有效提升了價格透明度,進而爲消費者節省了可觀的時間。html5

可是,你是否想過,這些應用如何獲得那些重要數據?一般,它們會藉助 Web 抓取技術來完成該任務。node

Web 抓取的定義

Web 抓取是抽取網絡數據的過程。只要藉助合適的工具,任何你能看到的數據均可以進行抽取。在本文中,咱們將重點介紹自動化抽取過程的程序,幫助你在較短期內收集大量數據。除了筆者前文提到的用例,抓取技術的用途還包括:SEO 追蹤、工做追蹤、新聞分析以及筆者的最愛——社交媒體的情感分析!python

一點提醒

在開啓 Web 抓取的探險以前,請確保本身瞭解相關的法律問題。許多網站在其服務條款中明確禁止對其內容進行抓取。例如,Medium 網站就寫道:「遵守網站 robots.txt 文件中的規定進行的爬取操做(Crawling)是可接受的,可是咱們禁止抓取(Scraping)操做。」對不容許抓取的網站進行抓取可能會使你進入他們的黑名單!與任何工具同樣,Web 抓取也可能用於複製網站內容之類的不良目的。此外,由 Web 抓取引發的法律訴訟也不在少數。web

設置代碼

在充分了解當心行事的必要以後,讓咱們開始學習 Web 抓取。其實,Web 抓取能夠經過任何編程語言實現,在不久以前,咱們使用 Node 實現過。在本文中,考慮到其簡潔性與豐富的包支持,咱們將使用 Python 實現抓取程序。正則表達式

Web 抓取的基本過程

當你打開網絡中的某個站點時,就會下載其 HTML 代碼,由你的 web 瀏覽器對其進行分析與展現。該 HTML 代碼包含了你所看到的全部信息。所以,經過分析 HTML 代碼就能獲得所需信息(好比價格)。你可使用正則表達式在數據海洋中搜索你須要的信息,也可使用函數庫來解釋 HTML,一樣也能獲得須要數據。數據庫

在 Python 中,咱們將使用一個名爲靚湯(Beautiful Soup)的模塊對 HTML 數據進行分析。你能夠藉助 pip 之類的安裝程序安裝之,運行以下代碼便可:編程

pip install beautifulsoup4

或者,你也能夠根據源碼進行構建。在該模塊的文檔說明頁,能夠看到詳細的安裝步驟。api

安裝完成以後,咱們大體會遵循如下步驟實現 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 檢查器完成。其餘瀏覽器也提供了相似的工具。

如何用 Python 實現 Web 抓取?
使用 Chrome 檢查器檢查某個頁面的 HTML 結構

如你所見,全部文章標題都帶有 h3 標籤與兩個類屬性:post-titleentry-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")

如何用 Python 實現 Web 抓取?
通知頁面的結構

# Print notificationsprint soup.find(class_ = "search_results").text

如何用 Python 實現 Web 抓取?
登陸進通知頁面後的結果

結語

許多開發者會告訴你:你在網絡上看到的任何信息均可以被抓取。經過這篇文章,你學會了如何輕鬆抽取登陸後才能看到的內容。此外,若是你的 IP 遭到了屏蔽,你能夠掩蓋本身的 IP 地址(或選用其餘地址)。同時,爲了看起來像是人類在訪問,你應該在請求之間保留必定的時間間隔。

隨着人們對數據的需求不斷增加,web 抓取(不論緣由好壞)技術在將來的應用只會更加普遍。也所以,理解其原理是至關重要的,無論你是爲了有效利用該技術,仍是爲了免受其坑害。

OneAPM 能幫您查看 Python 應用程序的方方面面,不只可以監控終端的用戶體驗,還能監控服務器性能,同時還支持追蹤數據庫、第三方 API 和 Web 服務器的各類問題。想閱讀更多技術文章,請訪問 OneAPM 官方技術博客

本文轉自 OneAPM 官方博客

原文地址:https://www.sitepoint.com/web-scraping-for-beginners/

相關文章
相關標籤/搜索