整合營銷服務商

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

          免費咨詢熱線:

          Python通過Lxml庫解析網絡爬蟲抓取到的html

          xml是基于 libxml2解析庫的Python封裝。libxml2是使用C語言編寫的,解析速度很好,不過安裝起來稍微有點復雜。安裝說明可以參考(http: //Lxml.de/installation.html),在CentOS7上中文安裝說明(http://www.cjavapy.com/article/64/),使用lxml庫來解析網絡爬蟲抓取到的HTML是一種非常高效的方式。lxml的html模塊特別適合處理HTML內容,它可以快速解析大型HTML文件,并提供XPath和CSS選擇器來查詢和提取數據。

          參考文檔:https://www.cjavapy.com/article/65/

          一、可能不合法的html標簽解析

          從網絡上抓取到的html的內容,有可能都是標準寫法,標簽什么的都閉合,屬性也是標準寫法,但是有可能有的網站的程序員不專業,這樣抓到的html解析就有可能有問題,因此,解析時先將有可能不合法的html解析為統一的格式。避免為后續的解析造成困擾。

          1、lxml.html

          lxml.html是專門用于解析和處理HTML文檔的模塊。它基于lxml.etree,但是為HTML文檔的特點做了優化。lxml.html能夠處理不良形式的HTML代碼,這對于解析和爬取網頁尤其有用。

          >>> import lxml.html
          >>> broken_html = '<ul class="body"><li>header<li>item</ul>'
          >>> tree = lxml.html.fromstring(broken_html) #解析html
          >>> fixed_html = lxml.html.tostring(tree,pretty_print=True)
          >>> print fixed_html
          <ul class="body">
          <li>header</li>
          <li>item</li>
          </ul>

          2、lxml.etree

          lxml.etree是lxml庫中用于處理XML文檔的模塊。它基于非常快的XML解析庫libxml2,提供了一個類似于標準庫xml.etree.ElementTreeAPI的接口,但是在性能和功能性方面要更加強大。lxml.etree支持XPath、XSLT、和Schema驗證等高級XML特性。

          >>> import lxml.etree
          >>> broken_html = '<ul class="body"><li>header<li>item</ul>'
          >>> tree = lxml.etree.fromstring(broken_html) #解析html
          >>> fixed_html = lxml.etree.tostring(tree,pretty_print=True)
          >>> print fixed_html
          <ul class="body">
          <li>header</li>
          <li>item</li>
          </ul>

          通過以上可以看出,lxml可以正確解析兩側缺失的括號,并閉合標簽,但不會額外增加<html>和<body>標簽。

          二、處理lxml解析出來的html內容

          若在html中找到我們想要的內容,用lxml有幾種不同的方法,XPath選擇器類似Beautiful Soup的find()方法。CSS選擇器用法和jQuery中的選擇器類似。兩種選擇器都可以用來查找文檔中的元素,但它們各有特點和適用場景。XPath是一種在XML文檔中查找信息的語言。它可以用來遍歷XML文檔的元素和屬性。CSS選擇器通常用于選擇和操作HTML文檔中的元素。

          1、XPath選擇器(/單斜杠表示絕對查找,//雙斜杠表示相對查找)

          from lxml import etree
          source_html = """
                   <div>
                      <ul>
                           <li class="item-0"><a href="link1.html">first item</a></li>
                           <li class="item-1"><a href="link2.html">second item</a></li>
                           <li class="item-inactive"><a href="link3.html">third item</a></li>
                           <li class="item-1"><a href="link4.html">fourth item</a></li>
                           <li class="item-0"><a href="link5.html">fifth item</a>
                       </ul>
                   </div>
                  """
          html = etree.HTML(source_html)
          print(html)
          result = etree.tostring(html)#會對的html標簽進行補全
          print(result.decode("utf-8"))

          輸出結果:

          <Element html at 0x39e58f0>
          <html><body><div>
          <ul>
          <li class="item-0"><a href="link1.html">first item</a></li>
          <li class="item-1"><a href="link2.html">second item</a></li>
          <li class="item-inactive"><a href="link3.html">third item</a></li>
          <li class="item-1"><a href="link4.html">fourth item</a></li>
          <li class="item-0"><a href="link5.html">fifth item</a>
          </li></ul>
          </div>
          </body></html>

          1)獲取某個標簽的內容(a標簽后不需要加斜杠,否則會報錯)

          #第一種寫法

          html = etree.HTML(source_html)
          html_data = html.xpath('/html/body/div/ul/li/a')#絕對查找
          #html_data = html.xpath('//li/a')#相對查找
          print(html)
          for i in html_data:
              print(i.text)
          

          輸出結果:

          <Element html at 0x14fe6b8>
          first item
          second item
          third item
          fourth item
          fifth item

          #第二種寫法
          #在要找的標簽后面加/text(),就是獲取標簽中的文本內容,結果中直接就是文本內容了,不用在通過text屬性獲取了。

          html = etree.HTML(source_html)
          html_data = html.xpath('/html/body/div/ul/li/a/text()')#絕對查找
          #html_data = html.xpath('//li/a/text()')#相對查找
          print(html)
          for i in html_data:
              print(i)

          輸出結果:

          <Element html at 0x128e3b7>
          first item
          second item
          third item
          fourth item
          fifth item

          2)獲取a標簽下的屬性

          html = etree.HTML(source_html)
          html_data = html.xpath('//li/a/@href') #相對查找
          #html_data = html.xpath('/html/body/div/ul/li/a/@href') #絕對查找
          for i in html_data:
              print(i)
          

          輸出結果:

          link1.html
          link2.html
          link3.html
          link4.html
          link5.html

          3)查找a標簽屬性等于link2.html的內容

          html = etree.HTML(source_html)
          html_data = html.xpath('/html/body/div/ul/li/a[@href="link2.html"]/text()')絕對查找
          #html_data = html.xpath('//li/a[@href="link2.html"]/text()')#相對查找
          print(html_data)
          for i in html_data:
              print(i)
          

          輸出結果:

          ['second item']
          second item

          4)查找最后一個li標簽里的a標簽的href屬性

          html = etree.HTML(source_html)
          html_data = html.xpath('//li[last()]/a/text()')
          print(html_data)
          for i in html_data:
              print(i)
          

          輸出結果:

          ['fifth item']
          fifth item

          5)查找倒數第二個li標簽里a標簽的href屬性

          html = etree.HTML(source_html)
          html_data = html.xpath('//li[last()-1]/a/text()')
          print(html_data)
          for i in html_data:
              print(i)
          

          輸出結果:

          ['fourth item']
          fourth item

          6)查找某個標簽id屬性值等于value的標簽

          //*[@id="value"]

          7)使用chrome瀏覽器提取某個標簽的XPath

          2、CSS選擇器(基本上和jQuery選擇器用法一樣)

          選擇器

          描述

          *

          選擇所有標簽

          a

          選擇<a>標簽

          .link

          選擇所有class = 'link'的元素

          a.link

          選擇class = 'link'的<a>標簽

          a#home

          選擇id = 'home'的<a>標簽

          a > span

          選擇父元素為<a>標簽的所有<span>子標簽

          a span

          選擇<a>標簽內部的所有<span>標簽

          使用示例:

          >>> html = """<div>
          <tr id="places_area_row" class="body">
          <td>header</td>
          <td class="w2p_fw">item1</td>
          <td class="w2p_fw">item2</td>
          <td class="w2p_fw">item3</td>
          <td><tr><td class="w2p_fw">header</td>
          <td class="w2p_fw">item4</td>
          <td class="w2p_fw">item5</td>
          <td class="w2p_fw">item6</td></tr></td>
          </tr>
          </div>"""
          >>> tree = lxml.html.fromstring(html)
          >>> td = tree.cssselect('tr#places_area_row > td.w2p_fw')[0]
          >>> htmlText = td.text_content()
          >>> print htmlText
          item1

          參考文檔:https://www.cjavapy.com/article/65/

          ?

          深入理解C語言:實用技巧與案例分析


          ## 一、引言

          C語言作為一門古老而強大的編程語言,其深層次的理解和實際運用對于程序員至關重要。本文將介紹一些實用技巧和通過案例分析來幫助讀者深入理解C語言的精髓。



          我整理了一些資料https://m.hqyjai.net/emb_study_blue_short.html?xt=yj




          ## 二、C語言實用技巧

          ### 1. 指針技巧

          指針是C語言中獨特且重要的概念,掌握指針技巧能夠讓程序更高效地操作內存,包括指針運算、指針數組等應用。


          ### 2. 宏定義技巧

          宏定義是C語言中的一種預處理指令,通過宏定義可以簡化代碼、提高可讀性,同時也可以實現一些高級的功能,如條件編譯、函數宏等。


          ### 3. 內聯函數技巧

          內聯函數是一種高效的函數調用方式,通過內聯函數可以減少函數調用的開銷,提高程序的執行效率,了解內聯函數的使用場景和注意事項非常重要。


          ## 三、C語言案例分析

          ### 1. 數據結構實現

          通過案例分析不同數據結構的實現,如鏈表、棧、隊列等,可以幫助讀者理解數據結構在C語言中的具體應用和實現方式。


          ### 2. 算法優化實例

          通過實際的算法優化案例,包括排序算法、查找算法等,展示如何在C語言中利用技巧和優化策略提升算法的效率和性能。


          ### 3. 實戰項目展示

          通過展示一些實際的C語言項目,如簡單的文件處理、網絡編程、圖形界面等,讓讀者從實際項目中學習C語言的應用和實踐技巧。



          我整理了一些資料https://m.hqyjai.net/emb_study_blue_short.html?xt=yj




          ## 四、結語

          通過本文的介紹和案例分析,讀者將更深入地理解C語言的實用技巧和應用場景,希望能夠為讀者在C語言編程的道路上提供一些啟發和幫助。


          以上是對《深入理解C語言:實用技巧與案例分析》的小點論述,希望能夠帶給您有益的啟示和知識。

          tmlAgilityPack 是一個 HTML 解析庫,用于 .NET 平臺。它允許開發者以類似于解析 XML 的方式,輕松地解析和操作 HTML 文檔。這個庫特別適合處理非標準的 HTML,例如那些格式不正確或包含錯誤的 HTML 文檔。

          從原理上說,解析是一個 CPU 密集型操作。在計算資源充裕的情況下,使用多線程并行可以加快處理速度。

          以下代碼展示了兩個場景:

          • 使用一個線程解析 1000 個頁面

          • 使用 8 個線程解析 1000 個頁面(總量 1000 個,測試機器上的 CPU 有 8 個內核)。

          • string html = File.ReadAllText("PATH");//One threadfor (int i = 0; i < 1000; i++) new HtmlDocument().LoadHtml(html);//Several threadsParallel.For(0, 1000, (int i) => new HtmlDocument().LoadHtml(html));

            然而實際的情況是:盡管多線程版本消耗了 2 ~ 3 倍的 CPU,但所花費的時間大致相同。而且 CPU 占用率一直維持在 30% 以下。即便更換了要處理的頁面,或者內核數量更多的電腦,情況都差不多。

            如何解決

            開啟更多的線程并不會提升處理的速度,這讓我開始懷疑是不是存在鎖的問題。遺憾的是沒有在源代碼中找到 lock ,但是發現了一個 Issues:

            https://github.com/zzzprojects/html-agility-pack/issues/191

            在使用 Profiler 工具對多線程程序進行分析之后,發現程序可能存在內存瓶頸。根據他的觀察,有大約 50% 的 CPU 時間耗費在了內存分配上。

            這和使用的 GC 類型有關,向 App.config 增加以下代碼可以解決該問題:

            •  <runtime> <gcServer enabled="true"/> <gcConcurrent enabled="false" /> </runtime>

              適配 .NET 8.0

              我的程序是一個使用 .NET 8.0 框架的控制臺,增加 App.config 文件之后并沒有效果。于是,我找到了微軟的官方文檔:

              https://learn.microsoft.com/zh-cn/dotnet/core/runtime-config/garbage-collector

              根據文檔所述,可以通過環境變量、runtimeconfig.json 文件或項目文件來指定程序使用 Server 版本。我選擇修改項目文件:

              • <Project Sdk="Microsoft.NET.Sdk">
                <PropertyGroup> <ServerGarbageCollection>true</ServerGarbageCollection> </PropertyGroup>
                </Project>

                問題得以解決:處理速度快了不少,CPU 占用維持在了 70% 左右。


          主站蜘蛛池模板: 中文字幕一区精品| 国产成人精品视频一区| 天天躁日日躁狠狠躁一区| 国产MD视频一区二区三区| 中文字幕日韩人妻不卡一区| 中文字幕一区二区三区在线观看 | 亚洲A∨精品一区二区三区下载| 久久4k岛国高清一区二区| 无码人妻一区二区三区免费手机| 亚洲色精品VR一区区三区| 国产成人精品亚洲一区| 色婷婷AV一区二区三区浪潮| 中文字幕日韩一区二区不卡 | 日本精品一区二区三区在线视频一 | 国产精品毛片a∨一区二区三区 | 国产午夜精品一区二区三区漫画| 亚洲国产日韩一区高清在线| 国产精品av一区二区三区不卡蜜| 日韩一区二区三区视频| 精品人妻码一区二区三区| 国产在线精品一区二区在线看| 中文字幕亚洲一区二区三区| 精品午夜福利无人区乱码一区| 国产在线不卡一区| 91精品国产一区二区三区左线| 国产精品视频无圣光一区| 无码人妻一区二区三区在线| 国产AV一区二区精品凹凸| 精品三级AV无码一区| 一区二区三区影院| 国产伦精品一区二区三区不卡 | 无码av中文一区二区三区桃花岛| 一区三区三区不卡| 亚洲国产成人久久一区二区三区 | 亚洲av午夜精品一区二区三区| 国产精品美女一区二区视频| 国产在线观看一区二区三区 | 国产福利91精品一区二区| 国产在线精品一区二区三区不卡| 一区二区和激情视频| 性无码免费一区二区三区在线|