python自帶的urllib使用

1.urllib中request構建完整請求

"""request構建完整請求"""
from urllib import request


# Request封裝url
req = request.Request("https://python.org")
# 發起請求並保存請求結果
res = request.urlopen(req)
# 打印響應信息
print(res.read().decode("utf-8"))


"""
class Request:

    def __init__(self, url, data=None, headers={},
                 origin_req_host=None, unverifiable=False,
                 method=None):
    參數解析:
    url:請求URL
    data:跟urlopen裏面的data傳遞同樣的bytes類型數據
    headers:請求頭可直接構造,也能夠使用類方法add_header()傳遞參數
    origin_req_host:請求時的host名稱或者IP
    unverifiable:權限操做,有或者沒有。默認False,表示用戶沒有權限選擇接受這個請求的結果
    method:請求時的方法,好比GET,POST,DELETE等
"""




from urllib import request, parse


# 設置請求的url
url = "http://httpbin.org/post"
# 設置請求頭信息
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
    "Host": "httpbin.org"
}
dict = {"name": "Germey"}
# 把字典轉換成字節流信息
data = bytes(parse.urlencode(dict), encoding="utf8")
# 參數按值傳遞
req = request.Request(url=url, data=data, headers=headers, method="POST")
# 發起請求並保存請求結果
res = request.urlopen(req)
# 打印響應信息
print(res.read().decode("utf-8"))
View Code

2.request中urlopen的get請求分析

"""urlopen的get分析"""
from urllib import request
from http.client import HTTPResponse  # 引用


res = request.urlopen("https://www.python.org")
print(type(res))        # 打印返回結果的類型,用from引用這個類型查看具有的方法和屬性
print(res.status)       # 返回相應的狀態碼
print(res.getheaders())     # 返回全部請求頭信息
print(res.getheader("Server"))      # 返回服務器信息,nginx。socket服務器中比較牛逼的一種

# def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
#             *, cafile=None, capath=None, cadefault=False, context=None):
"""
源碼解釋:
打開URL url,能夠是字符串或Request對象。

    * data *必須是指定要發送到的其餘數據的對象
    服務器,若是不須要這樣的數據,則爲None。請參閱請求
    細節。

    urllib.request模塊使用HTTP / 1.1幷包含「Connection:close」
    HTTP請求中的標頭。

    可選的* timeout *參數指定超時(以秒爲單位)
    阻塞操做,如鏈接嘗試(若是未指定,則
    將使用全局默認超時設置)。這僅適用於HTTP,
    HTTPS和FTP鏈接。

    若是指定了* context *,則它必須是描述的ssl.SSLContext實例
    各類SSL選項。有關更多詳細信息,請參閱HTTPSConnection。

    可選的* cafile *和* capath *參數指定一組可信CA.
    HTTPS請求的證書。 cafile應該指向一個文件
    包含一捆CA證書,而capath應指向a
    哈希證書文件的目錄。更多信息能夠在中找到
    ssl.SSLContext.load_verify_locations()。

    * cadefault *參數被忽略。

    此函數始終返回可用做上下文的對象
    經理和有方法,如

    * geturl() - 返回檢索到的資源的URL,經常使用於
      肯定是否遵循重定向

    * info() - 返回頁面的元信息,例如標題
      email.message_from_string()實例的形式(請參閱快速參考
      HTTP標頭)

    * getcode() - 返回響應的HTTP狀態代碼。引起URLError
      關於錯誤。

    對於HTTP和HTTPS URL,此函數返回http.client.HTTPResponse
    對象略有修改。除了以上三種新方法外,還有
    msg屬性包含與reason屬性相同的信息---
    服務器返回的緣由短語 - 而不是響應
    在HTTPResponse的文檔中指定的標頭。

    對於遺留顯式處理的FTP,文件和數據URL以及請求
    URLopener和FancyURLopener類,這個函數返回一個
    urllib.response.addinfourl對象。
"""
View Code

3.request中urlopen的post請求分析

"""urlopen的post請求分析"""
from urllib import parse
from urllib import request
import json


# 轉換utf8編碼的data數據
data = bytes(parse.urlencode({"word": "hello"}), encoding="utf8")
# parse.urlencode({"word": "hello"})    返回字符串形式'word=hello'
print(data)       # b'word=hello'    返回bytes類型數據與下面json區別
print(type(data))    # <class 'bytes'>
res = request.urlopen("http://httpbin.org/post", data=data)
print(res)          # <http.client.HTTPResponse object at 0x00000184DB1C3E10>   返回響應對象
print(type(res))    # <class 'http.client.HTTPResponse'>   對象類型
print(res.read())   # 讀取返回的內容中b'"form":{"word":"hello"},'此字段代表模擬了表單提交的方式
arg = json.dumps({"word": "hello"})
print(arg)          # '{"word": "hello"}' json返回字符串形式字典數據
print(type(arg))    # <class 'str'>
View Code

