一.理解網路爬蟲
1.1爬蟲的定義
網路爬蟲又稱為網頁蜘蛛、網路機器人,網路爬蟲是一種按照一定的規則自動的抓取網路資訊的程式或者腳本,通俗的說,就是根據一定的演算法實作編程開發,主要通過URL實作資料的抓取和挖掘,
1.2爬蟲的型別
根據系統結構和開發技術大致可分為4種型別:
(1)通用網路爬蟲,又稱為全網爬蟲,常見的有百度,Google等,
(2)聚焦網路爬蟲,又稱主題網路爬蟲,是選擇性的爬行根據需求的主題相關頁面的網路爬蟲,
(3)增量式網路爬蟲,是指對已下載網頁采取增量式更新和只爬行新產生或者已經發生變化的網頁的爬蟲,它能夠在一定程度上保證所爬行的頁面盡可能是新的頁面,只會在需要的時候爬行新產生或發生更新的頁面,并不重新下載沒有發生變化的頁面,這類爬蟲在實際中不太普及,
(4)深層網路爬蟲,是大部分內容不能通過靜態URL獲取的,隱藏在表單后的,只有用戶提交一些關鍵詞才能獲得的網路頁面,
這四類大致又可以分為兩類,通用爬蟲和聚焦爬蟲,聚焦網路爬蟲,增量式網路爬蟲和深層網路爬蟲可歸為一類,因為他們是定向爬蟲資料,而通用爬蟲在網路上稱為搜索引擎,
爬蟲的設計思路:
(1) 明確需要爬取的網頁的URL地址;
(2)通過http請求來獲取對應的HTML頁面;
(3)提取HTML的內容,若是有用的資料,就保存起來;若是繼續爬取的頁面,就重新指定第(2)步,
二.爬蟲開發基礎
2.1 HTTP與HTTPS
http是一個簡單的請求-回應協議,它通常運行在TCP之上,它指定了客戶端可能發送給服務器什么樣的訊息以及得到什么樣的回應,客戶端是終端用戶,服務器端是網站,通常使用web瀏覽器,網路爬蟲或者其他工具,客戶端會發起一個到服務器上指定的http請求,這個客戶端就叫做用戶代理(User Agent),一旦收到請求,服務器會發回一個狀態行(如“http/1.1 200 OK”)和 回應的 訊息,其中訊息的內容可能是請求的檔案,錯誤訊息或者其他訊息,
http協議傳輸的資料都是未加密的,因此使用http協議傳輸隱私資訊非常不安全,
https協議傳輸的資料都是加密的,在傳輸資料之前需要客戶端與服務端之間進行一次握手,在握手程序中將確立雙方加密傳輸資料的密碼資訊,
2.2 請求頭
請求頭描述客戶端向服務器發送請求時使用的協議型別,所使用的編碼以及發送內容的長度等,檢測請求頭是常見的反爬蟲策略,因為服務器會對請求頭做一次檢測來判斷此次請求是人為的還是非人為的,所以我們在每次發送請求時都添加上請求頭,
請求頭的引數如下:
(1)Accept:瀏覽器可以接收的型別
(2)Accept-Charset:編碼型別
(3)Accept-Encoding:可以接收壓縮編碼型別
(4)Accept-Language:可以接收的語言和國家型別
(5)Host:請求的主機地址和埠
(6)Referer:請求來自于那個頁面的URL
(7)User-Agent:瀏覽器相關資訊
(8)Cookie:瀏覽器暫存服務器發送的資訊
(9)Connection:http請求版本的特點
(10)Date:請求網站的時間
2.3 cookies
它是指某些網站為了辯護用戶身份,進行session跟蹤而存盤在用戶本地終端上的資料,一個cookies就是存盤在用戶主機瀏覽器 的文本檔案,
服務器可以利用cookies包含的資訊判斷在http傳輸中的狀態,
2.4 JSON
JSON(JavaScript Object Notation, JS 物件簡譜) 是一種輕量級的資料交換格式,它基于ECMAScript (歐洲計算機協會制定的js規范)的一個子集,采用完全獨立于編程語言的文本格式來存盤和表示資料,簡潔和清晰的層次結構使得 JSON 成為理想的資料交換語言, 易于人閱讀和撰寫,同時也易于機器決議和生成,并有效地提升網路傳輸效率,
例如:
{"name": "John Doe", "age": 18, "address": {"country" : "china", "zip-code": "10000"}}
2.5 JavaScript
JavaScript(簡稱“JS”) 是一種具有函式優先的輕量級,解釋型或即時編譯型的高級編程語言,是一種解釋性腳本語言(代碼不進行預編譯), 主要用來向HTML(標準通用標記語言下的一個應用)頁面添加互動行為,
JavaScript還能根據用戶觸發某些事件對用戶的操作進行加工處理,要在爬蟲實作一些功能,就要分析JS如何執行整個用戶登錄程序,
2.6 Ajax
Ajax 不是一種新的編程語言,而是一種用于創建更好更快以及互動性更強的Web應用程式的技術,使用 JavaScript 向服務器提出請求并處理回應而不阻塞用戶核心物件XMLHttpRequest,通過這個物件,您的 JavaScript 可在不多載頁面的情況與 Web 服務器交換資料,即在不需要重繪頁面的情況下,就可以產生區域重繪的效果, Ajax 在瀏覽器與 Web 服務器之間使用異步資料傳輸(HTTP 請求),這樣就可使網頁從服務器請求少量的資訊,而不是整個頁面, 判斷網頁資料是否使用ajax的方法:觸發事件之后,判斷網頁是否發生重繪狀態,若網頁沒有發生重繪,資料就自動生成,說明資料的加載是通過ajax生成并渲染到網頁上的,反之,數據是通過服務器后臺生成并加載的,三.Fiddler抓包工具
Fiddler是一個http協議除錯代理工具,它能夠記錄并檢查所有你的電腦和互聯網之間的http通訊,設定斷點,查看所有的“進出”Fiddler的資料(指cookie,html,js,css等檔案),
3.1 fiddler安裝配置
在官網網站下載(https://www.telerik.com/download/fiddler),界面如下圖所示:
配置fiddler,使其能夠抓取https請求資訊:
(1)打開選單-tools-fidder options-https,
(2)勾選https中的選項,然后點擊actions-trust root certificate,完成整數驗證,

3.2 fiddler抓取手機應用
fiddler可通過同一無線網路實作對手機應用的抓包,手機抓包主要通過遠程連接實作手機和fiddler通信,
實作fiddler抓取手機應用的步驟如下:
(1)配置fiddler遠程連接模式,打開選單欄:tools--fiddler options--connections,把allow remote computers to connect勾選上,
(2)在手機端進行引數配置,要連接在同一個IP地址上(cmd中輸入ipconfig查看IP地址)
(3)在手機瀏覽器中輸入電腦IP地址和fiddler埠,點擊確認后跳轉到證書下載頁面,點擊下載fiddlerroot certificate.
(4)證書檔案以cer為后綴名,完成證書安裝后,進入手機當前連接WiFi詳情,設定代理IP,主機名為電腦IP地址,埠為fiddler配置的埠,

四.開始爬蟲
4.1 urllib模塊
在python3中不存在urllib2模塊,同一為urllib,urllib模塊有如下四個子模塊:
1 urllib.request:用來打開和讀取URL, 2 urllib.error:包含了urllib.request產生的例外, 3 urllib.parse:用來決議和處理URL, 4 urllib.robotparse:用于決議robots.txt檔案,
urllib的方法及使用:
1 urllib.urlopen(url[, data[, proxies[,timeout[, context]]]]) 功能說明:urllib是用于訪問URL的唯一方法
引數解釋:
url :一個完整的遠程資源路徑,一般是一個網站, data:默認值為none,若引數data為none,則代表請求方式為get,反之請求方式為post,發送post請求,引數data以字典形式存盤資料,并將引數data由字典型別轉換成位元組型別才能完成post請求, proxies : 設定代理 timeout:超時設定 context:描述各種SSL選項的實體,
2 urllib.request.Request(url,data=https://www.cnblogs.com/z-8888/p/none,headers={},method=none)
功能說明:宣告一個request物件,該物件可定義header等請求資訊
引數解釋:
headers:設定request請求頭資訊
method:設定請求方式,主要是get和post
"""urllib的使用"""
import urllib.request # 向指定URL發送請求,獲取回應, response = urllib.request.urlopen('http://httpbin.org/anything') # 獲取回應內容 content = response.read().decode('utf-8') print(content) print(type(response)) # 回應碼 print(response.status) # 回應頭資訊 print(response.headers)
# 匯入urllib import urllib.request url = 'https://movie.douban.com/' # 自定義請求頭 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)' 'Chrome/45.0.2454.85 Safari/537.36 115Browser/6.0.3', 'Referer': 'https://movie.douban.com/', 'Connection': 'keep-alive'} # 設定request的請求頭 req = urllib.request.Request(url, headers=headers) # 使用urlopen打開req html = urllib.request.urlopen(req).read().decode('utf-8') # 寫入檔案 f = open('code2.txt', 'w', encoding='utf8') f.write(html) f.close()
4.2 requests模塊
requests模塊是在urllib的基礎上做了封裝,具備urllib的全部功能,讓使用者更加方便的使用,
安裝:pip install requests
4.2.1 發出請求
有兩種方式:requests.get()和requests.post()方法
1 requests.get(url, params=none, **kwargs) 2 requests.post(url, data=https://www.cnblogs.com/z-8888/p/none, json=none, **kwargs)
requests提供如下方法獲取回應內容:
1 r.status_code:回應狀態碼(200表示訪問成功,4**表示失敗) 2 r.raw:原始回應體,使用r.raw.read()讀取 3 r.content:位元組方式的回應體,需要進行解碼 4 r.text:字串方式的回應體,會自動根據回應頭部的字符編碼進行解碼 5 r.headers:以字典物件存盤服務器回應頭,若鍵不存在,則回傳none 6 r.json():requests中內置的json解碼器 7 r.raise_for_status():請求失敗(非200回應),拋出例外 8 r.url:獲取請求鏈接 9 r.cookies:獲取請求后的cookies 10 r.encoding:獲取編碼格式
"""使用requests發送請求和攜帶引數""" import requests r = requests.get('https://httpbin.org/get') # 發送get請求 print(r.text) # 發送post請求,并帶引數 r = requests.get('https://httpbin.org/get', params={'key1': 'value1', 'key2': 'value2'}) print(r.text) # 發送post請求,并傳遞引數 r = requests.post('https://httpbin.org/post', data=https://www.cnblogs.com/z-8888/p/{'key': 'value'}) print(r.text) # 其他HTTP請求型別:PUT,DELETE,HEAD和OPTIONS r = requests.put('https://httpbin.org/put', data=https://www.cnblogs.com/z-8888/p/{'key': 'value'}) print(r.text) r = requests.delete('https://httpbin.org/delete') print(r.text) r = requests.head('https://httpbin.org/get') print(r.text) r = requests.options('https://httpbin.org/get') print(r.text)
4.2.2 復雜的請求方式
(1)添加請求頭 import requests headers = { 'content-type': 'application/json', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0'} requests.get("https://www.baidu.com/", headers=headers) (2)使用代理IP import requests proxies = { "http": "http://10.10.1.10:3128", "https": "http://10.10.1.10:1080", } requests.get("https://www.baidu.com/", proxies=proxies) (3)證書驗證 import requests url = 'https://kyfw.12306.cn/otn/leftTicket/init' # 關閉證書驗證 r = requests.get(url, verify=False) print(r.status_code) # 開啟證書驗證 # r = requests.get(url, verify=True) # 設定證書所在路徑 # r = requests.get(url, verify= '/path/to/certfile') (4)超時設定 requests.get("https://www.baidu.com/", timeout=2) requests.post("https://www.baidu.com/", timeout=2) (5)使用cookies
import requests temp_cookies='JSESSIONID_GDS=y4p7osFr_IYV5Udyd6c1drWE8MeTpQn0Y58Tg8cCONVP020y2N!450649273;name=value' cookies_dict = {} for i in temp_cookies.split(';'): value = i.split('=') cookies_dict [value[0]] = value[1] r = requests.get(url, cookies=cookies) print(r.text)
4.2.3 錯誤和例外
若出現網路問題,則請求將引發connectionerror例外,
若http請求回傳不成功的狀態碼,則將會引發httperror例外,
若請求超時,則會引起超時例外,
若請求超過配置的最大重定向數,則會引發TooManyRedirects例外,
請求顯示引發的所有例外都繼承自requests.exceptions.RequestException,
4.3 re模塊
正則運算式是對字串操作的一種邏輯公式,就是用事先定義好的一些特定字符、及這些特定字符的組合,組成一個“規則字串”,這個“規則字串”用來表達對字串的一種過濾邏輯,
正則運算式是對字串(包括普通字符(例如,a 到 z 之間的字母)和特殊字符(稱為“元字符”))操作的一種邏輯公式,就是用事先定義好的一些特定字符、及這些特定字符的組合,組成一個“規則字串”,這個“規則字串”用來表達對字串的一種過濾邏輯,正則運算式是一種文本模式,該模式描述在搜索文本時要匹配的一個或多個字串,
語法請參考:https://www.runoob.com/regexp/regexp-tutorial.html
4.3.1 模塊內容
1. re.match(pattern, string[, flags])
這個方法將會從string(我們要匹配的字串)的開頭開始,嘗試匹配pattern,一直向后匹配,如果遇到無法匹配的字符,立即回傳None,如果匹配未結束已經到達string的末尾,也會回傳None,兩個結果均表示匹配失敗,否則匹配pattern成功,同時匹配終止,不再對string向后匹配,
"""match方法""" import re # match在起始位置匹配 ret = re.match('www', 'www.example.com') print(type(ret)) # 獲取匹配的內容 print(ret.group()) # 獲取匹配內容在原字串里的下標 print(ret.span()) # 匹配不成功,回傳None print(re.match('com', 'www.example.com')) line = "Cats are smarter than dogs" matchObj = re.match(r'(.*) are (.*?) .*', line, re.M | re.I) if matchObj: print("matchObj.group() : ", matchObj.group()) # 獲取第一組的內容 print("matchObj.group(1) : ", matchObj.group(1)) print("matchObj.group(2) : ", matchObj.group(2)) else: print("No match!!")
引數說明: ? pattern:匹配的正則運算式 ? string:要匹配的字串 ? flags:標志位,用于控制正則運算式的匹配方式,如是否區分大小寫,是否多行匹配等, flags引數可選值: ? re.I: 忽略大小寫(括號內是完整寫法,下同) ? re.M: 多行模式,改變'^'和'$'的行為(參見上圖) ? re.S: 點任意匹配模式,改變'.'的行為 ? re.L: 使預定字符類 \w \W \b \B \s \S 取決于當前區域設定 ? re.U: 使預定字符類 \w \W \b \B \s \S \d \D 取決于unicode定義的字符屬性 ? re.X: 詳細模式,這個模式下正則運算式可以是多行,忽略空白字符,并可以加入注釋,
2. re.search(pattern, string[, flags])
search方法與match方法極其類似,區別在于match()函式只檢測re是不是在string的開始位置匹配,search()會掃描整個string查找匹配,match()只有在0位置匹配成功的話才有回傳,如果不是開始位置匹配成功的話,match()就回傳None,同樣,search方法的回傳物件同樣match()回傳物件的方法和屬性,
"""search方法""" import re # search查找第一次出現 ret = re.search('www', 'www.aaa.com www.bbb.com') print(type(ret)) print(ret.group()) print(ret.span()) #匹配不成功,回傳None print(re.search('cn', 'www.aaa.com www.bbb.com')) line = "Cats are smarter than dogs"; searchObj = re.search(r'(.*) are (.*?) .*', line, re.M | re.I) if searchObj: print("searchObj.group() : ", searchObj.group()) print("searchObj.group(1) : ", searchObj.group(1)) print("searchObj.group(2) : ", searchObj.group(2)) else: print("Nothing found!!")
3. re.findall(pattern, string[, flags])
搜索string,以串列形式回傳全部能匹配的子串,
"""findall方法""" import re # 查找數字 result1 = re.findall(r'\d+','baidu 123 google 456') result2 = re.findall(r'\d+','baidu88oob123google456') print(result1) print(result2)
4. re.finditer(pattern, string[, flags])
搜索string,回傳一個順序訪問每一個匹配結果(Match物件)的迭代器,
"""finditer方法""" import re #回傳一個迭代器,可以回圈訪問,每次獲取一個Match物件 it = re.finditer(r"\d+", "12a32bc43jf3") for match in it: print(match.group())
5. re.split(pattern, string[, maxsplit])
按照能夠匹配的子串將string分割后回傳串列,maxsplit用于指定最大分割次數,不指定將全部分割,
6. re.sub(pattern, repl, string, count=0, flags=0)
"""sub方法""" import re phone = "2004-959-559 # 這是一個國外電話號碼" # 洗掉字串中的 Python注釋 num = re.sub(r'#.*$', "", phone) print("電話號碼是: ", num) # 洗掉非數字(-)的字串 num = re.sub(r'\D', "", phone) print("電話號碼是 : ", num) # 將匹配的數字乘以 2 def double(matched): value = int(matched.group('value')) return str(value * 2) s = 'A23G4HFD567' print(re.sub('(?P<value>\d+)', double, s))
引數說明:
1 repl:用于替換的字串 2 string:要被替換的字串 3 count:替換的次數
7. re.subn(pattern, repl, string[, count])
與sub()函式一致,回傳結果是一個元組,
8. re.compile(pattern[, flags])
該函式用于編譯正則運算式生成一個正則運算式(pattern)物件,供match()和search()等函式使用,
"""compile方法""" import re # 用于匹配至少一個數字 pattern = re.compile(r'\d+') # 查找頭部,沒有匹配 m = pattern.match('one12twothree34four') print(m) # 從'e'的位置開始匹配,沒有匹配 m = pattern.match('one12twothree34four', 2, 10) print(m) # 從'1'的位置開始匹配,正好匹配,回傳一個 Match 物件 m = pattern.match('one12twothree34four', 3, 10) print(m) # 可省略 0 print(m.group(0))
4.4BeautifulSoup4模塊
4.4.1 簡介
Beautiful Soup,有了它我們可以很方便地提取出 HTML 或 XML 標簽中的內容,BeautifulSoup是一個高效的網頁決議庫,可以從 HTML 或 XML 檔案中提取資料,
beautifulsoup支持不同的決議器,比如,對HTML決議,對XML決議,對HTML5決議,一般情況下,我們用的比較多的是 lxml 決議器,
4.4.2 安裝
1 pip install beautifulsoup4
使用時匯入:
1 from bs4 import BeautifulSoup
4.4.3 BeautifulSoup庫決議器
| 決議器 | 使用方法 | 條件 |
| bs4的HTML決議器 | BeautifulSoup(html,'html.parser') | 安裝bs4庫 |
| lxml的HTML決議器 | BeautifulSoup(html,'lxml') | pip install lxml |
| lxml的XML決議器 | BeautifulSoup(html,'xml') | pip install lxml |
| html5lib的決議器 | BeautifulSoup(html,'htmlslib') | pip install html5lib |
4.4.4 使用
"""將字串決議為HTML檔案決議""" from bs4 import BeautifulSoup html = """ <html><head><title>The Dormouse's story</title></head> <body> <p name="dromouse"><b>The Dormouse's story</b></p> <p >Once upon a time there were three little sisters; and their names were <a href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a href="http://example.com/lacie" id="link2">Lacie</a> and <a href="http://example.com/tillie" id="link3">Tillie</a>; and they lived at the bottom of a well.</p> <p >...</p> """ # 創建BeautifulSoup物件決議html,并使用lxml作為xml決議器soup = BeautifulSoup(html, 'lxml') # 格式化輸出soup物件的內容 print(soup.prettify())
例一:
"""bs4實體測驗""" from bs4 import BeautifulSoup import re html = """ <html><head><title>The Dormouse's story</title></head> <body> <p name="dromouse"><b>The Dormouse's story</b></p> <p >Once upon a time there were three little sisters; and their names were <a href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a href="http://example.com/lacie" id="link2">Lacie</a> and <a href="http://example.com/tillie" id="link3">Tillie</a>; and they lived at the bottom of a well.</p> <p >...</p> """ # 創建物件 soup = BeautifulSoup(html, 'lxml') # 獲取Tag物件 # 查找的是在所有內容中的第一個符合要求的標簽 print(soup.title) print(type(soup.title)) print(soup.p) # 標簽的名字 print(soup.p.name) # 標簽的屬性,可獲取,也可以設定 print(soup.p.attrs) print(soup.p.attrs['class']) # 文本 print(soup.p.string) # content屬性得到子節點,串列型別 print(soup.body.contents) # children屬性屬性得到子節點,可迭代物件 print(soup.body.children) # descendants屬性屬性得到子孫節點,可迭代物件 print(soup.body.descendants) # find_all 查找所有符合要求的 name是按照標簽名字查找 print(soup.find_all(name='b')) print(soup.find_all(name=['a', 'b'])) print(soup.find_all(name=re.compile("^b"))) # find_all 查找所有符合要求的 可以按照屬性查找,比如這里的id,class # 因為class是關鍵字,所以使用class_代替class print(soup.find_all(id='link2')) print(soup.find_all(class_='sister')) # select 查找所有符合要求的 支持選擇器 print(soup.select('title')) print(soup.select('.sister')) print(soup.select('#link1')) print(soup.select('p #link1')) print(soup.select('a[]')) # 獲取內容 print(soup.select('title')[0].get_text())
例二:
>>> from bs4 import BeautifulSoup
>>> import requests
>>> r = requests.get("http://python123.io/ws/demo.html")
>>> demo = r.text
>>> demo
'<html><head><title>This is a python demo page</title></head>\r\n<body>\r\n<p ><b>The demo python introduces several python courses.</b></p>\r\n<p >Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:\r\n<a href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a> and <a href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>.</p>\r\n</body></html>'
>>> soup = BeautifulSoup(demo,"html.parser")
>>> soup.title #獲取標題
<title>This is a python demo page</title>
>>> soup.a #獲取a標簽
<a href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>
>>> soup.title.string
'This is a python demo page'
>>> soup.prettify() #輸出html標準格式內容
'<html>\n <head>\n <title>\n This is a python demo page\n </title>\n </head>\n <body>\n <p >\n <b>\n The demo python introduces several python courses.\n </b>\n </p>\n <p >\n Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:\n <a href="http://www.icourse163.org/course/BIT-268001" id="link1">\n Basic Python\n </a>\n and\n <a href="http://www.icourse163.org/course/BIT-1001870001" id="link2">\n Advanced Python\n </a>\n .\n </p>\n </body>\n</html>'
>>> soup.a.name #每個<tag>都有自己的名字,通過<tag>.name獲取
'a'
>>> soup.p.name
'p'
>>> tag = soup.a
>>> tag.attrs
{'href': 'http://www.icourse163.org/course/BIT-268001', 'class': ['py1'], 'id': 'link1'}
>>> tag.attrs['class']
['py1']
>>> tag.attrs['href']
'http://www.icourse163.org/course/BIT-268001'
>>> type(tag.attrs)
<class 'dict'>
>>> type(tag)
<class 'bs4.element.Tag'>
五.更多資料提取的方式
5.1 XPath和lxml
5.1.1 xml
xml被用來傳輸和存盤資料,參考:https://www.runoob.com/xml/xml-tutorial.html
5.1.2 xpath
參考:https://www.runoob.com/xpath/xpath-tutorial.html
5.1.3 lxml
xml被設計用來傳輸和存盤資料,HTML被設計用來顯示資料,這兩個都是樹形結構,可以先將HTML檔案轉換成xml檔案,然后用xpath語法查找HTML節點或元素,這樣就用到了lxml模塊
# lxml安裝: pip install lxml # 使用 (1) """將字串決議為HTML檔案""" from lxml import etree text=''' <div> <ul> <li><ahref="https://www.cnblogs.com/z-8888/p/link1.html">firstitem</a></li> <li><ahref="https://www.cnblogs.com/z-8888/p/link2.html">seconditem</a></li> <li><ahref="https://www.cnblogs.com/z-8888/p/link3.html">thirditem</a></li> <li><ahref="https://www.cnblogs.com/z-8888/p/link4.html">fourthitem</a></li> <li><ahref="https://www.cnblogs.com/z-8888/p/link5.html">fifthitem</a> </ul> </div> ''' #利用etree.HTML,將字串決議為HTML檔案 html=etree.HTML(text) #按字串序列化HTML檔案 result=etree.tostring(html).decode('utf-8') print(result) (2) """讀檔案""" from lxml import etree # 讀取外部檔案hello.html html = etree.parse('./data/hello.html') # pretty_print=True表示格式化,比如左對齊和換行 result = etree.tostring(html, pretty_print=True).decode('utf-8') print(result)
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/228952.html
標籤:大數據
上一篇:Clickhouse 入門
