python學習筆記5---(python網絡爬蟲-網絡請求)

urllib庫

urllib是最基本的網絡請求庫。可以模擬瀏覽器行爲,向指定瀏覽器發送請求,並保存返回的數據。

urlopen函數

在urllib庫中,所有和網絡請求相關的方法,都集到urllib.request模塊下。

from urllib import request
resp=request.urlopen('http://www.baidu.com')
print(resp.read())  #將響應的結果讀取出來

上面三行代碼把百度的首頁的全部代碼爬下來了。爬下來的代碼和通過右鍵查看源代碼的結果一樣。

parse庫

parse是最基本的網絡解析庫。

urlretrieve函數

from urllib import request
request.urlretrieve('url','下載下來建的名字') #比如圖片的地址

urlencode函數

(對中文或特殊字符進行編碼和parse_qs函數是parse模塊下的函數,是作用相反的函數)

from urllib import parse
params={'name':'cai','age':18,'greet':'hello world'}

from urllib import parse
url='http://www.baidu.com/s'
params={"wd':"劉德華"}
qs=parse.urlencode(params)
url=url+"?"+qs
resp = request.urlopen(url)
print(resq.read())

parse_qs函數

from urllib import parse
params = {'name':'cai','age':18,'greet':'hello world'}
qs=parse.urlencode(params)
print(qs)
res = parse.parse_qs(qs)

urlparse和urlsplit

想要對url中的各個組成部分進行分割

from urllib import parse
url='http://www.baidu.com/s?username=cai'
result=parse.urlpaser(url)
print(result)
print('scheme:',result.scheme)
print('netloc:',result.netloc)
print('path:',result.path)
print('query:',result.query)

ParseResult(scheme='http',netloc='www.baidu.com',path='/s',params='',query='username=abc')
scheme=http
netloc=www.baidu.com
path=/s
query=username=abc

urlparse和urlsplit基本一樣,urlparse多一個params屬性,;和?中間的值即params的值。比如url=‘http://www.baidu.com/s;hello?username=cai’ ,params=hello

用request爬取拉勾網職位信息

想要在請求的時候增加一些請求頭,必須使用request.Request類實現。

from urllib import request
url='https://www.lagou.com/jobs/list_python?labelWords=sug&fromSearch=true&suginput=pyth'

resq=request.urlopen(url)
print(resq.read())

上述代碼得到不完整信息(因爲反爬蟲機制),所以下面僞裝請求頭。

from urllib import request
url='https://www.lagou.com/jobs/list_python?labelWords=sug&fromSearch=true&suginput=pyth'
headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36'}
res=request.Request(url,headers=headers)
reqs=request.urlopen(res)
print(reqs.read())

但是查看源代碼發現關於職位的信息不是從該網站得到,所以查找網頁中文件下面的json文件(靠經驗),發現文件叫positionAjex.json,類型是json,點擊該鏈接後,查看右邊的響應,發現職位信息在該json中(可以爲了方便閱讀,將該文件拷貝在www.json.cn中查看),於是點擊該json鏈接右邊的消息頭,複製請求網址,即爲實際的請求網址:https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false,並且請求方式爲post,所以還加入data字段信息,data信息在右邊參數中的表單信息中

from urllib import request
url='https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false'
data={
'first':'true';
'pn'=1;
'kd'='python'
}
headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36'}
res=request.Request(url,headers=headers,data=data,method='POST')
# 請求爲post,這也是後面我們翻頁的時候發現拉勾網翻頁時 瀏覽器 url欄地址沒有變化的原因
reqs=request.urlopen(res)
print(reqs.read())

上述報錯:要將data通過urlencode編碼,然後encode

from urllib import request,parse
url='https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false'
data={
'first':'true',
'pn'=1,
'kd'='python'
}
headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36'}
res=request.Request(url,headers=headers,data=parse.urlencode(data).encode('uft-8'),method='POST')
reqs=request.urlopen(res)
print(reqs.read())

上述報錯:但報錯信息要通過read().decode(‘utf-8’)才能讀懂,提示訪問太頻繁,但實際還是反爬蟲機制導致,所以加入更多的請求頭信息。

from urllib import request,parse
url='https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false'
data={
'first':'true',
'pn':1,
'kd':'python'
}

headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36',
                'Referer'='https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput='
                }
