Python urllib与requests、XML和HTMLParser
Python 的內建模塊urllib提供了一系列用于操作url的方法
Get
urllib的request可以非常方便的抓取URL的內容,通過GET發送一個請求到指定頁面,然后返回HTTP響應
還可以模仿瀏覽器發送一個GET請求,需要request對象,通過向request對象中添加HTTP請求頭,就可以把請求偽裝為一個瀏覽器
Post
需要把參數以bytes類型傳入
Handler
如果還需要更復雜的控制,加入需要通過一個代理去登陸網站,需要使用proxyhandler模塊
urllib提供的功能就是通過程序完成各種各樣的HTTP請求,如果需要模仿瀏覽器完成特定功能,需要將請求偽裝為瀏覽器請求,偽裝的方法是先監控瀏覽器發出的請求,然后再根據瀏覽器的請求頭來偽裝,User-Agent頭就是用來識別瀏覽器的
requests
requests是用于操作URl的第三方模塊,相比Python提供的內建模塊urllib,此模塊使用起來更方便
使用GET訪問一個頁面
-
使用params參數傳入一個dict類型的參數做為訪問url的參數
-
使用headers參數,傳入一個dict類型的參數作為請求頭
requests默認使用application/x-www-form-urlencoded對POST數據編碼。如果要傳遞JSON數據,可以直接傳給json參數
params = {'key': 'value'} r = requests.post(url, json=params) # 內部自動序列化為JSON如果需要上傳文件,可以直接將一個file對象傳給files參數
>>> upload_files = {'file': open('report.xls', 'rb')} >>> r = requests.post(url, files=upload_files)在讀取文件時,注意務必使用’rb’即二進制模式讀取,這樣獲取的bytes長度才是文件的長度。
把post()方法替換為put(),delete()等,就可以以PUT或DELETE方式請求資源。
除了能輕松獲取響應內容外,requests對獲取HTTP響應的其他信息也非常簡單。
例如,獲取響應頭
>>> r.headers {Content-Type': 'text/html; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Content-Encoding': 'gzip', ...} >>> r.headers['Content-Type'] 'text/html; charset=utf-8'requests對Cookie做了特殊處理,使得我們不必解析Cookie就可以輕松獲取指定的Cookie
>>> r.cookies['ts'] 'example_cookie_12345'要在請求中傳入Cookie,只需準備一個dict傳入cookies參數
可以使用encoding屬性查看編碼
無論響應的內容是文本或者二進制文件,都可以使用content屬性獲取其bytes對象
如果響應的是特定的類型,比如Json,可以使用json()方法直接獲取
最后,要指定超時,傳入以秒為單位的timeout參數:
>>> r = requests.get(url, timeout=2.5) # 2.5秒后超時XML
操作XML有兩種方法:DOM和SAX。DOM會把整個XML讀入內存,解析為樹,因此占用內存大,解析慢,優點是可以任意遍歷樹的節點。SAX是流模式,邊讀邊解析,占用內存小,解析快,缺點是我們需要自己處理事件。
正常情況下,優先考慮SAX,因為DOM實在太占內存。
注意使用attrs這個值
當SAX解析器讀到一個節點時:
<a href="/">python</a>會產生3個事件:
start_element事件,在讀取時;
char_data事件,在讀取python時;
end_element事件,在讀取時。
什么是事件呢?
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' from xml.parsers.expat import ParserCreate class DefaultSaxHandler(object):def start_element(self,name,attrs):print('sax:start_element:%s,attrs:%s'%(name,str(attrs)))#這里可以寫 當讀到這里時要發生的事件def end_element(self,name):print('sax:end_element:%s'%name)#這里可以寫 當讀到這里時要發生的事件def char_data(self,text):print('sax:char_data:%s'%text)#這里可以寫 當讀到這里時要發生的事件 xml = r'''<?xml version="1.0"?> <ol><li><a href="/python">Python</a></li><li><a href="/ruby">Ruby</a></li> </ol> ''' handler=DefaultSaxHandler() parser=ParserCreate() parser.StartElementHandler=handler.start_element parser.EndElementHandler=handler.end_element parser.CharacterDataHandler=handler.char_data parser.Parse(xml) #輸出 sax:start_element:ol,attrs:{} sax:char_data:sax:char_data: sax:start_element:li,attrs:{} sax:start_element:a,attrs:{'href': '/python'} sax:char_data:Python sax:end_element:a sax:end_element:li sax:char_data:sax:char_data: sax:start_element:li,attrs:{} sax:start_element:a,attrs:{'href': '/ruby'} sax:char_data:Ruby sax:end_element:a sax:end_element:li sax:char_data:sax:end_element:ol需要注意的是讀取一大段字符串時,CharacterDataHandler可能被多次調用,所以需要自己保存起來,在EndElementHandler里面再合并。
除了解析XML外,如何生成XML呢?99%的情況下需要生成的XML結構都是非常簡單的,因此,最簡單也是最有效的生成XML的方法是拼接字符串:
如果要生成復雜的XML呢?建議你不要用XML,改成JSON。
解析XML時,注意找出自己感興趣的節點,響應事件時,把節點數據保存起來。解析完畢后,就可以處理數據。
比如可以解析XML數據獲得相關城市的天氣信息(略)
HTMLParser
當我們爬取了網頁,下一步就是解析HTML頁面,看看里面的內容,到底是圖片、視頻還是文本。
利用HTMLParser,可以把網頁中的文本、圖像等解析出來。
HTML本質上是XML的子集,但是語法沒有XML要求的那么嚴格,所以不能通過標準的DOM或者SAX來解析HTML
好在Python提供了HTMLParser來非常方便地解析HTML,只需簡單幾行代碼:
注意使用attrs這個值,可以用來抽取鏈接、識別id為某個值元素
from html.parser import HTMLParser from html.entities import name2codepointclass MyHTMLParser(HTMLParser):def handle_starttag(self, tag, attrs):print('<%s>' % tag)def handle_endtag(self, tag):print('</%s>' % tag)def handle_startendtag(self, tag, attrs):print('<%s/>' % tag)#如img標簽<img src="",alt=""/>def handle_data(self, data):print(data)def handle_comment(self, data):print('<!--', data, '-->')def handle_entityref(self, name):#解析特殊字符print('&%s;' % name)def handle_charref(self, name):#解析特殊字符print('&#%s;' % name)parser = MyHTMLParser() parser.feed('''<html> <head></head> <body> <!-- test html parser --><p>Some <a href=\"#\">html</a> HTML tutorial...<br>END</p> </body></html>''') #輸出 (sort) λ python fortest.py <html><head> </head><body><!-- test html parser --><p> Some <a> html </a>HTML tutorial... <br> END </p></body> </html>feed()方法可以多次調用,也就是不一定一次把整個HTML字符串都塞進去,可以一部分一部分塞進去。
可是這樣怎么識別有特定id的標簽呢?,注意使用attrs這個值
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' def find_id(self,id_name,attrs):for i in attrs:if id_name in i:return Truereturn Falsedef handle_starttag(self, tag, attrs):if self.find_id('test1',attrs):print('<%s%s>' %(tag,str(attrs)))passparser.feed('''<html> <head></head> <body> <!-- test html parser --><p class='test' id='test1'>Some <a href=\"#\">html</a> HTML tutorial...<br>END</p> </body></html>''')#輸出 pass <p[('class', 'test'), ('id', 'test1')]> pass特殊字符有兩種,一種是英文表示的?,一種是數字表示的?,這兩種字符都可以通過Parser解析出來。
總結
以上是生活随笔為你收集整理的Python urllib与requests、XML和HTMLParser的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中的del,remove,p
- 下一篇: Python struct与小端存储