Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 欧美一区二区三区四区视频,1024.1024亚洲国产图片,亚洲小视频网站

          整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          用node.js實現(xiàn)一個網(wǎng)頁爬蟲

          文講解怎樣用 Node.js 高效地從 Web 爬取數(shù)據(jù)。

          前提條件

          本文主要針對具有一定 JavaScript 經(jīng)驗的程序員。如果你對 Web 抓取有深刻的了解,但對 JavaScript 并不熟悉,那么本文仍然能夠?qū)δ阌兴鶐椭?/p>

          • ? 會 JavaScript
          • ? 會用 DevTools 提取元素選擇器
          • ? 會一些 ES6 (可選)

          你將學(xué)到

          通過本文你將學(xué)到:

          • 學(xué)到更多關(guān)于 Node.js 的東西
          • 用多個 HTTP 客戶端來幫助 Web 抓取的過程
          • 利用多個經(jīng)過實踐考驗過的庫來爬取 Web

          了解 Node.js

          Javascript 是一種簡單的現(xiàn)代編程語言,最初是為了向瀏覽器中的網(wǎng)頁添加動態(tài)效果。當(dāng)加載網(wǎng)站后,Javascript 代碼由瀏覽器的 Javascript 引擎運行。為了使 Javascript 與你的瀏覽器進(jìn)行交互,瀏覽器還提供了運行時環(huán)境(document、window等)。

          這意味著 Javascript 不能直接與計算機(jī)資源交互或?qū)ζ溥M(jìn)行操作。例如在 Web 服務(wù)器中,服務(wù)器必須能夠與文件系統(tǒng)進(jìn)行交互,這樣才能讀寫文件。

          Node.js 使 Javascript 不僅能夠運行在客戶端,而且還可以運行在服務(wù)器端。為了做到這一點,其創(chuàng)始人 Ryan Dahl 選擇了Google Chrome 瀏覽器的 v8 Javascript Engine,并將其嵌入到用 C++ 開發(fā)的 Node 程序中。所以 Node.js 是一個運行時環(huán)境,它允許 Javascript 代碼也能在服務(wù)器上運行。

          與其他語言(例如 C 或 C++)通過多個線程來處理并發(fā)性相反,Node.js 利用單個主線程并并在事件循環(huán)的幫助下以非阻塞方式執(zhí)行任務(wù)。

          要創(chuàng)建一個簡單的 Web 服務(wù)器非常簡單,如下所示:

          const http = require('http');
          const PORT = 3000;
          
          const server = http.createServer((req, res) => {
            res.statusCode = 200;
            res.setHeader('Content-Type', 'text/plain');
            res.end('Hello World');
          });
          
          server.listen(port, () => {
            console.log(`Server running at PORT:${port}/`);
          });

          如果你已安裝了 Node.js,可以試著運行上面的代碼。Node.js 非常適合 I/O 密集型程序。

          HTTP 客戶端:訪問 Web

          HTTP 客戶端是能夠?qū)⒄埱蟀l(fā)送到服務(wù)器,然后接收服務(wù)器響應(yīng)的工具。下面提到的所有工具底的層都是用 HTTP 客戶端來訪問你要抓取的網(wǎng)站。

          Request

          Request 是 Javascript 生態(tài)中使用最廣泛的 HTTP 客戶端之一,但是 Request 庫的作者已正式聲明棄用了。不過這并不意味著它不可用了,相當(dāng)多的庫仍在使用它,并且非常好用。用 Request 發(fā)出 HTTP 請求是非常簡單的:

          const request = require('request')
          request('https://www.reddit.com/r/programming.json', function (  error,
            response,
            body) {
            console.error('error:', error)
            console.log('body:', body)
          })

          你可以在 Github 上找到 Request 庫,安裝它非常簡單。你還可以在 https://github.com/request/request/issues/3142 找到棄用通知及其含義。

          Axios

          Axios 是基于 promise 的 HTTP 客戶端,可在瀏覽器和 Node.js 中運行。如果你用 Typescript,那么 axios 會為你覆蓋內(nèi)置類型。通過 Axios 發(fā)起 HTTP 請求非常簡單,默認(rèn)情況下它帶有 Promise 支持,而不是在 Request 中去使用回調(diào):

          const axios = require('axios')
          
          axios
           .get('https://www.reddit.com/r/programming.json')
           .then((response) => {
            console.log(response)
           })
           .catch((error) => {
            console.error(error)
           });

          如果你喜歡 Promises API 的 async/await 語法糖,那么你也可以用,但是由于頂級 await 仍處于 stage 3 ,所以我們只好先用異步函數(shù)來代替:

          async function getForum() {
           try {
            const response = await axios.get(
             'https://www.reddit.com/r/programming.json'
            )
            console.log(response)
           } catch (error) {
            console.error(error)
           }
          }

          你所要做的就是調(diào)用 getForum!可以在 https://github.com/axios/axios 上找到Axios庫。

          Superagent

          與 Axios 一樣,Superagent 是另一個強(qiáng)大的 HTTP 客戶端,它支持 Promise 和 async/await 語法糖。它具有像 Axios 這樣相當(dāng)簡單的 API,但是 Superagent 由于存在更多的依賴關(guān)系并且不那么流行。

          用 promise、async/await 或回調(diào)向 Superagent 發(fā)出HTTP請求看起來像這樣:

          const superagent = require("superagent")
          const forumURL = "https://www.reddit.com/r/programming.json"
          
          // callbacks
          superagent
           .get(forumURL)
           .end((error, response) => {
            console.log(response)
           })
          
          // promises
          superagent
           .get(forumURL)
           .then((response) => {
            console.log(response)
           })
           .catch((error) => {
            console.error(error)
           })
          
          // promises with async/await
          async function getForum() {
           try {
            const response = await superagent.get(forumURL)
            console.log(response)
           } catch (error) {
            console.error(error)
           }
          }

          可以在 https://github.com/visionmedia/superagent 找到 Superagent。

          正則表達(dá)式:艱難的路

          在沒有任何依賴性的情況下,最簡單的進(jìn)行網(wǎng)絡(luò)抓取的方法是,使用 HTTP 客戶端查詢網(wǎng)頁時,在收到的 HTML 字符串上使用一堆正則表達(dá)式。正則表達(dá)式不那么靈活,而且很多專業(yè)人士和業(yè)余愛好者都難以編寫正確的正則表達(dá)式。

          讓我們試一試,假設(shè)其中有一個帶有用戶名的標(biāo)簽,我們需要該用戶名,這類似于你依賴正則表達(dá)式時必須執(zhí)行的操作

          const htmlString = '<label>Username: John Doe</label>'
          const result = htmlString.match(/<label>(.+)<\/label>/)
          
          console.log(result[1], result[1].split(": ")[1])
          // Username: John Doe, John Doe

          在 Javascript 中,match() 通常返回一個數(shù)組,該數(shù)組包含與正則表達(dá)式匹配的所有內(nèi)容。第二個元素(在索引1中)將找到我們想要的 <label> 標(biāo)記的 textContentinnerHTML。但是結(jié)果中包含一些不需要的文本( “Username: “),必須將其刪除。

          如你所見,對于一個非常簡單的用例,步驟和要做的工作都很多。這就是為什么應(yīng)該依賴 HTML 解析器的原因,我們將在后面討論。

          Cheerio:用于遍歷 DOM 的核心 JQuery

          Cheerio 是一個高效輕便的庫,它使你可以在服務(wù)器端使用 JQuery 的豐富而強(qiáng)大的 API。如果你以前用過 JQuery,那么將會對 Cheerio 感到很熟悉,它消除了 DOM 所有不一致和與瀏覽器相關(guān)的功能,并公開了一種有效的 API 來解析和操作 DOM。

          const cheerio = require('cheerio')
          const $ = cheerio.load('<h2 class="title">Hello world</h2>')
          
          $('h2.title').text('Hello there!')
          $('h2').addClass('welcome')
          
          $.html()
          // <h2 class="title welcome">Hello there!</h2>

          如你所見,Cheerio 與 JQuery 用起來非常相似。

          但是,盡管它的工作方式不同于網(wǎng)絡(luò)瀏覽器,也就這意味著它不能:

          • 渲染任何解析的或操縱 DOM 元素
          • 應(yīng)用 CSS 或加載外部資源
          • 執(zhí)行 JavaScript

          因此,如果你嘗試爬取的網(wǎng)站或 Web 應(yīng)用是嚴(yán)重依賴 Javascript 的(例如“單頁應(yīng)用”),那么 Cheerio 并不是最佳選擇,你可能不得不依賴稍后討論的其他選項。

          為了展示 Cheerio 的強(qiáng)大功能,我們將嘗試在 Reddit 中抓取 r/programming 論壇,嘗試獲取帖子名稱列表。

          首先,通過運行以下命令來安裝 Cheerio 和 axios:npm install cheerio axios

          然后創(chuàng)建一個名為 crawler.js 的新文件,并復(fù)制粘貼以下代碼:

          const axios = require('axios');
          const cheerio = require('cheerio');
          
          const getPostTitles = async () => {
           try {
            const { data } = await axios.get(
             'https://old.reddit.com/r/programming/'
            );
            const $ = cheerio.load(data);
            const postTitles = [];
          
            $('div > p.title > a').each((_idx, el) => {
             const postTitle = $(el).text()
             postTitles.push(postTitle)
            });
          
            return postTitles;
           } catch (error) {
            throw error;
           }
          };
          
          getPostTitles()
          .then((postTitles) => console.log(postTitles));

          getPostTitles() 是一個異步函數(shù),將對舊的 reddit 的 r/programming 論壇進(jìn)行爬取。首先,用帶有 axios HTTP 客戶端庫的簡單 HTTP GET 請求獲取網(wǎng)站的 HTML,然后用 cheerio.load() 函數(shù)將 html 數(shù)據(jù)輸入到 Cheerio 中。

          然后在瀏覽器的 Dev Tools 幫助下,可以獲得可以定位所有列表項的選擇器。如果你使用過 JQuery,則必須非常熟悉 $('div> p.title> a')。這將得到所有帖子,因為你只希望單獨獲取每個帖子的標(biāo)題,所以必須遍歷每個帖子,這些操作是在 each() 函數(shù)的幫助下完成的。

          要從每個標(biāo)題中提取文本,必須在 Cheerio 的幫助下獲取 DOM元素( el 指代當(dāng)前元素)。然后在每個元素上調(diào)用 text() 能夠為你提供文本。

          現(xiàn)在,打開終端并運行 node crawler.js,然后你將看到大約存有標(biāo)題的數(shù)組,它會很長。盡管這是一個非常簡單的用例,但它展示了 Cheerio 提供的 API 的簡單性質(zhì)。

          如果你的用例需要執(zhí)行 Javascript 并加載外部源,那么以下幾個選項將很有幫助。

          JSDOM:Node 的 DOM

          JSDOM 是在 Node.js 中使用的文檔對象模型的純 Javascript 實現(xiàn),如前所述,DOM 對 Node 不可用,但是 JSDOM 是最接近的。它或多或少地模仿了瀏覽器。

          由于創(chuàng)建了 DOM,所以可以通過編程與要爬取的 Web 應(yīng)用或網(wǎng)站進(jìn)行交互,也可以模擬單擊按鈕。如果你熟悉 DOM 操作,那么使用 JSDOM 將會非常簡單。

          const { JSDOM } = require('jsdom')
          const { document } = new JSDOM(
           '<h2 class="title">Hello world</h2>'
          ).window
          const heading = document.querySelector('.title')
          heading.textContent = 'Hello there!'
          heading.classList.add('welcome')
          
          heading.innerHTML
          // <h2 class="title welcome">Hello there!</h2>

          代碼中用 JSDOM 創(chuàng)建一個 DOM,然后你可以用和操縱瀏覽器 DOM 相同的方法和屬性來操縱該 DOM。

          為了演示如何用 JSDOM 與網(wǎng)站進(jìn)行交互,我們將獲得 Reddit r/programming 論壇的第一篇帖子并對其進(jìn)行投票,然后驗證該帖子是否已被投票。

          首先運行以下命令來安裝 jsdom 和 axios:npm install jsdom axios

          然后創(chuàng)建名為 crawler.js的文件,并復(fù)制粘貼以下代碼:

          const { JSDOM } = require("jsdom")
          const axios = require('axios')
          
          const upvoteFirstPost = async () => {
            try {
              const { data } = await axios.get("https://old.reddit.com/r/programming/");
              const dom = new JSDOM(data, {
                runScripts: "dangerously",
                resources: "usable"
              });
              const { document } = dom.window;
              const firstPost = document.querySelector("div > div.midcol > div.arrow");
              firstPost.click();
              const isUpvoted = firstPost.classList.contains("upmod");
              const msg = isUpvoted
                ? "Post has been upvoted successfully!"
                : "The post has not been upvoted!";
          
              return msg;
            } catch (error) {
              throw error;
            }
          };
          
          upvoteFirstPost().then(msg => console.log(msg));

          upvoteFirstPost() 是一個異步函數(shù),它將在 r/programming 中獲取第一個帖子,然后對其進(jìn)行投票。axios 發(fā)送 HTTP GET 請求獲取指定 URL 的HTML。然后通過先前獲取的 HTML 來創(chuàng)建新的 DOM。JSDOM 構(gòu)造函數(shù)把HTML 作為第一個參數(shù),把 option 作為第二個參數(shù),已添加的 2 個 option 項執(zhí)行以下功能:

          • runScripts:設(shè)置為 dangerously 時允許執(zhí)行事件 handler 和任何 Javascript 代碼。如果你不清楚將要運行的腳本的安全性,則最好將 runScripts 設(shè)置為“outside-only”,這會把所有提供的 Javascript 規(guī)范附加到 “window” 對象,從而阻止在 inside 上執(zhí)行的任何腳本。
          • resources:設(shè)置為“usable”時,允許加載用 <script> 標(biāo)記聲明的任何外部腳本(例如:從 CDN 提取的 JQuery 庫)

          創(chuàng)建 DOM 后,用相同的 DOM 方法得到第一篇文章的 upvote 按鈕,然后單擊。要驗證是否確實單擊了它,可以檢查 classList 中是否有一個名為 upmod 的類。如果存在于 classList 中,則返回一條消息。

          打開終端并運行 node crawler.js,然后會看到一個整潔的字符串,該字符串將表明帖子是否被贊過。盡管這個例子很簡單,但你可以在這個基礎(chǔ)上構(gòu)建功能強(qiáng)大的東西,例如,一個圍繞特定用戶的帖子進(jìn)行投票的機(jī)器人。

          如果你不喜歡缺乏表達(dá)能力的 JSDOM ,并且實踐中要依賴于許多此類操作,或者需要重新創(chuàng)建許多不同的 DOM,那么下面將是更好的選擇。

          Puppeteer:無頭瀏覽器

          顧名思義,Puppeteer 允許你以編程方式操縱瀏覽器,就像操縱木偶一樣。它通過為開發(fā)人員提供高級 API 來默認(rèn)控制無頭版本的 Chrome。

          Puppeteer 比上述工具更有用,因為它可以使你像真正的人在與瀏覽器進(jìn)行交互一樣對網(wǎng)絡(luò)進(jìn)行爬取。這就具備了一些以前沒有的可能性:

          • 你可以獲取屏幕截圖或生成頁面 PDF。
          • 可以抓取單頁應(yīng)用并生成預(yù)渲染的內(nèi)容。
          • 自動執(zhí)行許多不同的用戶交互,例如鍵盤輸入、表單提交、導(dǎo)航等。

          它還可以在 Web 爬取之外的其他任務(wù)中發(fā)揮重要作用,例如 UI 測試、輔助性能優(yōu)化等。

          通常你會想要截取網(wǎng)站的屏幕截圖,也許是為了了解競爭對手的產(chǎn)品目錄,可以用 puppeteer 來做到。首先運行以下命令安裝 puppeteer,:npm install puppeteer

          這將下載 Chromium 的 bundle 版本,根據(jù)操作系統(tǒng)的不同,該版本大約 180 MB 至 300 MB。如果你要禁用此功能。

          讓我們嘗試在 Reddit 中獲取 r/programming 論壇的屏幕截圖和 PDF,創(chuàng)建一個名為 crawler.js的新文件,然后復(fù)制粘貼以下代碼:

          const puppeteer = require('puppeteer')
          
          async function getVisual() {
           try {
            const URL = 'https://www.reddit.com/r/programming/'
            const browser = await puppeteer.launch()
            const page = await browser.newPage()
          
            await page.goto(URL)
            await page.screenshot({ path: 'screenshot.png' })
            await page.pdf({ path: 'page.pdf' })
          
            await browser.close()
           } catch (error) {
            console.error(error)
           }
          }
          
          getVisual()

          getVisual() 是一個異步函數(shù),它將獲 URL 變量中 url 對應(yīng)的屏幕截圖和 pdf。首先,通過 puppeteer.launch() 創(chuàng)建瀏覽器實例,然后創(chuàng)建一個新頁面。可以將該頁面視為常規(guī)瀏覽器中的選項卡。然后通過以 URL 為參數(shù)調(diào)用 page.goto() ,將先前創(chuàng)建的頁面定向到指定的 URL。最終,瀏覽器實例與頁面一起被銷毀。

          完成操作并完成頁面加載后,將分別使用 page.screenshot()page.pdf() 獲取屏幕截圖和 pdf。你也可以偵聽 javascript load 事件,然后執(zhí)行這些操作,在生產(chǎn)環(huán)境級別下強(qiáng)烈建議這樣做。

          在終端上運行 node crawler.js ,幾秒鐘后,你會注意到已經(jīng)創(chuàng)建了兩個文件,分別名為 screenshot.jpgpage.pdf

          Nightmare:Puppeteer 的替代者

          Nightmare 是類似 Puppeteer 的高級瀏覽器自動化庫,該庫使用 Electron,但據(jù)說速度是其前身 PhantomJS 的兩倍。

          如果你在某種程度上不喜歡 Puppeteer 或?qū)?Chromium 捆綁包的大小感到沮喪,那么 nightmare 是一個理想的選擇。首先,運行以下命令安裝 nightmare 庫:npm install nightmare

          然后,一旦下載了 nightmare,我們將用它通過 Google 搜索引擎找到 ScrapingBee 的網(wǎng)站。創(chuàng)建一個名為crawler.js的文件,然后將以下代碼復(fù)制粘貼到其中:

          const Nightmare = require('nightmare')
          const nightmare = Nightmare()
          
          nightmare
           .goto('https://www.google.com/')
           .type("input[title='Search']", 'ScrapingBee')
           .click("input[value='Google Search']")
           .wait('#rso > div:nth-child(1) > div > div > div.r > a')
           .evaluate(
            () =>
             document.querySelector(
              '#rso > div:nth-child(1) > div > div > div.r > a'
             ).href
           )
           .end()
           .then((link) => {
            console.log('Scraping Bee Web Link': link)
           })
           .catch((error) => {
            console.error('Search failed:', error)
           })

          首先創(chuàng)建一個 Nighmare 實例,然后通過調(diào)用 goto() 將該實例定向到 Google 搜索引擎,加載后,使用其選擇器獲取搜索框,然后使用搜索框的值(輸入標(biāo)簽)更改為“ScrapingBee”。完成后,通過單擊 “Google搜索” 按鈕提交搜索表單。然后告訴 Nightmare 等到第一個鏈接加載完畢,一旦完成,它將使用 DOM 方法來獲取包含該鏈接的定位標(biāo)記的 href 屬性的值。

          最后,完成所有操作后,鏈接將打印到控制臺。

          總結(jié)

          • ? Node.js 是 Javascript 在服務(wù)器端的運行時環(huán)境。由于事件循環(huán)機(jī)制,它具有“非阻塞”性質(zhì)。
          • ? HTTP客戶端(例如 Axios、Superagent 和 Request)用于將 HTTP 請求發(fā)送到服務(wù)器并接收響應(yīng)。
          • ? CheerioJQuery 的優(yōu)點抽出來,在服務(wù)器端 進(jìn)行 Web 爬取是唯一的目的,但不執(zhí)行 Javascript 代碼。
          • ? JSDOM 根據(jù)標(biāo)準(zhǔn) Javascript規(guī)范 從 HTML 字符串中創(chuàng)建一個 DOM,并允許你對其執(zhí)行DOM操作。
          • ? Puppeteer and Nightmare高級(high-level )瀏覽器自動化庫,可讓你以編程方式去操作 Web 應(yīng)用,就像真實的人正在與之交互一樣。

          互聯(lián)網(wǎng)時代,信息獲取變得越來越便捷。然而,在進(jìn)行網(wǎng)頁數(shù)據(jù)分析或者自動化測試時,我們常常需要獲取特定的網(wǎng)頁元素。為了實現(xiàn)這一目的,有一種非常實用的工具——抓取網(wǎng)頁元素的插件。下面小編將與大家分享一些關(guān)于使用抓取網(wǎng)頁元素插件模仿點擊的經(jīng)驗。

          1.概述

          抓取網(wǎng)頁元素的插件是一種能夠模仿用戶點擊操作,并且自動獲取所需數(shù)據(jù)或執(zhí)行相應(yīng)動作的工具。通過簡單配置和使用該插件,我們可以輕松地完成對網(wǎng)頁元素的抓取和操作。

          2.安裝插件

          首先,在瀏覽器中搜索并安裝適合自己需求的抓取網(wǎng)頁元素插件,如Chrome瀏覽器中常用的插件有SelectorGadget、XPath Helper等。安裝完成后,確保插件已啟用。

          3.找到目標(biāo)元素

          在需要抓取的頁面上打開開發(fā)者工具(F12),選擇插件提供的定位工具(如SelectorGadget),然后點擊要抓取的目標(biāo)元素。插件會自動生成對應(yīng)的CSS選擇器或XPath路徑。

          4.配置選擇器或路徑

          將生成的CSS選擇器或XPath路徑復(fù)制到插件提供的配置界面中。根據(jù)需要,可以進(jìn)一步調(diào)整選擇器或路徑,以確保準(zhǔn)確地定位到目標(biāo)元素。

          5.模擬點擊操作

          配置完成后,可以使用插件提供的模擬點擊功能來執(zhí)行所需操作。例如,模擬點擊按鈕、鏈接或輸入框等。插件會自動模擬用戶點擊,并獲取相應(yīng)的數(shù)據(jù)或執(zhí)行相應(yīng)的動作。

          6.處理動態(tài)網(wǎng)頁

          對于一些動態(tài)加載內(nèi)容的網(wǎng)頁,插件可能無法直接獲取所需元素。這時,我們可以借助開發(fā)者工具中的網(wǎng)絡(luò)請求分析功能,找到對應(yīng)的接口請求,并通過代碼發(fā)送請求獲取所需數(shù)據(jù)。

          7.處理驗證碼

          在一些情況下,網(wǎng)頁可能會出現(xiàn)驗證碼以防止機(jī)器人訪問。針對這種情況,我們可以使用第三方驗證碼識別服務(wù),將驗證碼圖片提交給服務(wù)商進(jìn)行識別,并將識別結(jié)果應(yīng)用到插件中進(jìn)行操作。

          8.編寫腳本自動化

          如果需要反復(fù)執(zhí)行相同的抓取操作,可以考慮編寫腳本來實現(xiàn)自動化。通過腳本語言(如Python)結(jié)合插件提供的API或命令行工具,可以實現(xiàn)更加靈活和高效的抓取任務(wù)。

          9.注意事項

          在使用抓取網(wǎng)頁元素的插件時,需要注意以下幾點:

          -遵守網(wǎng)站的使用規(guī)則和法律法規(guī),不進(jìn)行非法操作和侵犯他人隱私的行為;

          -對于需要登錄的網(wǎng)頁,確保已經(jīng)登錄,并且有足夠的權(quán)限進(jìn)行操作;

          -注意網(wǎng)頁結(jié)構(gòu)的變化,及時更新選擇器或路徑以適應(yīng)頁面變化。

          通過使用抓取網(wǎng)頁元素的插件,我們可以輕松地實現(xiàn)對特定網(wǎng)頁元素的抓取和模擬點擊操作。無論是進(jìn)行數(shù)據(jù)分析還是自動化測試,這一工具都能為我們節(jié)省大量時間和精力。希望以上經(jīng)驗分享對大家有所幫助!

          為一種面向?qū)ο蟮恼Z言,Python是最容易學(xué)習(xí)的語言之一。Python的類和對象比任何其他計算機(jī)語言都更加用戶友好。此外,存在幾個庫,使得在Python中創(chuàng)建Web抓取工具變得輕而易舉。因此,使用Python步驟進(jìn)行網(wǎng)絡(luò)抓取很可能很簡單。我敢打賭你的下一個問題是,什么是網(wǎng)絡(luò)抓取?跟我來!

          在本文中,我們將介紹:

          1. 什么是網(wǎng)絡(luò)抓取?
          2. 解決網(wǎng)絡(luò)抓取的合法性問題
          3. 使用 Python 進(jìn)行 Web 抓取步驟

          1. 什么是網(wǎng)頁抓取?

          網(wǎng)絡(luò)抓取被定義為從互聯(lián)網(wǎng)上自動提取特定數(shù)據(jù)。它具有許多應(yīng)用,例如為機(jī)器學(xué)習(xí)項目收集數(shù)據(jù),開發(fā)價格比較工具或任何其他需要大量數(shù)據(jù)的新想法。

          雖然理論上可以手動提取數(shù)據(jù),但互聯(lián)網(wǎng)的廣闊性使得這種方法在許多情況下不切實際。了解如何創(chuàng)建網(wǎng)頁抓取工具可能會有所幫助。

          2. 解決網(wǎng)頁抓取的合法性問題

          雖然抓取是合法的,但您提取的數(shù)據(jù)可能不是。確保您沒有干擾以下任何一項:

          2.1 受版權(quán)保護(hù)的內(nèi)容

          此內(nèi)容類型是某人的知識產(chǎn)權(quán),受法律保護(hù),不能簡單地重復(fù)使用。

          2.2 個人數(shù)據(jù)

          如果您收集的信息可用于識別某人,則將其視為個人數(shù)據(jù),并且很可能受到該地區(qū)法律的保護(hù)。建議您避免存儲數(shù)據(jù),除非您有堅實的法律理由。

          一般來說,在抓取之前,您應(yīng)該始終閱讀每個網(wǎng)站的條款和條件,以確保您沒有違反他們的政策。如果您不確定如何繼續(xù),請與網(wǎng)站所有者聯(lián)系并請求權(quán)限。

          這篇Python網(wǎng)頁抓取文章將介紹開始使用簡單應(yīng)用程序所需的所有知識。您將學(xué)習(xí)如何在抓取網(wǎng)站之前對其進(jìn)行評估,如何使用BeautifulSoup提取精確的數(shù)據(jù),以及如何在使用Selenium進(jìn)行Java渲染之后提取數(shù)據(jù),并將所有內(nèi)容保存在新的CSV或JSON文件中。您將能夠按照下面提供的方法快速掌握如何完成網(wǎng)絡(luò)抓取。

          3. 使用 Python 進(jìn)行 Web 抓取步驟

          本文在Python Web抓取庫Beautiful Soup的幫助下介紹了Web抓取的步驟。

          網(wǎng)頁抓取涉及以下步驟:

          1. 使用 HTTP 向目標(biāo) URL 的網(wǎng)頁發(fā)出請求。服務(wù)器通過發(fā)回網(wǎng)頁的 HTML 內(nèi)容來回答問題。
          2. 檢索HTML文本后,我們必須解析數(shù)據(jù)。由于大多數(shù) HTML 數(shù)據(jù)是分層的,因此我們無法僅通過字符串處理來提取數(shù)據(jù)。需要一個可以構(gòu)造HTML數(shù)據(jù)的嵌套/樹結(jié)構(gòu)的解析器。其他HTML解析器庫可用,但html5lib是最先進(jìn)的。
          3. 剩下的就是導(dǎo)航和搜索我們生成的解析樹,即樹遍歷。將使用第三方Python軟件包Mithing Soup。它是一個從HTML和XML文件中提取數(shù)據(jù)的Python庫。

          3.1 安裝相應(yīng)的第三方庫

          Pip是在Python中安裝外部庫的最簡單方法。使用以下步驟進(jìn)行安裝:

          pip install requests
          pip install html5lib
          pip install bs4

          3.2 從網(wǎng)頁中檢索 HTML 內(nèi)容/文本

          首先,導(dǎo)入請求庫。之后,輸入要抓取的網(wǎng)頁URL。將請求 (HTTP) 發(fā)送到提供的 URL,并將服務(wù)器響應(yīng)保存在名為 r 的響應(yīng)對象中。使用 print r.content 獲取網(wǎng)頁的“字符串”類型的 HTML 內(nèi)容(原始)。

          import requests
          URL = "https://www.skillproperty.org/what-to-do-before-selling-your-home/"
          r = requests.get(URL)
          print(r.content)

          3.3 解析 HTML 內(nèi)容

          以這個為例,

          soup = BeautifulSoup(r.content, 'html5lib')

          我們通過提供兩個參數(shù)來制作一個 BeautifulSoup 對象:

          • r.content:這是未處理的 HTML 內(nèi)容。
          • html5lib:指定要使用的 HTML 解析器。

          soup.prettify() 現(xiàn)在已經(jīng)打印出來了,它為您提供了從原始HTML內(nèi)容生成的解析樹的可視化圖片。

          #This will not run on online IDE
          import requests
          from bs4 import BeautifulSoup
            
          URL = "http://www.skillproperty.com/blog"
          r = requests.get(URL)
            
          soup = BeautifulSoup(r.content, 'html5lib') 
          # should this return any error, install html5lib or 'pip install html5lib'
          print(soup.prettify())

          3.4 在解析樹中搜索和導(dǎo)航

          現(xiàn)在我們想從HTML內(nèi)容中提取一些有價值的數(shù)據(jù)。soup 對象包括分層結(jié)構(gòu)中可以通過編程方式檢索的所有數(shù)據(jù)。在此示例中,我們正在處理一個充滿引號的網(wǎng)頁。因此,我們想開發(fā)一個程序來保存這些報價。

          #program to scrap website and save quotes
          import requests
          from bs4 import BeautifulSoup
          import csv
             
          URL = "http://www.messagestogirl.com/romantic-quotes"
          r = requests.get(URL)
             
          soup = BeautifulSoup(r.content, 'html5lib')
             
          quotes=[]  # a list to store quotes
             
          table = soup.find('div', attrs = {'id':'all_quotes'}) 
             
          for row in table.findAll('div',
                                   attrs = {'class':'col-6 col-lg-3 text-center margin-30px-bottom sm-margin-30px-top'}):
              quote = {}
              quote['theme'] = row.h5.text
              quote['url'] = row.a['href']
              quote['img'] = row.img['src']
              quote['lines'] = row.img['alt'].split(" #")[0]
              quote['author'] = row.img['alt'].split(" #")[1]
              quotes.append(quote)
             
          filename = 'motivational_quotes.csv'
          with open(filename, 'w', newline='') as f:
              w = csv.DictWriter(f,['theme','url','img','lines','author'])
              w.writeheader()
              for quote in quotes:
                  w.writerow(quote)
          

          在繼續(xù)之前,建議您檢查我們使用soup.prettify()生成的網(wǎng)頁的HTML文本,并尋找一種導(dǎo)航到引號的方法。

          • 發(fā)現(xiàn)所有報價都包含在一個div容器中,ID為“所有報價”。因此,我們使用 find() 方法來定位該 div 元素(在前面的代碼中稱為 table):
          table = soup.find('div', attrs = {'id':'all_quotes'}) 

          第一個參數(shù)是要搜索的 HTML 標(biāo)記,第二個參數(shù)是字典類型元素,用于描述與該標(biāo)記連接的其他屬性。find() 方法返回第一個匹配的元素。您可以嘗試打印 table.prettify() 以了解此代碼的作用。

          • 在 table 元素中,每個引號都包含在帶有類引號的 div 容器中。因此,我們使用類引用循環(huán)遍歷每個 div 容器。

          在本例中,我們使用 findAll() 函數(shù),該函數(shù)在參數(shù)方面與 find 方法相當(dāng),但返回所有匹配組件的列表。現(xiàn)在使用名為row的變量來遍歷每個引號。

          現(xiàn)在考慮這段代碼:

          for row in table.find_all_next('div', attrs = 
               {'class': 'col-6 col-lg-3 text-center margin-30px-bottom sm-margin-30px-top'}):
          quote = {}
          quote['theme'] = row.h5.text
          quote['url'] = row.a['href']
          quote['img'] = row.img['src']
          quote['lines'] = row.img['alt'].split(" #")[0]
          quote['author'] = row.img['alt'].split(" #")[1]
          quotes.append(quote)
          

          為了保存有關(guān)報價的所有信息,我們開發(fā)了一本字典。點表示法可用于訪問分層結(jié)構(gòu)。然后,我們使用 .text 獲取 HTML 元素中的文本。

          quote['theme'] = row.h5.text

          將標(biāo)簽視為字典,使我們能夠添加,修改和刪除該標(biāo)簽的屬性。

          quote['url'] = row.a['href']

          最后,所有引號都將附加到名為引號的列表中。

          所以,這是一個如何在Python中制作網(wǎng)頁抓取器的基本示例。從這里,您可以嘗試廢棄您想要的任何其他網(wǎng)站!你可以花時間學(xué)習(xí)python,因為這是一個很好的技能。

          結(jié)論

          從現(xiàn)在開始,你只能靠自己了。用Python構(gòu)建網(wǎng)絡(luò)抓取器,獲取數(shù)據(jù),并從大量信息中得出結(jié)論,這本身就是一個迷人而具有挑戰(zhàn)性的過程。

          感謝您的閱讀!

          原文標(biāo)題:Web Scraping with Python – Learning the Basics

          作者:AI

          原文:https://rubikscode.net/2022/05/02/web-scraping-with-python-learning-the-basics/

          編譯:LCR


          主站蜘蛛池模板: 无码一区二区三区AV免费| 一区二区三区免费视频观看 | 91视频国产一区| 亚洲日韩精品一区二区三区| 精品视频一区在线观看| 日韩视频一区二区| 国产成人一区二区三区精品久久 | 男人免费视频一区二区在线观看| 成人区人妻精品一区二区三区| 精品欧洲AV无码一区二区男男| 亚洲福利一区二区精品秒拍| 国产在线精品一区二区三区直播 | 亚洲av日韩综合一区二区三区| 在线观看午夜亚洲一区| 一区二区三区美女视频| 久久精品亚洲一区二区| 中文字幕人妻AV一区二区| 国产一区二区三区在线观看免费| 丰满人妻一区二区三区视频53| 无码乱人伦一区二区亚洲一| 精品免费国产一区二区三区| 麻豆果冻传媒2021精品传媒一区下载 | 日本一区二区三区不卡视频| 国产精品亚洲一区二区麻豆 | 一区二区和激情视频| 精品国产aⅴ无码一区二区| 精品无码人妻一区二区三区品| 国产精品视频免费一区二区| 亚洲色一区二区三区四区| 在线日产精品一区| 亚洲国产欧美国产综合一区 | 日韩伦理一区二区| 加勒比精品久久一区二区三区| 国产精品成人99一区无码| 日韩精品一区二区午夜成人版| 美女免费视频一区二区三区| 亚洲一区二区三区无码影院| 日本道免费精品一区二区| 久久国产精品无码一区二区三区| 精品国产a∨无码一区二区三区 | av无码精品一区二区三区四区|