引言
在過去,收集數(shù)據(jù)是一項(xiàng)繁瑣的工作,有時(shí)非常昂貴。機(jī)器學(xué)習(xí)項(xiàng)目不能沒有數(shù)據(jù)。幸運(yùn)的是,我們現(xiàn)在在網(wǎng)絡(luò)上有很多數(shù)據(jù)可供我們使用。我們可以從 Web 復(fù)制數(shù)據(jù)來創(chuàng)建數(shù)據(jù)集。我們可以手動下載文件并將其保存到磁盤。但是,我們可以通過自動化數(shù)據(jù)收集來更有效地做到這一點(diǎn)。Python中有幾種工具可以幫助自動化。
完成本教程后,您將學(xué)習(xí):
- 如何使用
requests
庫通過 HTTP 讀取網(wǎng)絡(luò)數(shù)據(jù) - 如何使用
pandas
讀取網(wǎng)頁上的表格 - 如何使用
Selenium
模擬瀏覽器操作
概述
本教程分為三個(gè)部分;它們是:
- 使用
requests
庫 - 使用
panda
在網(wǎng)絡(luò)上閱讀表格 - 用
selenium
閱讀動態(tài)內(nèi)容
使用requests庫
當(dāng)我們談?wù)摼帉慞ython程序從Web上讀取時(shí),不可避免的是我們無法避免requests
庫。您需要安裝它(以及我們稍后將介紹的BeautifulSoup和lxml):
pip install requests beautifulsoup4 lxml
它為您提供了一個(gè)界面,可讓您輕松與網(wǎng)絡(luò)進(jìn)行交互。
非常簡單的用例是從URL讀取網(wǎng)頁:
import requests
# Lat-Lon of New York
URL = "https://weather.com/weather/today/l/40.75,-73.98"
resp = requests.get(URL)
print(resp.status_code)
print(resp.text)
運(yùn)行結(jié)果:
如果您熟悉 HTTP,您可能還記得狀態(tài)代碼 200 表示請求已成功完成。然后我們可以閱讀響應(yīng)。在上面,我們閱讀文本響應(yīng)并獲取網(wǎng)頁的HTML。如果它是CSV或其他一些文本數(shù)據(jù),我們可以在響應(yīng)對象的屬性中獲取它們。例如text
,這就是我們從美聯(lián)儲經(jīng)濟(jì)學(xué)數(shù)據(jù)中讀取CSV的方法:
以下例子會用到pandas 模塊 :
安裝: pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple
import io
import pandas as pd
import requests
URL = "https://fred.stlouisfed.org/graph/fredgraph.csv?id=T10YIE&cosd=2017-04-14&coed=2022-04-14"
resp = requests.get(URL)
if resp.status_code == 200:
csvtext = resp.text
csvbuffer = io.StringIO(csvtext)
df = pd.read_csv(csvbuffer)
print(df)
運(yùn)行結(jié)果:
如果數(shù)據(jù)是JSON的形式,我們可以將其讀取為文本,甚至可以為您解碼。例如,以下是以JSON格式從GitHub中提取一些數(shù)據(jù)并將其轉(zhuǎn)換為Python字典:
import requests
URL = "https://api.github.com/users/jbrownlee"
resp = requests.get(URL)
if resp.status_code == 200:
data = resp.json()
print(data)
運(yùn)行結(jié)果:
但是,如果 URL 為您提供了一些二進(jìn)制數(shù)據(jù),例如 ZIP 文件或 JPEG 圖像,則需要在屬性中獲取它們,因?yàn)檫@將是二進(jìn)制數(shù)據(jù)。例如,這就是我們下載圖像(維基百科的標(biāo)志)的方式:
import requests
URL = "https://en.wikipedia.org/static/images/project-logos/enwiki.png"
wikilogo = requests.get(URL)
if wikilogo.status_code == 200:
with open("enwiki.png", "wb") as fp:
fp.write(wikilogo.content)
運(yùn)行結(jié)果:
鑒于我們已經(jīng)獲得了網(wǎng)頁,我們應(yīng)該如何提取數(shù)據(jù)?這超出了requests
所能提供給我們的范圍,但我們可以使用不同的library 來提供幫助。有兩種方法可以做到這一點(diǎn),這取決于我們想要如何指定數(shù)據(jù)。
第一種方法是將 HTML 視為一種 XML 文檔,并使用 XPath 語言提取元素。在這種情況下,我們可以利用該庫首先創(chuàng)建一個(gè)文檔對象模型(DOM),然后通過XPath進(jìn)行搜索:
import requests
from lxml import etree
URL = "https://weather.com/weather/today/l/40.75,-73.98"
resp = requests.get(URL)
# 從HTML文本創(chuàng)建DOM
dom = etree.HTML(resp.text)
# 搜索溫度元素并獲得內(nèi)容
elements = dom.xpath("http://span[@data-testid='TemperatureValue' and contains(@class,'CurrentConditions')]")
print(elements[0].text)
XPath 是一個(gè)字符串,它指定如何查找元素。lxml 對象提供了一個(gè)函數(shù),用于在 DOM 中搜索與 XPath 字符串匹配的元素,這些元素可以是多個(gè)匹配項(xiàng)。上面的 XPath 意味著在具有標(biāo)記和屬性與 “” 匹配且以 “” 開頭的任何位置查找 HTML 元素。我們可以通過檢查HTML源代碼從瀏覽器的開發(fā)人員工具(例如,下面的Chrome屏幕截圖)中學(xué)習(xí)這一點(diǎn)。xpath()``<span>``data-testid``TemperatureValue``class``CurrentConditions
這個(gè)例子是找到紐約市的溫度,由我們從這個(gè)網(wǎng)頁獲得的這個(gè)特定元素提供。我們知道與 XPath 匹配的第一個(gè)元素是我們需要的,我們可以讀取標(biāo)記內(nèi)的文本。<span>
另一種方法是在HTML文檔上使用CSS選擇器,我們可以利用BeautifulSoup庫:
import requests
from bs4 import BeautifulSoup
URL = "https://weather.com/weather/today/l/40.75,-73.98"
resp = requests.get(URL)
soup = BeautifulSoup(resp.text, "lxml")
elements = soup.select('span[data-testid="TemperatureValue"][class^="CurrentConditions"]')
print(elements[0].text)
運(yùn)行結(jié)果:
在上面,我們首先將HTML文本傳遞給BeautifulSoup。BeautifulSoup支持各種HTML解析器,每個(gè)解析器具有不同的功能。在上面,我們使用庫作為BeautifulSoup推薦的解析器(它通常也是最快的)。CSS選擇器是一種不同的迷你語言,與XPath相比有優(yōu)點(diǎn)和缺點(diǎn)。上面的選擇器與我們在上一個(gè)示例中使用的 XPath 相同。因此,我們可以從第一個(gè)匹配的元素中獲得相同的溫度。
以下是根據(jù)網(wǎng)絡(luò)上的實(shí)時(shí)信息打印紐約當(dāng)前溫度的完整代碼:
import requests
from bs4 import BeautifulSoup
from lxml import etree
URL = "https://weather.com/weather/today/l/40.75,-73.98"
resp = requests.get(URL)
if resp.status_code == 200:
# Using lxml
dom = etree.HTML(resp.text)
elements = dom.xpath("http://span[@data-testid='TemperatureValue' and contains(@class,'CurrentConditions')]")
print(elements[0].text)
# Using BeautifulSoup
soup = BeautifulSoup(resp.text, "lxml")
elements = soup.select('span[data-testid="TemperatureValue"][class^="CurrentConditions"]')
print(elements[0].text)
可以想象,您可以通過定期運(yùn)行此腳本來收集溫度的時(shí)間序列。同樣,我們可以從各種網(wǎng)站自動收集數(shù)據(jù)。這就是我們?yōu)闄C(jī)器學(xué)習(xí)項(xiàng)目獲取數(shù)據(jù)的方法。
使用 panda 在網(wǎng)絡(luò)上閱讀表格
通常,網(wǎng)頁將使用表格來承載數(shù)據(jù)。如果頁面足夠簡單,我們甚至可以跳過檢查它以找出XPath或CSS選擇器,并使用pandas一次性獲取頁面上的所有表格。它很簡單,可以在一行中完成:
import pandas as pd
tables = pd.read_html("https://www.federalreserve.gov/releases/h10/current/")
print(tables)
[ Instruments 2022Apr7 2022Apr8 2022Apr11 2022Apr12 2022Apr13
0 Federal funds (effective) 1 2 3 0.33 0.33 0.33 0.33 0.33
1 Commercial Paper 3 4 5 6 NaN NaN NaN NaN NaN
2 Nonfinancial NaN NaN NaN NaN NaN
3 1-month 0.30 0.34 0.36 0.39 0.39
4 2-month n.a. 0.48 n.a. n.a. n.a.
5 3-month n.a. n.a. n.a. 0.78 0.78
6 Financial NaN NaN NaN NaN NaN
7 1-month 0.49 0.45 0.46 0.39 0.46
8 2-month n.a. n.a. 0.60 0.71 n.a.
9 3-month 0.85 0.81 0.75 n.a. 0.86
10 Bank prime loan 2 3 7 3.50 3.50 3.50 3.50 3.50
11 Discount window primary credit 2 8 0.50 0.50 0.50 0.50 0.50
12 U.S. government securities NaN NaN NaN NaN NaN
13 Treasury bills (secondary market) 3 4 NaN NaN NaN NaN NaN
14 4-week 0.21 0.20 0.21 0.19 0.23
15 3-month 0.68 0.69 0.78 0.74 0.75
16 6-month 1.12 1.16 1.22 1.18 1.17
17 1-year 1.69 1.72 1.75 1.67 1.67
18 Treasury constant maturities NaN NaN NaN NaN NaN
19 Nominal 9 NaN NaN NaN NaN NaN
20 1-month 0.21 0.20 0.22 0.21 0.26
21 3-month 0.68 0.70 0.77 0.74 0.75
22 6-month 1.15 1.19 1.23 1.20 1.20
23 1-year 1.78 1.81 1.85 1.77 1.78
24 2-year 2.47 2.53 2.50 2.39 2.37
25 3-year 2.66 2.73 2.73 2.58 2.57
26 5-year 2.70 2.76 2.79 2.66 2.66
27 7-year 2.73 2.79 2.84 2.73 2.71
28 10-year 2.66 2.72 2.79 2.72 2.70
29 20-year 2.87 2.94 3.02 2.99 2.97
30 30-year 2.69 2.76 2.84 2.82 2.81
31 Inflation indexed 10 NaN NaN NaN NaN NaN
32 5-year -0.56 -0.57 -0.58 -0.65 -0.59
33 7-year -0.34 -0.33 -0.32 -0.36 -0.31
34 10-year -0.16 -0.15 -0.12 -0.14 -0.10
35 20-year 0.09 0.11 0.15 0.15 0.18
36 30-year 0.21 0.23 0.27 0.28 0.30
37 Inflation-indexed long-term average 11 0.23 0.26 0.30 0.30 0.33,
pandas 中的函數(shù)read_html()
讀取 URL 并查找頁面上的所有表。每個(gè)表都轉(zhuǎn)換為 pandas DataFrame,然后在列表中返回所有表。在這個(gè)例子中,我們正在閱讀美聯(lián)儲的各種利率,而美聯(lián)儲恰好在這個(gè)頁面上只有一個(gè)表格。表列由 pandas 自動標(biāo)識。
很可能并非所有表格都是我們感興趣的。有時(shí),網(wǎng)頁會使用表格作為格式化頁面的一種方式,但熊貓可能不夠聰明, 無法分辨。因此,我們需要測試并挑選函數(shù)返回的結(jié)果。
用硒閱讀動態(tài)內(nèi)容
現(xiàn)代網(wǎng)頁的很大一部分充滿了JavaScript。這給了我們一個(gè)更奇特的體驗(yàn),但成為一個(gè)障礙,用作提取數(shù)據(jù)的程序。一個(gè)例子是雅虎的主頁,如果我們只加載頁面并找到所有新聞標(biāo)題,那么在瀏覽器上看到的要少得多:
import requests
# Read Yahoo home page
from lxml import etree
URL = "https://www.yahoo.com/"
resp = requests.get(URL)
dom = etree.HTML(resp.text)
# Print news headlines
elements = dom.xpath("http://h3/a[u[@class='StretchedBox']]")
for elem in elements:
print(etree.tostring(elem, method="text", encoding="unicode"))
運(yùn)行結(jié)果:
這是因?yàn)橄襁@樣的網(wǎng)頁依靠JavaScript來填充內(nèi)容。著名的Web框架,如AngularJS或React,是這一類別的幕后推手。Python 庫,比如requests
,不理解 JavaScript。因此,您將看到不同的結(jié)果。如果你想從網(wǎng)上獲取的數(shù)據(jù)就是其中之一,你可以研究JavaScript是如何被調(diào)用的,并在你的程序中模仿瀏覽器的行為。但這可能太乏味了,無法使其正常工作。
另一種方法是要求真正的瀏覽器讀取網(wǎng)頁,而不是使用requests
。這就是selenium
可以做的。在使用它之前,我們需要安裝庫:
pip install selenium
但Selenium只是一個(gè)控制瀏覽器的框架。您需要在計(jì)算機(jī)上安裝瀏覽器以及將Selenium連接到瀏覽器的驅(qū)動程序。如果您打算使用Chrome,則還需要下載并安裝ChromeDriver。您需要將驅(qū)動程序chromedriver
放在可執(zhí)行路徑中,以便Selenium可以像普通命令一樣調(diào)用它。
同樣,如果你使用的是Firefox,你需要GeckoDriver。有關(guān)設(shè)置Selenium的更多詳細(xì)信息,請參閱其文檔。
之后,您可以使用 Python 腳本來控制瀏覽器行為。例如:
import time
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
# Launch Chrome browser in headless mode
options = webdriver.ChromeOptions()
options.add_argument("headless")
browser = webdriver.Chrome(options=options)
# Load web page
browser.get("https://www.yahoo.com")
# Network transport takes time. Wait until the page is fully loaded
def is_ready(browser):
return browser.execute_script(r"""
return document.readyState === 'complete'
""")
WebDriverWait(browser, 30).until(is_ready)
# Scroll to bottom of the page to trigger JavaScript action
browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(1)
WebDriverWait(browser, 30).until(is_ready)
# Search for news headlines and print
elements = browser.find_elements(By.XPATH, "http://h3/a[u[@class='StretchedBox']]")
for elem in elements:
print(elem.text)
# Close the browser once finish
browser.close()
上述代碼的工作原理如下。我們首先以無外設(shè)模式啟動瀏覽器,這意味著我們要求Chrome啟動但不顯示在屏幕上。如果我們想遠(yuǎn)程運(yùn)行腳本,這很重要,因?yàn)榭赡軟]有任何GUI支持。請注意,每個(gè)瀏覽器的開發(fā)方式都不同,因此我們使用的選項(xiàng)語法特定于Chrome。如果我們使用Firefox,代碼將是這樣的:
options = webdriver.FirefoxOptions()
options.set_headless()
browser = webdriver.Firefox(firefox_options=options)
啟動瀏覽器后,我們會為其提供一個(gè)要加載的 URL。但是,由于網(wǎng)絡(luò)需要時(shí)間來交付頁面,并且瀏覽器需要時(shí)間來呈現(xiàn)它,因此我們應(yīng)該等到瀏覽器準(zhǔn)備就緒后再繼續(xù)下一個(gè)操作。我們檢測瀏覽器是否已經(jīng)使用 JavaScript 完成了渲染。我們讓Selenium為我們運(yùn)行JavaScript代碼,并使用該函數(shù)告訴我們結(jié)果。我們利用Selenium的工具運(yùn)行它,直到它成功或直到30秒超時(shí)。加載頁面時(shí),我們滾動到頁面底部,以便可以觸發(fā)JavaScript以加載更多內(nèi)容。然后,我們無條件地等待一秒鐘,以確保瀏覽器觸發(fā)了JavaScript,然后等待頁面再次準(zhǔn)備就緒。之后,我們可以使用XPath(或者使用CSS選擇器)提取新聞標(biāo)題元素。由于瀏覽器是外部程序,因此我們負(fù)責(zé)在腳本中關(guān)閉它。
使用硒在幾個(gè)方面與使用庫不同。首先,您永遠(yuǎn)不會直接在Python代碼中擁有Web內(nèi)容。相反,您可以在需要時(shí)引用瀏覽器的內(nèi)容。因此,該函數(shù)返回的Web元素引用外部瀏覽器內(nèi)部的對象,因此在完成使用它們之前,我們不得關(guān)閉瀏覽器。其次,所有操作都應(yīng)基于瀏覽器交互而不是網(wǎng)絡(luò)請求。因此,您需要通過模擬鍵盤和鼠標(biāo)移動來控制瀏覽器。但作為回報(bào),您擁有支持JavaScript的全功能瀏覽器。例如,您可以使用 JavaScript 檢查頁面上某個(gè)元素的大小和位置,只有在呈現(xiàn) HTML 元素后,您才會知道這些大小和位置。
Selenium框架提供了更多功能,我們可以在這里介紹。它功能強(qiáng)大,但是由于它連接到瀏覽器,因此使用它比庫的要求更高,并且速度要慢得多。通常,這是從網(wǎng)絡(luò)收集信息的最后手段。文章來源:http://www.zghlxwxcb.cn/news/detail-403807.html
延伸閱讀
Python中另一個(gè)著名的Web爬行庫,我們上面沒有介紹過,那就是Scrapy。這就像將requests
庫與BeautifulSoup合并為一體一樣。網(wǎng)絡(luò)協(xié)議很復(fù)雜。有時(shí)我們需要管理網(wǎng)絡(luò) cookie 或使用 POST 方法為請求提供額外的數(shù)據(jù)。所有這些都可以通過具有不同函數(shù)或額外參數(shù)的請求庫來完成。以下是一些資源供您深入了解:文章來源地址http://www.zghlxwxcb.cn/news/detail-403807.html
到了這里,關(guān)于python 爬蟲熱身篇 使用 requests 庫通過 HTTP 讀取網(wǎng)絡(luò)數(shù)據(jù),使用 pandas 讀取網(wǎng)頁上的表格,使用 Selenium 模擬瀏覽器操作的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!