4.request中urlopen的異常處理

"""urllib的異常處理"""
from urllib import request, error


try:
    res = request.urlopen("https://home.cnblogs.com/u/Guishuzhe/1")
except error.HTTPError as e:
    # 先捕獲子類詳細異常緣由
    print(e.reason, e.code, e.headers)
except error.URLError as e:
    # 再用父類捕獲子類中沒有的異常
    print(e.reason)
else:
    print("Request Successfully")



import socket
from urllib import request
from urllib import error


try:
    # 設置超時時間timeout=0.2
    res = request.urlopen("http://httpbin.org/get", timeout=0.2)
# 捕捉超時異常,返回友好信息
except error.URLError as e:
    print(type(e.reason))
    # class URLError(OSError):源碼  self.reason屬性, e.reason調用這個屬性
    # 內置函數isinstance判斷錯誤對象是否是某一類型
    # 在這裏是鏈接超時錯誤socket.timeout
    if isinstance(e.reason, socket.timeout):
        print("超時了")
View Code

5.urllib進階設置Handlerhtml

"""urllib進階設置Handler工具"""
from urllib.request import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener
from urllib.error import URLError


username = "username"
password = "password"
url = "http://127.0.0.1:8000/"
# 實例化一個待處理對象
p = HTTPPasswordMgrWithDefaultRealm()
# 給實例化對象添加請求參數realm=None等..
p.add_password(None, url, username, password)
# class AbstractBasicAuthHandler:找到父類並實例化出具體請求對象(Handler)
auth_handler = HTTPBasicAuthHandler(p)
# build_opener()方法接受*Handlers任意個Handler對象進行去重等處理,返回Opener對象
opener = build_opener(auth_handler)

try:
    # 開始請求
    res = opener.open(url)
    # 獲取請求結果
    html = res.read().decode("utf8")
    print(html)
except URLError as e:
    # 打印錯誤信息
    print(e.reason)


"""
HITPDefaultErrorHandler :用於處理HTTP響應錯誤,錯誤都會拋出HTTPError類型的異常
HTTPRedirectHandler :用於處理重定向
HTTPCookieProcessor 用於處理Cookies
ProxyHandler :用於設置代理默認代理爲空
HπPPasswordMgr :用於管理密碼,它維護了用戶名和密碼的表
HTTPBasicAuthHandler 用於管理認證,若是一個連接打開時須要認證,那麼能夠用它來解決認證問題
"""
View Code

6.cookies的處理

"""cookies的處理"""
from http import cookiejar
from urllib import request


# 存放cookie信息
filename = "cookies.txt"
cookie = cookiejar.LWPCookieJar(filename)    # 建議使用此保存格式
# cookie = cookiejar.MozillaCookieJar(filename)
handler = request.HTTPCookieProcessor(cookie)
opener = request.build_opener(handler)
res = opener.open("http://www.baidu.com")
cookie.save(ignore_discard=True, ignore_expires=True)



# 讀取cookie信息
cookie = cookiejar.LWPCookieJar()       # 實例化LWP對象
# 指定要讀取的文件數據到cookie實例,忽略丟棄和忽略過時
cookie.load("cookies.txt", ignore_discard=True, ignore_expires=True)
# 將讀取的cookie信息封裝爲handler類型
handler = request.HTTPCookieProcessor(cookie)
# 建立一個opener對象
opener = request.build_opener(handler)
# 調用opener對象的open方法打開url
res = opener.open("http://www.baidu.com")
print(res.read().decode("utf-8"))
View Code

7.代理設置

"""urllib的代理設置"""
from urllib.error import URLError
from urllib.request import ProxyHandler, build_opener


# 設置代理請求的類型、ip和端口,_parse_proxy函數完成代理參數解析
proxy_handler = ProxyHandler({
    "http": "http://124.231.16.75:9000",
    "https": "https://113.105.201.193:3128"
})
# 封裝設置的代理數據,製造opener對象
opener = build_opener(proxy_handler)
try:
    # 調用opener的open方法代理訪問百度
    res = opener.open("https://www.baidu.com")
    print(res.read().decode("utf-8"))
except URLError as e:
    print(e.reason)
View Code

8.url的解析

"""urllib中的parse模塊"""
from urllib.parse import urlparse     # 等同from urllib.parse import urlsplit
from urllib.parse import urlunparse   # 等同from urllib.parse import urlunsplit
# urljoin拼接主url和所需url參數造成完整的url
from urllib.parse import urljoin      # base_url + new_url = complete_url
from urllib.parse import urlencode    # 構造GET請求參數,序列化完整url
# 反序列化url參數
from urllib.parse import parse_qs     # from urllib.parse import parse_qsl
from urllib.parse import quote        # 解決中文編碼問題,默認utf-8編碼
from urllib.parse import unquote      # 進行URL解碼