res=request.Request(url,headers=headers,data=parse.urlencode(data).encode(uft-8),method='POST')
reqs=request.urlopen(res)
print(reqs.read())

ProxyHandler處理器(代理設置)

代理網站:1.西刺免費代理IP(全部免費):http://www.xicidaili.com
2.快代理:http://www.kuaidaili.com/
3.代理雲:http://www.dailiyun.com/

from urllib import request
# 沒有使用代理
# url='htttp://httpbin.org/ip'
# resq=request.urlopen(url) 其底層機制同下
# print(resq.read()) # 得到該電腦的外網的ip
# 使用代理
url='htttp://httpbin.org/ip'
#1.使用ProxyHandler,傳入代理構建handler
handler=request.ProxyHandler({"http":"218.66.161.88:31769"})
#2.使用已創建的handler構建一個opener
opener=request.build_opener(handler)
#3.使用opener發送請求
resq=opener.open(url)
print(resq.read())

cookie

cookie存儲的數據量有限,不同的瀏覽器有不同的存儲大小,一般超過4kb
使用cookie訪問人人網(必須登錄)中大鵬頁面的一種方法

from urllib import request
dapeng_url='XXX'
headers={
'User-Agent':"XXXX",
'Cookie':'XXXX'
}
resq=request.Request(url=dapeng_url,henders=headers)
req=request.urlopen(resq)
with open('dapeng.html','w',encoding='utf-8') as f:
    #write函數必須寫入一個str的數據類型
    #req.read()讀出來是bytes數據類型
    #bytes-》decode-》str
    #str-》encode-》bytes
    f.write(req.read().decode('utf-8'))

http.cookiejar

該模塊主要的類有CookieJar(cookie只能存儲在內存中)、FileCookieJar(cookie可以存儲在文件中,由CookieJar派生來)、MozillaCookieJar、LWPCookieJar,其中MozillaCookieJar和LWPCookieJar繼承自FileCookieJar,兩者很類似。

通過登錄方式動態獲取cookie,訪問大鵬人人網首頁

from urllib import request
from urllib import parse
from http.cookiejar import CookieJar

# 1、登錄
# 1.1 創建一個cookiejar對象
cookiejar = CookieJar()
# 1.2 使用cookiejar創建一個HTTPCookieProcess對象
handler=request.HTTPCookieProcessor(cookiejar)
# 1.3 使用上一步創建的handler創建一個opener
opener = request.build_opener(handler)
# 1.4 使用opener發送登錄的請求(人人網的郵箱和密碼)
headers = {
'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36"  
#在火狐瀏覽器中由於字符太長,省略中間信息,導致複製了(...),最終報錯:UnicodeEncodeError: 'latin-1' codec can't encode character '\u2026' in position 30: ordinal not in range(256),解決辦法:在chrome中的請求頭中複製該信息
}
data={
'email':"15116475571",
'password':"caiyijunxpy"
}
login_url = "http://www.renren.com/PLogin.do"  # 地址錯誤報:HTTPError: /sysHome
req=request.Request(login_url,data=parse.urlencode(data).encode('utf-8'),headers=headers)
opener.open(req)
 # 2 訪問個人主頁
 dapeng_url = "http://www.renren.com/880151247/profile"
 req = request.Request(dapeng_url,headers=headers)
 resp = opener.open(req)
 with open('dapeng.html','w',encoding='utf-8') as f:
     f.write(resp.read().decode('utf-8'))
     

將上面代碼寫成函數顯示

