Python爬蟲教程1.2 — urllib基礎(chǔ)用法教程

綜述

本系列文檔用于對Python爬蟲技術(shù)進行簡單的講解記錄牵署,鞏固自己技術(shù)知識的同時,萬一一不小心又正好對你有用那就更好了循帐。
Python 版本是3.7.4

上篇文章介紹了urllib的基礎(chǔ)使用方法本篇文章就來介紹一下urllib稍微高級一點的用法轧钓。

網(wǎng)上有很多的網(wǎng)站想要請求需要設(shè)置一些請求頭辙诞,如果要在請求的時候增加一些請求頭,那么就必須使用request.Request類來實現(xiàn)了量淌,比如要增加一個 User-Agent 骗村,增加一個 Referer 頭信息等。

通常防止爬蟲被反主要有以下幾個策略:

  1. 動態(tài)設(shè)置請求頭headers(User-Agent)(隨機切換User-Agent呀枢,模擬不同用戶的瀏覽器信息)
  2. 使用IP地址池:VPN和代理IP胚股,現(xiàn)在大部分網(wǎng)站都是根據(jù)IP來ban的
  3. Cookies
  4. 設(shè)置延遲下載(防止訪問過于頻繁,設(shè)置為2秒或更高)要明白爬蟲重要的是拿到數(shù)據(jù)(這個用到time庫的time.sleep()方法裙秋,在這里不在說明)

設(shè)置請求頭(urllib.request.Request)

urllib.request.Request是urllib的一個抽象類琅拌,用于構(gòu)造一個http請求對象實例。
request類Request方法常用的內(nèi)置方法:

  • Request.add_data(data)設(shè)置data參數(shù)摘刑,如果一開始創(chuàng)建的時候沒有給data參數(shù)进宝,那么可以使用該方法追加data參數(shù);
  • Request.get_method() 返回HTTP請求方法枷恕,一般返回GET或是POST党晋;
  • Request.has_data() 查看是否設(shè)置了data參數(shù);
  • Request.get_data() 獲取data參數(shù)的數(shù)據(jù);
  • Request.add_header(key, val) 添加頭部信息未玻,key為頭域名灾而,val為域值;
  • Request.get_full_url() 獲取請求的完整url扳剿;
  • Request.get_host() 返回請求url的host(主域名)旁趟;
  • Request.set_proxy(host, type) 設(shè)置代理,第一個參數(shù)是代理ip和端口庇绽,第二個參數(shù)是代理類型(http/https)锡搜。
  1. 代碼示例
    # 導入urllib庫
    import urllib.parse
    import urllib.request
    
    # 聲明定義請求頭
    headers = {
        # 在這個頭字典里面可以將你所有需要傳遞的頭添加進來
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
    }
    
    # 向指定的url發(fā)送請求,并返回
    post_url = 'https://fanyi.baidu.com/sug'
    # 傳入?yún)?shù)
    form_data = {
        'kw': 'honey'
    }
    # 格式化參數(shù)
    form_data = urllib.parse.urlencode(form_data).encode()
    # 創(chuàng)建Request類
    req = urllib.request.Request(url=post_url, headers=headers, data=form_data)
    
    # 進行請求瞧掺,打印結(jié)果
    ret = urllib.request.urlopen(req)
    print(ret.read())
  1. 爬蟲示例

