整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          前端面試題:瀏覽器如何解析HTML文件?

          覽器解析HTML文件的過程是網頁呈現的關鍵步驟之一。具體介紹如下:


          HTML文檔的接收和預處理

          1. 網絡請求處理:當用戶輸入URL或點擊鏈接時,瀏覽器發起HTTP請求,服務器響應并返回HTML文件。此過程中,瀏覽器需要處理DNS查詢、建立TCP連接等底層網絡通信操作。
          2. 預解析優化:為了提高性能,現代瀏覽器在主線程解析HTML之前會啟動一個預解析線程,提前下載HTML中鏈接的外部CSS和JS文件。這一步驟確保了后續渲染過程的順暢進行。

          解析為DOM樹

          1. 詞法分析和句法分析:瀏覽器的HTML解析器通過詞法分析將HTML文本標記轉化為符號序列,然后通過句法分析器按照HTML規范構建出DOM樹。每個節點代表一個HTML元素,形成了多層次的樹狀結構。
          2. 生成對象接口:生成的DOM樹是頁面元素的結構化表示,提供了操作頁面元素的接口,如JavaScript可以通過DOM API來動態修改頁面內容和結構。

          CSS解析與CSSOM樹構建

          1. CSS文件加載與解析:瀏覽器解析HTML文件中的<link>標簽引入的外部CSS文件和<style>標簽中的內聯CSS,生成CSSOM樹。CSSOM樹反映了CSS樣式的層級和繼承關系。
          2. CSS屬性計算:包括層疊、繼承等,確保每個元素對應的樣式能夠被準確計算。這些計算過程為后續的布局提供必要的樣式信息。

          JavaScript加載與執行

          1. 阻塞式加載:當解析器遇到<script>標簽時,它會停止HTML的解析,轉而先加載并執行JavaScript代碼。這是因為JS可能會修改DOM結構或CSSOM樹,從而影響已解析的部分。
          2. 異步和延遲加載:為了不影響頁面的初步渲染,可以采用async或defer屬性來異步加載JS文件,這樣可以在后臺進行JS的加載和執行,而不阻塞HTML解析。

          渲染樹的構建

          1. 合并DOM樹和CSSOM樹:有了DOM樹和CSSOM樹后,瀏覽器將它們組合成渲染樹,這個樹只包含顯示界面所需的DOM節點及對應的樣式信息。
          2. 不可見元素的排除:渲染樹會忽略例如<head>、<meta>等不可見元素,只關注<body>內的可視化內容。

          布局計算(Layout)

          1. 元素位置和尺寸確定:瀏覽器從渲染樹根節點開始,遞歸地計算每個節點的精確位置和尺寸,這個過程也被稱為“回流”或“重排”,是后續繪制的基礎。
          2. 布局過程的優化:現代瀏覽器會盡量優化布局過程,例如通過流式布局的方式減少重復計算,確保高效地完成布局任務。

          繪制(Paint)

          1. 像素級繪制:繪制是一個將布局計算后的各元素繪制成像素點的過程。這包括文本、顏色、邊框、陰影以及替換元素的繪制。
          2. 層次化的繪制:為了高效地更新局部內容,瀏覽器會將頁面分成若干層次(Layer),對每一層分別進行繪制,這樣只需更新變化的部分。

          因此,我們開發中要注意以下幾點:

          • 避免過度使用全局腳本:盡量減少使用全局腳本或者將它們放在文檔底部,以減少對HTML解析的阻塞。
          • 合理組織CSS和使用CSS預處理器:合理組織CSS文件的結構和覆蓋規則,利用CSS預處理器進行模塊化管理。
          • 利用瀏覽器緩存機制:通過設置合理的緩存策略,減少重復加載相同資源,提升二次訪問的體驗。
          • 優化圖片和多媒體資源:適當壓縮圖片和優化多媒體資源的加載,減少網絡傳輸時間和渲染負擔。

          綜上所述,瀏覽器解析HTML文件是一個復雜而高度優化的過程,涉及從網絡獲取HTML文檔到最終將其渲染到屏幕上的多個步驟。開發者需要深入理解這些步驟,以優化網頁性能和用戶體驗。通過合理組織HTML結構、優化資源加載順序、減少不必要的DOM操作和合理安排CSS和JavaScript的加載與執行,可以顯著提升頁面加載速度和運行效率。

          .什么是jsoup

          jsoup 是一款 Java 的 HTML 解析器,可直接解析某個 URL 地址、HTML 文本內容。它提供了一套非常省力的 API,可通過 DOM,CSS 以及類似于 jQuery 的操作方法來取出和操作數據,可操作 HTML 元素、屬性、文本。

          JSoup 功能

          jsoup 實現 WHATWG HTML5 規范,并將 HTML 解析為與現代瀏覽器相同的 DOM。

          • 從 URL,文件或字符串中提取并解析 HTML。
          • 查找和提取數據,使用 DOM 遍歷或 CSS 選擇器。
          • 操縱 HTML 元素,屬性和文本。
          • 根據安全的白名單清理用戶提交的內容,以防止 XSS 攻擊。
          • 輸出整潔的 HTML。

          JSoup 主要類

          大多數情況下,下面給出 3 個類是我們需要重點了解的。

          Jsoup 類

          Jsoup 類是任何 Jsoup 程序的入口點,并將提供從各種來源加載和解析 HTML 文檔的方法。 Jsoup 類的一些重要方法如下:

          方法

          描述

          static Connection connect(String url)

          創建并返回 URL 的連接。

          static Document parse(File in, String charsetName)

          將指定的字符集文件解析成文檔。

          static Document parse(String html)

          將給定的 html 代碼解析成文檔。

          static String clean(String bodyHtml, Whitelist whitelist)

          從輸入 HTML 返回安全的 HTML,通過解析輸入 HTML 并通過允許的標簽和屬性的白名單進行過濾。

          Jsoup 類的其他重要方法可以參見 - https://jsoup.org/apidocs/org/jsoup/Jsoup.html

          Document 類

          該類表示通過 Jsoup 庫加載 HTML 文檔??梢允褂么祟悎绦羞m用于整個 HTML 文檔的操作。 Element 類的重要方法可以參見 - http://jsoup.org/apidocs/org/jsoup/nodes/Document.html 。

          Element 類

          HTML 元素是由標簽名稱,屬性和子節點組成。 使用 Element 類,您可以提取數據,遍歷節點和操作 HTML。 Element 類的重要方法可參見 - http://jsoup.org/apidocs/org/jsoup/nodes/Element.html 。

          2.代碼工程

          實驗目的

          實現解析liuhaihua.cn首頁list

          pom.xml

          <?xml version="1.0" encoding="UTF-8"?>
          <project xmlns="http://maven.apache.org/POM/4.0.0"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
              <parent>
                  <artifactId>springboot-demo</artifactId>
                  <groupId>com.et</groupId>
                  <version>1.0-SNAPSHOT</version>
              </parent>
              <modelVersion>4.0.0</modelVersion>
          
              <artifactId>jsoup</artifactId>
          
              <properties>
                  <maven.compiler.source>8</maven.compiler.source>
                  <maven.compiler.target>8</maven.compiler.target>
              </properties>
              <dependencies>
          
                  <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-web</artifactId>
                  </dependency>
          
                  <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-autoconfigure</artifactId>
                  </dependency>
                  <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-test</artifactId>
                      <scope>test</scope>
                  </dependency>
                  <dependency>
                      <groupId>org.jsoup</groupId>
                      <artifactId>jsoup</artifactId>
                      <version>1.12.1</version>
                  </dependency>
                  <dependency>
                      <groupId>org.apache.httpcomponents</groupId>
                      <artifactId>httpclient</artifactId>
                  </dependency>
          
              </dependencies>
          </project>

          controller

          package com.et.jsoup;
          
          import org.springframework.web.bind.annotation.RequestMapping;
          import org.springframework.web.bind.annotation.RestController;
          
          import java.util.HashMap;
          import java.util.Map;
          
          @RestController
          public class HelloWorldController {
              @RequestMapping("/hello")
              public Map<String, Object> showHelloWorld(){
                  Map<String, Object> map = new HashMap<>();
                  map =JsoupUtil.parseHtml("http://www.liuhaihua.cn/");
                  map.put("msg", "HelloWorld");
                  return map;
              }
          }

          工具類

          package com.et.jsoup;
          import java.io.IOException;
          import java.util.ArrayList;
          import java.util.HashMap;
          import java.util.List;
          import java.util.Map;
          
          import org.apache.http.HttpEntity;
          import org.apache.http.HttpStatus;
          import org.apache.http.client.ClientProtocolException;
          import org.apache.http.client.methods.CloseableHttpResponse;
          import org.apache.http.client.methods.HttpGet;
          import org.apache.http.client.utils.HttpClientUtils;
          import org.apache.http.impl.client.CloseableHttpClient;
          import org.apache.http.impl.client.HttpClients;
          import org.apache.http.util.EntityUtils;
          import org.jsoup.Jsoup;
          import org.jsoup.nodes.Document;
          import org.jsoup.nodes.Element;
          import org.jsoup.select.Elements;
          
          /**
           * @author liuhaihua
           * @version 1.0
           * @ClassName JsoupUtil
           * @Description todo
           * @date 2024/06/24/ 9:16
           */
          
          public class JsoupUtil {
                  public static Map<String ,Object> parseHtml(String url){
                      Map<String,Object> map = new HashMap<>();
                      //1.生成httpclient,相當于該打開一個瀏覽器
                      CloseableHttpClient httpClient = HttpClients.createDefault();
                      CloseableHttpResponse response = null;
                      //2.創建get請求,相當于在瀏覽器地址欄輸入 網址
                      HttpGet request = new HttpGet(url);
                      //設置請求頭,將爬蟲偽裝成瀏覽器
                      request.setHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36");
          //        HttpHost proxy = new HttpHost("60.13.42.232", 9999);
          //        RequestConfig config = RequestConfig.custom().setProxy(proxy).build();
          //        request.setConfig(config);
                      try {
                          //3.執行get請求,相當于在輸入地址欄后敲回車鍵
                          response = httpClient.execute(request);
          
                          //4.判斷響應狀態為200,進行處理
                          if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                              //5.獲取響應內容
                              HttpEntity httpEntity = response.getEntity();
                              String html = EntityUtils.toString(httpEntity, "utf-8");
                              System.out.println(html);
          
                              /**
                               * 下面是Jsoup展現自我的平臺
                               */
                              //6.Jsoup解析html
                              Document document = Jsoup.parse(html);
                              //像js一樣,通過標簽獲取title
                              System.out.println(document.getElementsByTag("title").first());
                              Elements blogmain = document.getElementsByClass("col-sm-8 blog-main");
          
          
                              //像js一樣,通過class 獲取列表下的所有博客
                              Elements postItems =  blogmain.first().getElementsByClass("fade-in");
                              //循環處理每篇博客
                              List<Map>  list =  new ArrayList<>();
                              for (Element postItem : postItems) {
                                  Map<String,Object> row = new HashMap<>();
                                  //像jquery選擇器一樣,獲取文章標題元素
                                  Elements titleEle = postItem.select(".entry-title a");
                                  System.out.println("文章標題:" + titleEle.text());;
                                  row.put("title",titleEle.text());
                                  System.out.println("文章地址:" + titleEle.attr("href"));
                                  row.put("href",titleEle.attr("href"));
                                  //像jquery選擇器一樣,獲取文章作者元素
                                  Elements footEle = postItem.select(".archive-content");
                                  System.out.println("文章概要:" + footEle.text());;
                                  row.put("summary",footEle.text());
                                  Elements view = postItem.select(".views");
                                  System.out.println( view.text());
                                  row.put("views",view.text());
                                  System.out.println("*********************************");
                                  list.add(row);
                              }
                              map.put("data",list);
          
                          } else {
                              //如果返回狀態不是200,比如404(頁面不存在)等,根據情況做處理,這里略
                              System.out.println("返回狀態不是200");
                              System.out.println(EntityUtils.toString(response.getEntity(), "utf-8"));
                          }
          
                      } catch (ClientProtocolException e) {
                          e.printStackTrace();
                      } catch (IOException e) {
                          e.printStackTrace();
                      } finally {
                          //6.關閉
                          HttpClientUtils.closeQuietly(response);
                          HttpClientUtils.closeQuietly(httpClient);
                      }
                      return  map;
                  }
                  public static void main(String[] args) {
                      parseHtml("http://www.liuhaihua.cn/");
                  }
          
          }

          DemoApplication.java

          package com.et.jsoup;
          
          import org.springframework.boot.SpringApplication;
          import org.springframework.boot.autoconfigure.SpringBootApplication;
          
          @SpringBootApplication
          public class DemoApplication {
          
             public static void main(String[] args) {
                SpringApplication.run(DemoApplication.class, args);
             }
          }

          以上只是一些關鍵代碼,所有代碼請參見下面代碼倉庫

          代碼倉庫

          • https://github.com/Harries/springboot-demo

          3.測試

          • 啟動spring boot應用
          • 訪問http://127.0.0.1:8088/hello,返回解析結果

          4.引用

          • 官網:https://jsoup.org/
          • GitHub:https://github.com/jhy/jsoup/
          • http://www.liuhaihua.cn/archives/710776.html

          送HTTP請求:首先,你需要向目標網頁發送HTTP請求以獲取其HTML內容。這可以通過Java的內置庫java.net.HttpURLConnection或者使用更高級的庫如Apache HttpClient、OkHttp等來完成。

          讀取響應內容:一旦你發送了請求并收到了響應,你需要讀取響應的內容,這通常是HTML格式的字符串。

          解析HTML:然后,你需要解析HTML字符串以提取所需的信息。這可以通過正則表達式來完成,但通常建議使用專門的HTML解析庫,如Jsoup。Jsoup提供了一種非常方便的方式來解析HTML文檔,并可以通過類似于CSS或jQuery的選擇器語法來提取和操作數據。

          如果你需要處理更復雜的網頁或進行更高級的網頁抓取和解析任務,你可能還需要考慮使用如Selenium這樣的瀏覽器自動化工具來模擬真實的瀏覽器行為。但是,請注意,頻繁或大規模地抓取網頁可能會違反網站的使用條款,甚至可能構成法律問題。


          主站蜘蛛池模板: 日本一区中文字幕日本一二三区视频| 亚洲国产精品一区二区久| 国产AV一区二区三区传媒| 一区二区三区在线观看| 国产丝袜无码一区二区三区视频| 亚洲乱码av中文一区二区| 国产伦精品一区二区三区| 一区二区三区在线播放| 色屁屁一区二区三区视频国产| 亚洲国产情侣一区二区三区| 中文字幕aⅴ人妻一区二区| 国产在线观看精品一区二区三区91 | 亚洲AⅤ视频一区二区三区| 无码日韩精品一区二区免费| 国产精品分类视频分类一区 | 亚洲变态另类一区二区三区| 国产精品丝袜一区二区三区| 国产成人无码一区二区在线观看| 一区精品麻豆入口| 日本精品一区二区久久久| 国产精品va一区二区三区| 国产精品一区二区久久沈樵| 国产一区二区三区播放心情潘金莲 | 国产一区二区在线观看麻豆| 国语对白一区二区三区| 在线观看一区二区精品视频| 波多野结衣中文字幕一区| 国产视频一区在线播放| 国产日韩精品一区二区在线观看 | 精品国产乱码一区二区三区| 99久久精品午夜一区二区| 亚洲熟女综合一区二区三区| 国产一区二区草草影院| 国产精品久久久久一区二区| 亚洲男人的天堂一区二区| 红桃AV一区二区三区在线无码AV| 久久人妻内射无码一区三区| 自拍日韩亚洲一区在线| 日本精品视频一区二区三区 | 亚欧在线精品免费观看一区| 国产精品合集一区二区三区 |