爬蟲_python3_urllib

urlib庫爲python3的HTTP內置請求庫html

urilib的四個模塊:python

  • urllib.request:用於獲取網頁的響應內容瀏覽器

  • urllib.error:異常處理模塊,用於處理異常的模塊cookie

  • urllib.parse:用於解析urlide

  • urllib.robotparse:用於解析robots.txt,主要用於看哪些網站不能進行爬取,不過少用post

1.  urllib.request學習

urllib.request.urlopen(url,data=None,[timeout,]*,cafile=None,cadefault=False,context=None)網站

  • url:爲請求網址ui

  • data:請求時須要發送的參數url

  • timeout:超時設置,在該時間範圍內返回請求內容就不會報錯

from urllib import request
 # 請求獲取網頁返回內容
response = request.urlopen('https://movie.douban.com/')
# 獲取網頁返回內容
print(response.read().decode('utf-8'))
# 獲取狀態碼
print(response.status)
# 獲取請求頭
print(response.getheaders())

  

# 對請求頭進行遍歷
for k, v in response.getheaders():
    print(k, '=', v) 

 

能夠使用上面的代碼對一些網站進行請求了,可是當須要一些反爬網站時,這就不行了,這時咱們須要適當地增長請求頭進行請求,這時就須要使用複雜一點的代碼了,這時咱們須要用到Request對象

# 請求頭
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0'}
requests = request.Request('https://movie.douban.com/', headers=headers) # 加入本身的請求頭更加接近瀏覽器
# 進行請求,把Request對象傳入urlopen參數中
response = request.urlopen(requests)
print(response.read().decode('utf-8'))

  

這個我添加了請求頭進行請求,使我發送的請求更加接近瀏覽器的行爲。能夠對應一些反爬網站了。若是網站須要進行登錄,這時須要用到post方法,用上面的也是能夠的。

from urllib import request, parse
# 使用post方法來進行模擬登錄豆瓣
data = {'source': 'None',
        'redir': 'https://www.douban.com/',
        'form_email': '*****@qq.com',
        'form_password': '***',
        'remember': 'on',
         'login': '登陸'}
# 將data的字典類型轉換爲get請求方式
data=bytes(parse.urlencode(data),encoding='utf-8')
requests = request.Request('https://accounts.douban.com/login', headers=headers, data=data, method='POST')
response = request.urlopen(requests)
print(response.read().decode('utf-8'))

  

這裏我用到了data的參數把登錄須要的參數傳進去,還加了個請求方法Method

 

parse.urlencode()後面有講

 

這裏還有另一種添加請求頭的方法

Request.add_header(): 參數有兩個,分別爲請求頭對應的鍵和值,這種方法一次只能添加一個請求頭,添加多個須要用到循環或者直接用前面的方法添加多個請求頭

 

在登錄了網站以後,咱們須要用到cookie來保存登錄信息,這時就須要獲取cookie了。urllib獲取cookie比較麻煩

 

from http import cookiejar
# 獲取cookie
cookie = cookiejar.CookieJar()
# 獲取助手把cookie傳進去
handler = request.HTTPCookieProcessor(cookie)
# 獲取opener進行請求網站
opener = request.build_opener(handler)
# 請求網頁
response = opener.open('https://movie.douban.com/')
# 打印cookie
for c in cookie:
    print(c.name, '=', c.value)

  單純地打印沒什麼用,咱們須要把他存入文件來保存,下次使用時再次加載cookie來登錄

保存cookie爲文件:

from http import cookiejar
#將cookie保存在文件中
filename='cookie.txt'
cookie=cookiejar.MozillaCookieJar(filename)#表示使用Mozilla的cookie方式存儲和讀取
handler=request.HTTPCookieProcessor(cookie)
opener=request.build_opener(handler)
opener.open('https://movie.douban.com/')
#保存文件
cookie.save(ignore_discard=True,ignore_expires=True)

另外一種保存方法:

from http import cookiejar
cookie=cookiejar.LWPCookieJar(filename)#表示Set-Cookie3文件格式存儲和讀取
handler=request.HTTPCookieProcessor(cookie)
opener=request.build_opener(handler)
opener.open('https://movie.douban.com/')
#保存文件
cookie.save(ignore_discard=True,ignore_expires=True)

這兩種保存格式都是不同的,須要保存的內容同樣。

保存能夠了,這時就須要用到加載了,固然也能夠。代碼以下:

from http import cookiejar
# 從cookie文件加載到網頁上實現記住登錄
cookie = cookiejar.LWPCookieJar()
# 加載文件
cookie.load(filename, ignore_discard=True, ignore_expires=True)
handler = request.HTTPCookieProcessor(cookie)
opener = request.build_opener(handler)
opener.open('https://movie.douban.com/')

這樣就能夠實現不用密碼進行登錄了。

 

cookie小總結:在操做cookie時,都是分五步,以下:

  1. 進行導包,相當重要的一步,不導包直接出錯。

  2. 獲取cookie處理對象,使用cookiejar包

  3. 建立cookie處理器,使用request.HTTPCookieJarProcessor()

  4. 利用cookie處理器構建opener,使用request.build_opener()

  5. 進行請求網站,用opener.open(),這個不能用request.urlopen()

 