from urllib import request
from urllib import parse
from http.cookiejar import CookieJar

   headers = {
    'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36"  
    #在火狐瀏覽器中由於字符太長,省略中間信息,導致複製了(...),最終報錯:UnicodeEncodeError: 'latin-1' codec can't encode character '\u2026' in position 30: ordinal not in range(256),解決辦法:在chrome中的請求頭中複製該信息
}

def get_opener():
    # 1、登錄
    # 1.1 創建一個cookiejar對象
    cookiejar = CookieJar()
    # 1.2 使用cookiejar創建一個HTTPCookieProcessor對象
    handler=request.HTTPCookieProcessor(cookiejar)
    # 1.3 使用上一步創建的handler創建一個opener
    opener = request.build_opener(handler)
    return opener

def login_renren(opener):
    # 1.4 使用opener發送登錄的請求(人人網的郵箱和密碼)
 
    data={
'email':"15116475571",
'password':"caiyijunxpy"
}
    login_url = "http://www.renren.com/PLogin.do"  # 地址錯誤報:HTTPError: /sysHome
    req=request.Request(login_url,data=parse.urlencode(data).encode('utf-8'),headers=headers)
    opener.open(req)

def visit_profile(opener):
     # 2 訪問個人主頁
     dapeng_url = "http://www.renren.com/880151247/profile"
     req = request.Request(dapeng_url,headers=headers)
     resp = opener.open(req)
     # 自動新建的dapeng.html,打開顯示大鵬的主頁 
     with open('dapeng.html','w',encoding='utf-8') as f:
         f.write(resp.read().decode('utf-8'))

if __name__ == '__main__':
    opener =get_opener()
    login_renren(opener)
    visit_profile(opener)

保存cookie

from urllib import request
from http.cookiejar import MozillaCookieJar

cookiejar = MozillaCookieJar('cookie.txt')
handler=request.HTTPCookieProcessor(cookiejar)
opener=request.build_opener(handler)

req=opener.open('http://httpbin.org/cookies')
cookiejar.save(ignore_discard=True) #程序運行完後cookie信息會過期

加載cookie

from urllib import request
from http.cookiejar import MozillaCookieJar

cookiejar = MozillaCookieJar('cookie.txt')
cookiejar.load(ignore_discard=True) 
handler=request.HTTPCookieProcessor(cookiejar)
opener=request.build_opener(handler)

req=opener.open('http://httpbin.org/cookies')
for cookie in cookiejar:
    print(cookie)

requests庫

response.text和response.content的區別
1.response.content:這是直接從網絡上抓取的數據,沒有經過任何解碼,是個bytes類型。在硬盤和網絡上傳輸的字符串都是bytes類型。
2.response.text:這個是str數據類型,是requests庫將response.content進行解碼的字符串。解碼需要指定一個編碼方式,requests會根據自己的猜測判斷編碼方式,但有時可能會出錯,導致解碼產生亂碼,此時應該使用response.content.decode(‘utf-8’)進行手動解碼

import requests

data={
'first':"true",
'pn':'1',
'kd':'python'
}
headers={
'Referer':'https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput='
'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36"  
}

response=requests.post("https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false",data=data,headers=headers)
print(response.json())

反爬蟲機制提示:{'status': False, 'msg': '您操作太頻繁,請稍後再訪問', 'clientIp': '218.104.146.110', 'state': 2402}

requests處理cookie信息

之前使用urllib庫可以使用opener發送多個請求,多個請求之間可以共享cookie。如果使用requests,共享cookie,可以使用session對象。

import requests

url = "http://www.renren.com/PLogin.do"  
data={
'email':"15116475571",
'password':"caiyijunxpy"
}
headers={'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36"  }

session =requests.Session()
session =post(url,data=data,headers=headers)
res=Session.get("http://www.renren.com/880151247/profile")
with open('dapeng.html','w',encoding="utf-8") as f:
    f.write(res.text)

處理不信任的SSL證書

res=requests.get('http://12306.cn/mormhweb/',verify=False)
print(res.content.decode('utf-8')
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章