爬取拉勾網(wǎng)Python職位招聘信息(由于拉勾網(wǎng)進行了防爬耕餐,訪問其接口需要傳遞Cookie,本人直接在瀏覽器復制出來寫入到請求頭中的)夸盟。

    # 引入urllib庫
    import urllib.parse
    import urllib.request
    
    # 聲明定義請求頭
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36',
        'Referer': 'https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput=',
        'Host': 'www.lagou.com',
        'Origin': 'https://www.lagou.com',
        'X-Requested-With': 'XMLHttpRequest',
        'Cookie': '_ga=GA1.2.1158944803.1554684888; user_trace_token=20190408085447-e8216b55-5998-11e9-8cbc-5254005c3644; LGUID=20190408085447-e8216df3-5998-11e9-8cbc-5254005c3644; JSESSIONID=ABAAABAAAFCAAEG89414A0A463BB593A6FCB8B25161B297; WEBTJ-ID=20190803154150-16c566d76a7a71-0d0261dbc1a413-a7f1a3e-2073600-16c566d76a8664; _gid=GA1.2.646413362.1564818110; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1564818110; LGSID=20190803154149-2746a012-b5c2-11e9-8700-525400f775ce; PRE_UTM=; PRE_HOST=www.baidu.com; PRE_SITE=https%3A%2F%2Fwww.baidu.com%2F; PRE_LAND=https%3A%2F%2Fwww.lagou.com%2F; index_location_city=%E5%85%A8%E5%9B%BD; X_HTTP_TOKEN=7b450c20fc1c8ebb1028184651d95c44e86182119a; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1564818202; _gat=1; LGRID=20190803154322-5e321a85-b5c2-11e9-8700-525400f775ce; TG-TRACK-CODE=index_search; SEARCH_ID=f2eeeba9273a435281d59597e5b8b7ba',
    }
    # 拉鉤接口地址
    url = 'https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false'
    # 接口參數(shù)
    data = {
        'first': 'true',
        'pn': '1',
        'kd': 'python'
    }
    from_data = urllib.parse.urlencode(data).encode()
    # 聲明定義Request類
    req = urllib.request.Request(url=url, headers=headers, data=from_data)
    # 請求接口蛾方,打印結(jié)果
    res = urllib.request.urlopen(req)
    print(res.read().decode())

使用代理(urllib.request.ProxyHandle)

很多網(wǎng)站會員檢測某一時間內(nèi)某個IP的訪問次數(shù)(通過流量統(tǒng)計像捶,系統(tǒng)日志等)上陕,如果訪問次數(shù)多的不像正常人,它就會禁止這個IP訪問拓春。所以我們可以設(shè)置一些代理服務(wù)器释簿,每隔一段時間換一個代理,就算IP被禁止硼莽,依然可以換個IP繼續(xù)爬取庶溶。

  1. 基本原理
    代理實際上指的就是代理服務(wù)器,它的功能是代理網(wǎng)絡(luò)用戶去取得網(wǎng)絡(luò)信息懂鸵。形象地說偏螺,它是網(wǎng)絡(luò)信息的中轉(zhuǎn)站。在我們正常請求一個網(wǎng)站時匆光,其實是發(fā)送了請求給Web服務(wù)器套像,Web服務(wù)器把響應(yīng)傳回給我們。如果設(shè)置了代理服務(wù)器终息,實際上就是在本機和服務(wù)器之間搭建了一個橋夺巩,此時本機不是直接向Web服務(wù)器發(fā)起請求,而是向代理服務(wù)器發(fā)出請求周崭,請求會發(fā)送給代理服務(wù)器柳譬,然后由代理服務(wù)器再發(fā)送給Web服務(wù)器,接著由代理服務(wù)器再把Web服務(wù)器返回的響應(yīng)轉(zhuǎn)發(fā)給本機续镇。這樣我們同樣可以正常訪問網(wǎng)頁美澳,但這個過程中Web服務(wù)器識別出的真實IP就不再是我們本機的IP了,就成功實現(xiàn)了IP偽裝,這就是代理的基本原理制跟。

  2. 作用

    • 突破自身IP訪問限制柴墩,訪問一些平時不能訪問的站點;
    • 提高訪問速度凫岖;
    • 隱藏真實IP江咳。
  3. 常用的代理

  4. 用法示例

        # 引入所需要的庫
        import random
        import urllib.request
        
        # 聲明定義代理服務(wù)器列表
        proxy_list = [
            {"http": "220.184.144.80:8060"},
            {"http": "180.175.170.210:8060"},
            {"http": "116.226.28.17:8060"},
            {"http": "123.123.137.72:8060"},
            {"http": "116.226.31.161:8060"}
        ]
        # 隨機選擇一個代理
        proxy = random.choice(proxy_list)
        
        # 使用選擇的代理構(gòu)建代理處理器對象
        http_proxy_handler = urllib.request.ProxyHandler(proxy)
        # 通過 urllib.request.build_opener(),創(chuàng)建自定義opener對象
        opener = urllib.request.build_opener(http_proxy_handler)
        # 創(chuàng)建Request對象
        url = 'http://www.baidu.com/s?ie=UTF-8&wd=ip'
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
        }
        req = urllib.request.Request(url=url, headers=headers)
        # 使用opener.open()方法發(fā)送請求才使用自定義的代理,而urlopen()則不使用自定義代理
        # 這么寫哥放,就是將opener應(yīng)用到全局歼指,之后所有的,不管是opener.open()還是urlopen()發(fā)送請求甥雕,都將使用自定義代理
        res = opener.open(req)
        print(res.read().decode())
    

