整合營銷服務商

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

          免費咨詢熱線:

          Python如何解析HTML和XML數據

          一篇我們介紹了如何解析CSV和JSON數據:如何解析互聯網數據:CSV和JSON篇,今天我們將介紹如何解析HTML和XML數據。

          今天的介紹能夠幫助你輕而易舉地從網頁中(比如下面的中航電子的2017年一季度交易數據)提取自己想要的數據:

          準備

          在Python中可以解析html和xml數據的軟件包很多,今天我們介紹的是lxml,先安裝:

          $ pip install lxml

          如果不熟悉pip的使用,可以參考另一篇文章:如何管理python軟件包。

          解析HTML數據

          首先,回顧一下HTML的一些基本概念:

          • 標簽/tag:比如<html>, <h1>, <head>...一般成對出現,例如開始標簽<html>和結束標簽</html>

          • 元素/element:開始標簽到結束標簽整段代碼,標簽對之間的即為內容(content)

          • 屬性/attribute:標簽可擁有key=value形式的屬性,比如<div class="header">...</div>

          簡單地理解,HTML網頁就是由一組元素構成的一個集合。另外,大多數HTML標簽是可以嵌套的,因此元素可以包含一系列子元素。有了這些概念做基礎,我們將能夠很容易理解軟件包lxml的使用。實際上,在lxml里面,每個HTML元素對應一個lxml.html.HtmlElement對象,該對象提供一組標準的方法取訪問包含在該元素內部的數據,比如屬性、內容和子元素等。

          例子

          考察下面的鏈接,它提供中航電子在2017年第一季度的交易數據,我們打算從里面提取一些數據:

          >>> url = "http://quotes.money.163.com/trade/lsjysj_600372.html?year=2017&season=1"

          先把該網頁爬取下來:

          >>> import urllib2

          >>> rsp = urllib2.urlopen(url).read()

          >>> print rsp[0:15]

          <!DOCTYPE html>

          將字符串rsp轉換成HtmlElement對象:

          >>> from lxml import html

          >>> doc = html.document_fromstring(rsp)

          >>> type(doc)

          <class 'lxml.html.HtmlElement'>

          >>> doc.tag

          'html'

          所以其實doc就是一個html元素,它包含一些元素,比如head, body, link, div...

          比如,如果你想提取該網頁里面所有的鏈接(links):

          >>> links = [ link for link in doc.iterlinks() ]

          >>> len(links)

          106

          >>> links[0]

          (<Element link at 0x1029179f0>, 'href', 'http://img1.cache.netease.com/f2e/finance/gegu/s.1064000.css', 0)

          >>> links[0][2]

          'http://img1.cache.netease.com/f2e/finance/gegu/s.1064000.css'

          如果你想查看元素直接包含哪些子元素,可以調用getchildren()方法:

          >>> doc.getchildren()

          [<Element head at 0x10299a0a8>, <Element body at 0x10299a470>]

          對嵌套很深的元素,如果熟悉xpath表達式,最直接的辦法是調用xpath(...)方法:

          >>> [ td.text for td in doc.xpath('/html/body/div[2]/div[4]/table/tr[1]/td')]

          ['2017-03-31', '19.02', '19.50', '19.02', '19.30', '0.36', '1.90', '102,212', '19,747', '2.53', '0.58']

          此外,還可以通過find, findall, find_class, get_element_by_id等方法查找目標元素,比如:

          >>> [ td.text for td in doc.findall('./body/div[2]/div[4]/table/tr[1]/td')]

          ['2017-03-31', '19.02', '19.50', '19.02', '19.30', '0.36', '1.90', '102,212', '19,747', '2.53', '0.58']

          如果元素有屬性,提取屬性值也很方便,比如:

          >>> form = doc.forms[0]

          >>> form.tag

          'form'

          >>> form.attrib

          {'action': '/trade/lsjysj_600372.html', 'id': 'date'}

          >>> form.keys()

          ['id', 'action']

          >>> form.get('action')

          '/trade/lsjysj_600372.html'

          >>> form.items()

          [('id', 'date'), ('action', '/trade/lsjysj_600372.html')]

          '>>> form.form_values()

          [('year', '2017'), ('season', '1')]

          >>> form.method

          'GET'

          做為一個完整的例子,下面的腳本就是爬取中航電子在2017年第一季度的數據:

          輸出效果:

          (test) $ head -3 600372.csv

          日期;開盤價;最高價;最低價;收盤價;漲跌額;漲跌幅(%);成交量(手);成交金額(萬元);振幅(%);換手率(%)

          2017-03-31;19.02;19.50;19.02;19.30;0.36;1.90;102,212;19,747;2.53;0.58

          2017-03-31;19.02;19.50;19.02;19.30;0.36;1.90;102,212;19,747;2.53;0.58

          解析xml數據

          xml的格式和HTML類似,也是由標簽構成的,但是要比HTML文件簡單許多,看下面的xml文件片段處理:

          >>> xmlstr="""\

          ... <target name="run" depends="jar">

          ... <java fork="true" classname="${main-class}">

          ... <classpath>

          ... <path refid="classpath"/>

          ... <path refid="application"/>

          ... </classpath>

          ... </java>

          ... </target>"""

          >>> from lxml import etree

          第一步是獲取根節點:

          >>> root = etree.fromstring(xmlstr)

          >>> root.tag

          'target'

          如果要提取節點屬性:

          >>> root.items()

          [('name', 'run'), ('depends', 'jar')]

          >>> root.keys()

          ['name', 'depends'

          >>> root.get("name")

          'run'

          >>> root.values()

          ['run', 'jar']

          可以使用find, xpath等方法去獲取和查找子節點:

          >>> java = root.find("./java")

          >>> java.tag

          'java'

          >>> java.keys()

          ['fork', 'classname']

          >>> [ path.get("refid") for path in root.xpath("http://path")]

          ['classpath', 'application']

          lxml軟件的功能很強大,如果有興趣進一步了解,可以查看官方文檔:

          http://lxml.de/index.html

          今天就寫這么,歡迎大家留言、評論和關注。

          Python寫爬蟲工具在現在是一種司空見慣的事情,每個人都希望能夠寫一段程序去互聯網上扒一點資料下來,用于數據分析或者干點別的事情。

          我們知道,爬蟲的原理無非是把目標網址的內容下載下來存儲到內存中,這個時候它的內容其實是一堆HTML,然后再對這些HTML內容進行解析,按照自己的想法提取出想要的數據,所以今天我們主要來講四種在Python中解析網頁HTML內容的方法,各有千秋,適合在不同的場合下使用。

          首先我們隨意找到一個網址,這時我腦子里閃過了豆瓣這個網站。嗯,畢竟是用Python構建的網站,那就拿它來做示范吧。

          我們找到了豆瓣的Python爬蟲小組主頁,看起來長成下面這樣。


          讓我們用瀏覽器開發者工具看看HTML代碼,定位到想要的內容上,我們想要把討論組里的帖子標題和鏈接都給扒出來。


          通過分析,我們發現實際上我們想要的內容在整個HTML代碼的 <table class="olt">這個區域里,那我們只需要想辦法把這個區域內的內容拿出來就差不多了。

          現在開始寫代碼。

          1: 正則表達式大法

          正則表達式通常被用來檢索、替換那些符合某個模式的文本,所以我們可以利用這個原理來提取我們想要的信息。

          參考以下代碼。


          在代碼第6行和第7行,需要手動指定一下header的內容,裝作自己這個請求是瀏覽器請求,否則豆瓣會視為我們不是正常請求會返回HTTP 418錯誤。

          在第7行我們直接用requests這個庫的get方法進行請求,獲取到內容后需要進行一下編碼格式轉換,同樣是因為豆瓣的頁面渲染機制的問題,正常情況下,直接獲取requests content的內容即可。

          Python模擬瀏覽器發起請求并解析內容代碼:

          url = 'https://www.douban.com/group/491607/'
          headers = {"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0"}
          response = requests.get(url=url,headers=headers).content.decode('utf-8')

          正則的好處是編寫麻煩,理解不容易,但是匹配效率很高,不過時至今日有太多現成的HTMl內容解析庫之后,我個人不太建議再手動用正則來對內容進行匹配了,費時費力。

          主要解析代碼:

          re_div = r'<table\s+class=\"olt\">[\W|\w]+</table>'
          pattern = re.compile(re_div)
          content = re.findall(pattern, str(response))
          re_link = r'<a .*?>(.*?)</a>'
          mm = re.findall(re_link, str(content), re.S|re.M)
          urls=re.findall(r"<a.*?href=.*?<\/a>",  str(content), re.I|re.S|re.M)


          2: requests-html

          這個庫其實是我個人最喜歡的庫,作則是編寫requests庫的網紅程序員 Kenneth Reitz,他在requests的基礎上加上了對html內容的解析,就變成了requests-html這個庫了。


          下面我們來看看范例:


          我喜歡用requests-html來解析內容的原因是因為作者依據幫我高度封裝過了,連請求返回內容的編碼格式轉換也自動做了,完全可以讓我的代碼邏輯簡單直接,更專注于解析工作本身。

          主要解析代碼:

          links = response.html.find('table.olt', first=True).find('a')

          安裝途徑: pip install requests-html


          3: BeautifulSoup


          大名鼎鼎的 BeautifulSoup庫,出來有些年頭了,在Pyhton的HTML解析庫里屬于重量級的庫,其實我評價它的重量是指比較臃腫,大而全。

          還是來先看看代碼。


          soup = BeautifulSoup(response, 'html.parser')
          links = soup.findAll("table", {"class": "olt"})[0].findAll('a')

          BeautifulSoup解析內容同樣需要將請求和解析分開,從代碼清晰程度來講還將就,不過在做復雜的解析時代碼略顯繁瑣,總體來講可以用,看個人喜好吧。

          安裝途徑: pip install beautifulsoup4

          4: lxml的XPath

          lxml這個庫同時 支持HTML和XML的解析,支持XPath解析方式,解析效率挺高,不過我們需要熟悉它的一些規則語法才能使用,例如下圖這些規則。

          來看看如何用XPath解析內容。

          主要解析代碼:

          content = doc.xpath("//table[@class='olt']/tr/td/a")


          如上圖,XPath的解析語法稍顯復雜,不過熟悉了語法的話也不失為一種優秀的解析手段,因為。

          安裝途徑: pip install lxml

          四種方式總結

        1. 正則表達式匹配不推薦,因為已經有很多現成的庫可以直接用,不需要我們去大量定義正則表達式,還沒法復用,在此僅作參考了解。
        2. BeautifulSoup是基于DOM的方式,簡單的說就是會在解析時把整個網頁內容加載到DOM樹里,內存開銷和耗時都比較高,處理海量內容時不建議使用。不過BeautifulSoup不需要結構清晰的網頁內容,因為它可以直接find到我們想要的標簽,如果對于一些HTML結構不清晰的網頁,它比較適合。
        3. XPath是基于SAX的機制來解析,不會像BeautifulSoup去加載整個內容到DOM里,而是基于事件驅動的方式來解析內容,更加輕巧。不過XPath要求網頁結構需要清晰,而且開發難度比DOM解析的方式高一點,推薦在需要解析效率時使用。
        4. requests-html 是比較新的一個庫,高度封裝且源碼清晰,它直接整合了大量解析時繁瑣復雜的操作,同時支持DOM解析和XPath解析兩種方式,靈活方便,這是我目前用得較多的一個庫。

        5. 除了以上介紹到幾種網頁內容解析方式之外還有很多解析手段,在此不一一進行介紹了。

          寫一個爬蟲,最重要的兩點就是如何抓取數據,如何解析數據,我們要活學活用,在不同的時候利用最有效的工具去完成我們的目的。

          因篇幅有限,以上四種方式的代碼就不貼在文章里了,歡迎給我私信獲取。

          歡迎關注我 “紙飛機編程”,獲取更多有趣的python教程信息。

          ython爬蟲。

          大家好,我是Python的Python爬蟲。今天給大家演示一個網絡爬蟲的源碼,就是用Python來解析html就是前端的數據。首先可以看到前面有一個支付串,支付串里包含的內容是前端的數據,它有html標簽、Python標簽、玻璃標簽和html標簽。

          然后要通過網絡劃重來提取標簽語的數據。首先寫了一個Python對象的方法。然后把這個文件,文件用PythonL解析器來解析,最后再輸出這個文件。輸出文件之后再打印這個文件的格式,來看一下具體效果。

          可以看到html文件已經打印成功了,它的類型是beautiful soul beautiful Python類型。然后再來獲取一下當前的標簽名,可以看到它或許是title標簽里的內容,可以看到title標簽里的內容是b。然后看打印的結果和這個一分為二。再運行一下,可以看到標簽內容打印的結果是一致的。然后再獲取一下當前的標簽名,看一下打印的內容是否一致。再運行一下,這里出現了一個錯誤。是因為這里有一行代碼,有一個漢字沒有注視掉。

          再運行一下,可以看到這個標簽名還是打印出來了,它和這里的內容是一樣的。再輸出一下標簽,標簽里面的內容。可以看到p標簽點內容就可以打印出來了。然后獲取一下所有的a標簽,可以看到一標簽的內容就打印出來了。然后讀取一下所有的a標簽,看一下剛才的a標簽一共有一個兩個三個在,第三個在這邊,a標簽。

          其中a標簽和a標簽是一樣的,所以一共只打印了一個A4標簽。然后查找一下,a D為Python的標簽。打印一下標a d n minus 三的標簽。可以看到a d 為mix三的標簽,已經顯示出來了。最后打印所的內容。

          把前面都做四個,可以看到標簽里面的內容都出來了,看一下是不是對的。可以看到這個內容和這都對的上。最后一句,最后一句的內容就對的上。今天演示的網絡花叢的視頻就到這里,謝謝大家的收看。


          主站蜘蛛池模板: 亚洲AV无码一区二区三区电影| 日本免费一区二区三区最新 | tom影院亚洲国产一区二区| 国产一区二区精品久久凹凸| 日韩一区二区三区免费播放| 区三区激情福利综合中文字幕在线一区亚洲视频1| 伊人色综合网一区二区三区| 国产成人av一区二区三区在线| 精品国产一区二区三区免费看| 国产一区二区精品久久岳√| 久久99国产一区二区三区| 亚洲国产美国国产综合一区二区 | 国产中的精品一区的| 亚洲一区二区在线视频| 亚洲一区二区三区深夜天堂| 日韩精品久久一区二区三区| 国产美女露脸口爆吞精一区二区| 亚洲国产精品一区二区久久hs | 久久久国产精品亚洲一区| 无码人妻精品一区二区三区9厂| 日本夜爽爽一区二区三区| 亚洲AV综合色区无码一区爱AV| 人妻互换精品一区二区| 久久精品国产一区二区三| 国产av天堂一区二区三区 | 日韩内射美女人妻一区二区三区| 亚洲性无码一区二区三区| 亚洲国产综合无码一区二区二三区| 无码国产精品一区二区免费16| 韩国精品一区二区三区无码视频 | 99久久精品国产高清一区二区 | 无码福利一区二区三区| 麻豆一区二区三区蜜桃免费| 无码视频一区二区三区在线观看| 久久青青草原一区二区| 国产剧情国产精品一区| 色视频综合无码一区二区三区 | 日本精品少妇一区二区三区| 日韩人妻不卡一区二区三区| 亚洲av无码天堂一区二区三区| 精品视频一区二区三区四区|