# 解析url的標準格式
res = urlparse("http://www.baidu.com/index.html;user?id=5#comment")
print(type(res), res)

"""
# 返回ParseResult結果的對象
<class 'urllib.parse.ParseResult'> 
ParseResult(scheme='http',              # 協議
            netloc='www.baidu.com',     # 域名
            path='/index.html',         # 路徑
            params='user',              # 參數
            query='id=5',               # 查詢條件,通常get查詢時使用
            fragment='comment'          # 錨點,定位頁面內部的下拉位置
            )
scheme://netloc/path;params?query#fragment    標準格式的url
"""

# urlunparse拼接url,須要6個參數完成拼接,限制比較大
data = ["https", "www.baidu.com", "index.html", "user", "id=5", "comment"]
print(urlunparse(data))


# urljoin拼接,經常使用此拼接方法,可自動補全完整的url鏈接
print(urljoin("https://www.baidu.com", "s?ie=utf-8&tn=baidu&wd=girl"))


# urlencode構造GET請求參數,經常使用方法。用字段存儲url所需參數,使用時再進行轉換
params = {
    "name": "Jim",
    "age": "26"
}
base_url = "https://www.baidu.com?"
url = base_url + urlencode(params)
print(url)


# parse_qs反序列化url參數{'name': ['Jim'], 'age': ['26']}, parse_qsl轉換爲元組組成的列表
query = "name=Jim&age=26"
print(parse_qs(query))


# quote方法能夠將內容轉換爲URL編碼的格式,默認utf-8編碼
keyword = "機械鍵盤"
url = "https://www.baidu.com/s?wd=" + quote(keyword)
print(url)


# unquote方法能夠將已編碼的URL解碼
url = "https://www.baidu.com/s?wd=%E6%9C%BA%E6%A2%B0%E9%94%AE%E7%9B%98"
print(unquote(url))
View Code

9.蜘蛛協議

"""
百度!!!
分析Robots協議,Robots協議也稱做爬蟲協議、機器人協議,它的全名叫做網絡爬蟲排除標準(Robots Exclusion
Protocol),用來告訴爬蟲和搜索引擎哪些頁面能夠抓取,哪些不能夠抓取它一般是一個叫做 robots.txt
的文本文件,通常放在網站的根目錄下
User-agent: *     *通配符,表示對全部爬蟲都有效,此處能夠設置爬蟲名稱
Disallow: /       /不容許抓取全部頁面,不容許抓取的目錄
Allow: /public/    能夠抓取的目錄,和Disallow一塊兒使用

urllib的robotparser模塊
set_url():用來設置robots.txt文件的連接若是在建立RobotFileParser對象時傳入了鏈
接,那麼就不須要再使用這個方法設置了
read ():讀取robots.txt文件並進行分析.注意,這個方法執行一個讀取和分析操做,若是不
調用這個方法接下來的判斷都會爲False,因此必定記得調用這個方法這個方法不會返
回任何內容,可是執行了讀取操做
parse():用來解析robots.txt文件,傳人的參數是robots.txt某些行的內容,它會按照robots.txt
的語法規則來分析這些內容
can_fetch():該方法傳人兩個參數第一個是User-agent,第二個是要抓取的URL返回的
內容是該搜索引擎是否能夠抓取這個URL,返回結果是True或False
mtime():返回的是上次抓取和分析robots.txt的時間,這對於長時間分析和抓取的搜索爬蟲
頗有必要的,你可能須要按期檢查來抓取最新的robots.txt
modified():它一樣對長時間分析和抓取的搜索爬蟲頗有幫助,將當前時間設置爲上次抓取
和分析robots.txt的時間
"""
from urllib.robotparser import RobotFileParser
from urllib.request import urlopen
from urllib import request


# 建立RobotFileParser對象
rp = RobotFileParser()
# 設置鏈接
rp.set_url("https://www.jianshu.com/robots.txt")
# 讀取分析
rp.read()
# 打印判斷的結果,直接無模擬訪問抓取都返回False
print(rp.can_fetch("*", "https://www.jianshu.com/p/b67554025d7d"))      # False
print(rp.can_fetch("*", "https://www.jianshu.com/search?q=python&page=1&type=collections"))     # False


# 須要添加headers信息,不添加直接403.模擬瀏覽器訪問抓取
url = "https://www.jianshu.com/robots.txt"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
}
req = request.Request(url=url, headers=headers)
res = urlopen(req).read().decode("utf-8").split("\n")
rp = RobotFileParser()
rp.parse(res)
print(rp.can_fetch("*", "https://www.jianshu.com/p/b67554025d7d"))      # True
print(rp.can_fetch("*", "https://www.jianshu.com/search?q=python&page=1&type=collections"))     # False
View Code
相關文章
相關標籤/搜索