Cookie(urllib.request.HTTPCookieProcessor)

  1. cookie是什么

    在網(wǎng)站中踩身,http請求時無狀態(tài)的,也就是說即使第一次和服務(wù)器鏈接后并且登陸成功后社露,第二次請求服務(wù)器依然不能知道當前請求是那個用戶挟阻,cookie的出現(xiàn)就是為了解決這個問題,第一次登陸后服務(wù)器返回一些數(shù)據(jù)(cookie)給瀏覽器峭弟,然后瀏覽器保存在本地附鸽,當該用戶第二次請求的時候,就會自動把上次請求的cookie數(shù)據(jù)自動的攜帶給服務(wù)器瞒瘸,服務(wù)器通過瀏覽器攜帶的cookie數(shù)據(jù)就能判斷當前的用戶是那個了坷备。cookie存儲的數(shù)據(jù)有限,不同的瀏覽器又不同的存儲大小情臭,但一般不超過4kb省撑,因此使用cookie只能存儲一些小量的數(shù)據(jù)。(解釋比較簡單俯在,詳細的cookie說明可以看百科介紹)

  2. cookie格式

    Set-Cookie: NAME=VALUE; Expires=DATE; Domain=DOMAIN_NAME; Path=PATH; SECURE
    
    • NAME=VALUE:這是每一個Cookie均必須有的部分竟秫。NAME是該Cookie的名稱,VALUE是該Cookie的值跷乐。在字符串“NAME=VALUE”中肥败,不含分號、逗號和空格等字符劈猿;
    • Expires=DATE:Expires變量是一個只寫變量拙吉,它確定了Cookie有效終止日期。該變量可省揪荣,如果缺省時筷黔,則Cookie的屬性值不會保存在用戶的硬盤中,而僅僅保存在內(nèi)存當中仗颈,Cookie文件將隨著瀏覽器的關(guān)閉而自動消失佛舱;
    • Domain=DOMAIN-NAME:Domain該變量是一個只寫變量椎例,它確定了哪些Internet域中的Web服務(wù)器可讀取瀏覽器所存取的Cookie,即只有來自這個域的頁面才可以使用Cookie中的信息请祖。這項設(shè)置是可選的订歪,如果缺省時,設(shè)置Cookie的屬性值為該Web服務(wù)器的域名肆捕;
    • Path=PATH:Path屬性定義了Web服務(wù)器上哪些路徑下的頁面可獲取服務(wù)器設(shè)置的Cookie刷晋;
    • SECURE:在Cookie中標記該變量,表明只有當瀏覽器的通信協(xié)議為加密認證協(xié)議時慎陵,瀏覽器才向服務(wù)器提交相應(yīng)的Cookie眼虱。當前這種協(xié)議只有一種,即為HTTPS席纽。
  3. http.cookiejar

    cookielib一般用于客戶端處理HTTP cookie信息捏悬,通過它可以從服務(wù)器端獲取cookie信息,反過來又可以通過它將獲取到的cookie發(fā)送給服務(wù)器润梯。cookielib提供了不同的類來自動處理HTTP的cookie信息过牙,使用比較多的類包括了CookieJar、MozillaCookieJar以及Cookie纺铭。