若是有時你在同一ip連續屢次發送請求,會有被封ip的可能,這時咱們還須要用到代理ip進行爬取,代碼以下:

proxy = request.ProxyHandler({'https': 'https://106.60.34.111:80'})
opener = request.build_opener(proxy)
opener.open('https://movie.douban.com/',timeout=1)

  

2. urllib.error

將上面的使用代理ip的請求進行異常處理,以下:

from urllib import request, error
try:
    proxy = request.ProxyHandler({
    'https': 'https://106.60.34.111:80'
    })
    opener = request.build_opener(proxy)
    opener.open('https://movie.douban.com/', timeout=1)
except error.HTTPError as e:
    print(e.reason(), e.code(), e.headers())
except error.URLError as e:
    print(e.reason)

由於有時這個ip或許也被封了,有可能會拋出異常,因此咱們爲了讓程序運行下去進而進行捕捉程序

  • error.URLError: 這個是url的一些問題,這個異常只有一個reason屬性

  • error.HTTPError:這個是error.URLError的子類,因此在與上面的混合使用時須要將這個異常放到前面,這個異常是一些請求錯誤,有三個方法,.reason(), .code(), .headers(),因此在捕捉異常時一般先使用這個

3. urllib.parse

解析url:urllib.parse.urlparse(url, scheme='', allow_fragments=True)

 

簡單的使用:

from urllib import request, parse
# 解析url
print(parse.urlparse('https://movie.douban.com/'))
print(parse.urlparse('https://movie.douban.com/', scheme='http'))
print(parse.urlparse('movie.douban.com/', scheme='http'))
#結果
#ParseResult(scheme='https', netloc='movie.douban.com', path='/', params='', query='', fragment='')
#ParseResult(scheme='https', netloc='movie.douban.com', path='/', params='', query='', fragment='')
#ParseResult(scheme='http', netloc='', path='movie.douban.com/', params='', query='', fragment='')

能夠看出加了scheme參數和沒加的返回結果是有區別的。而當scheme協議加了,而前面的url也包含協議,通常會忽略後面的scheme參數

 

既然有解析url,那固然也有反解析url,就是把元素串連成一個url

from urllib import parse
# 將列表元素拼接成url
url = ['http', 'www', 'baidu', 'com', 'dfdf', 'eddffa'] # 這裏至少須要6個元素(我亂寫的,請忽視)
print(parse.urlunparse(url))
# 下面是結果
# http://www/baidu;com?dfdf#eddffa

 urlparse()接收一個列表的參數,並且列表的長度是有要求的,是必須六個參數以上,要不會拋出異常 

1Traceback (most recent call last):
2 File "E:/anaconda/python_project/python3_spider/urllib_test.py", line 107, in <module>
3 print(parse.urlunparse(url))
4 File "E:\anaconda\lib\urllib\parse.py", line 454, in urlunparse
5 _coerce_args(*components))
6ValueError: not enough values to unpack (expected 7, got 6)

  urllib.parse.urljoin():這個是將第二個參數的url缺乏的部分用第一個參數的url補齊

 

# 鏈接兩個參數的url, 將第二個參數中缺的部分用第一個參數的補齊
print(parse.urljoin('https://movie.douban.com/', 'index'))
print(parse.urljoin('https://movie.douban.com/','https://accounts.douban.com/login'))
# 下面是結果
#https://movie.douban.com/index
#https://accounts.douban.com/login

  urllib.parse.urlencode():這個方法是將字典類型的參數轉爲請求爲get方式的字符串

data = {'name': 'sergiojuue', 'sex': 'boy'}
data = parse.urlencode(data)
print('https://accounts.douban.com/login'+data)
# 下面是結果
#https://accounts.douban.com/loginname=sergiojuue&sex=boy

  4. 結語

還有個urllib.robotparse庫少用,就不說了,留給之後須要再去查文檔吧。

 

上面的只是我在學習過程當中的總結,若是有什麼錯誤的話,歡迎在留言區指出,還有就是須要查看更多用法的請查看文檔https://docs.python.org/3/library/urllib.html

學習過程當中看的大可能是崔慶才大佬的視頻:https://edu.hellobi.com/course/157

 

 

感謝!:https://mp.weixin.qq.com/s?__biz=MzI5NDY1MjQzNA==&mid=2247485940&idx=1&sn=3fabf8c9bb52395675cd71db65cc9109&chksm=ec5ed689db295f9f01f9eb56b95a25fe8221e516969a7ec30794e41fd51fbe582add5002decd&mpshare=1&scene=1&srcid=0329HJXcKhalaWwriIvQ95r7&pass_ticket=jt1ntJmxsOysHtvsCD6R975Ofkvtsc8maZ4Fep%2FuRAov9uL%2Fo%2BMRdbYALU2UxCY0#rd

相關文章
相關標籤/搜索