"""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"))
"""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對象。 """
"""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'>
"""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("超時了")
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 用於管理認證,若是一個連接打開時須要認證,那麼能夠用它來解決認證問題 """
"""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"))
"""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)
"""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))
""" 百度!!! 分析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