代碼使用示例(使用http.cookiejar和urllib.request.HTTPCookieProcessor登陸人人網(wǎng)):


    # 引入所需要的庫
    import http.cookiejar
    import urllib.parse
    import urllib.request
    
    # 真實的模擬瀏覽器寇钉,當發(fā)送完post請求的時候,將cookie保存到代碼中
    # 創(chuàng)建一個cookiejar對象
    cj = http.cookiejar.CookieJar()
    # 通過cookiejar創(chuàng)建一個handler
    handler = urllib.request.HTTPCookieProcessor(cj)
    # 根據(jù)handler創(chuàng)建一個opener
    opener = urllib.request.build_opener(handler)
    # 人人網(wǎng)登陸地址
    post_uel = 'http://www.renren.com/ajaxLogin/login?1=1&uniqueTimestamp=2019621044248'
    form_data = {
        'email': '188****7357',  # 這是人人網(wǎng)賬號
        'icode': '',
        'origURL': 'http://www.renren.com/home',
        'domain': 'renren.com',
        'key_id': '1',
        'captcha_type': 'web_login',
        'password': '01cb55635986f56265d3b55aaddaa79337d094cb56d6cf7724343a93ad586fe7',
        'rkey': 'd5ff51375d8eb17a011cad5622d835fd',
        'f': 'http%3A%2F%2Fwww.renren.com%2F971686685%2Fprofile'
    }
    # 聲明定義header
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
    }
    # 創(chuàng)建Request對象,格式化參數(shù)
    req = urllib.request.Request(url=post_uel, headers=headers)
    form_data = urllib.parse.urlencode(form_data).encode()
    # 構(gòu)造訪問
    res = opener.open(req, data=form_data)
    print(res.read().decode())
    print('*' * 50)
    
    # 人人網(wǎng)個人中心地址
    get_url = 'http://www.renren.com/971686685/profile'
    # 創(chuàng)建Request對象
    req1 = urllib.request.Request(url=get_url, headers=headers)
    # 構(gòu)造訪問(自帶cookie),打印結(jié)果
    res1 = opener.open(req1)
    print(res1.read().decode())

  1. cookie信息的保存
    # 引入所需要的庫
    import urllib.request
    from http.cookiejar import MozillaCookieJar
    
    # 聲明cookiejar
    cj = MozillaCookieJar('cookie.txt')
    # 創(chuàng)建handler\opener
    handler = urllib.request.HTTPCookieProcessor(cj)
    opener = urllib.request.build_opener(handler)
    # 聲明定義url,進行訪問
    url = 'http://httpbin.org/cookies/set?wei=weizhihua'
    res = opener.open(url)
    # 保存cookie, ignore_discard 設(shè)置為True,將過期的cookie也進行保存
    # 如果在聲明cookiejar時沒有寫入文件保存地址,則在save()函數(shù)中需寫入文件地址參數(shù)
    cj.save(ignore_discard=True)
  1. cookie信息的加載
    import urllib.request
    from http.cookiejar import MozillaCookieJar
    
    # 聲明cookiejar
    cj = MozillaCookieJar('cookie.txt')
    # ignore_discard 設(shè)置為True,將過期的cookie也加載出來
    cj.load(ignore_discard=True)
    # 打印內(nèi)容
    for cookie in cj:
        print(cookie)

其他博文鏈接

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末彤蔽,一起剝皮案震驚了整個濱河市摧莽,隨后出現(xiàn)的幾起案子庙洼,更是在濱河造成了極大的恐慌顿痪,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件油够,死亡現(xiàn)場離奇詭異蚁袭,居然都是意外死亡,警方通過查閱死者的電腦和手機石咬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門揩悄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鬼悠,你說我怎么就攤上這事删性。” “怎么了焕窝?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵蹬挺,是天一觀的道長。 經(jīng)常有香客問我它掂,道長巴帮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮榕茧,結(jié)果婚禮上垃沦,老公的妹妹穿的比我還像新娘。我一直安慰自己用押,他們只是感情好肢簿,可當我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蜻拨,像睡著了一般译仗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上官觅,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天纵菌,我揣著相機與錄音,去河邊找鬼休涤。 笑死咱圆,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的功氨。 我是一名探鬼主播序苏,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼捷凄!你這毒婦竟也來了忱详?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤跺涤,失蹤者是張志新(化名)和其女友劉穎匈睁,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體桶错,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡航唆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了院刁。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片糯钙。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖退腥,靈堂內(nèi)的尸體忽然破棺而出任岸,到底是詐尸還是另有隱情,我是刑警寧澤狡刘,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布享潜,位于F島的核電站,受9級特大地震影響颓帝,放射性物質(zhì)發(fā)生泄漏米碰。R本人自食惡果不足惜窝革,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吕座。 院中可真熱鬧虐译,春花似錦、人聲如沸吴趴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锣枝。三九已至厢拭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間撇叁,已是汗流浹背供鸠。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留陨闹,地道東北人楞捂。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像趋厉,于是被迫代替她去往敵國和親寨闹。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容