Python3網絡爬蟲開發實戰】 3.2.1-基本用法

      網友投稿 3427 2022-05-30

      1. 準備工作

      在開始之前,請確保已經正確安裝好了requests庫。如果沒有安裝,可以參考1.2.1節安裝。

      2. 實例引入

      urllib庫中的urlopen()方法實際上是以GET方式請求網頁,而requests中相應的方法就是get()方法,是不是感覺表達更明確一些?下面通過實例來看一下:

      import?requests r?=?requests.get('https://www.baidu.com/') print(type(r)) print(r.status_code) print(type(r.text)) print(r.text) print(r.cookies)

      運行結果如下:

      200 ???? ???? ,?,?,?]>

      這里我們調用get()方法實現與urlopen()相同的操作,得到一個Response對象,然后分別輸出了Response的類型、狀態碼、響應體的類型、內容以及Cookies。

      通過運行結果可以發現,它的返回類型是requests.models.Response,響應體的類型是字符串str,Cookies的類型是RequestsCookieJar。

      使用get()方法成功實現一個GET請求,這倒不算什么,更方便之處在于其他的請求類型依然可以用一句話來完成,示例如下:

      r?=?requests.post('http://httpbin.org/post') r?=?requests.put('http://httpbin.org/put') r?=?requests.delete('http://httpbin.org/delete') r?=?requests.head('http://httpbin.org/get') r?=?requests.options('http://httpbin.org/get')

      這里分別用post()、put()、delete()等方法實現了POST、PUT、DELETE等請求。是不是比urllib簡單太多了?

      其實這只是冰山一角,更多的還在后面。

      3. GET請求

      HTTP中最常見的請求之一就是GET請求,下面首先來詳細了解一下利用requests構建GET請求的方法。

      基本實例

      首先,構建一個最簡單的GET請求,請求的鏈接為http://httpbin.org/get,該網站會判斷如果客戶端發起的是GET請求的話,它返回相應的請求信息:

      import?requests r?=?requests.get('http://httpbin.org/get') print(r.text)

      運行結果如下:

      { ??"args":?{},? ??"headers":?{ ????"Accept":?"*/*",? ????"Accept-Encoding":?"gzip,?deflate",? ????"Host":?"httpbin.org",? ????"User-Agent":?"python-requests/2.10.0" ??},? ??"origin":?"122.4.215.33",? ??"url":?"http://httpbin.org/get" }

      可以發現,我們成功發起了GET請求,返回結果中包含請求頭、URL、IP等信息。

      那么,對于GET請求,如果要附加額外的信息,一般怎樣添加呢?比如現在想添加兩個參數,其中name是germey,age是22。要構造這個請求鏈接,是不是要直接寫成:

      r?=?requests.get('http://httpbin.org/get?name=germey&age=22')

      這樣也可以,但是是不是有點不人性化呢?一般情況下,這種信息數據會用字典來存儲。那么,怎樣來構造這個鏈接呢?

      這同樣很簡單,利用params這個參數就好了,示例如下:

      import?requests data?=?{ ????'name':?'germey', ????'age':?22 } r?=?requests.get("http://httpbin.org/get",?params=data) print(r.text)

      運行結果如下:

      { ??"args":?{ ????"age":?"22",? ????"name":?"germey" ??},? ??"headers":?{ ????"Accept":?"*/*",? ????"Accept-Encoding":?"gzip,?deflate",? ????"Host":?"httpbin.org",? ????"User-Agent":?"python-requests/2.10.0" ??},? ??"origin":?"122.4.215.33",? ??"url":?"http://httpbin.org/get?age=22&name=germey" }

      通過運行結果可以判斷,請求的鏈接自動被構造成了:http://httpbin.org/get?age=22&name=germey。

      另外,網頁的返回類型實際上是str類型,但是它很特殊,是JSON格式的。所以,如果想直接解析返回結果,得到一個字典格式的話,可以直接調用json()方法。示例如下:

      import?requests r?=?requests.get("http://httpbin.org/get") print(type(r.text)) print(r.json()) print(type(r.json()))

      運行結果如下:

      {'headers':?{'Accept-Encoding':?'gzip,?deflate',?'Accept':?'*/*',?'Host':?'httpbin.org',?'User-Agent':?'python-requests/2.10.0'},?'url':?'http://httpbin.org/get',?'args':?{},?'origin':?'182.33.248.131'}

      可以發現,調用json()方法,就可以將返回結果是JSON格式的字符串轉化為字典。

      但需要注意的書,如果返回結果不是JSON格式,便會出現解析錯誤,拋出json.decoder.JSONDecodeError異常。

      抓取網頁

      上面的請求鏈接返回的是JSON形式的字符串,那么如果請求普通的網頁,則肯定能獲得相應的內容了。下面以“知乎”→“發現”頁面為例來看一下:

      import?requests import?re headers?=?{ ????'User-Agent':?'Mozilla/5.0?(Macintosh;?Intel?Mac?OS?X?10_11_4)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/52.0.2743.116?Safari/537.36' } r?=?requests.get("https://www.zhihu.com/explore",?headers=headers) pattern?=?re.compile('explore-feed.*?question_link.*?>(.*?)',?re.S) titles?=?re.findall(pattern,?r.text) print(titles)

      這里我們加入了headers信息,其中包含了User-Agent字段信息,也就是瀏覽器標識信息。如果不加這個,知乎會禁止抓取。

      接下來我們用到了最基礎的正則表達式來匹配出所有的問題內容。關于正則表達式的相關內容,我們會在3.3節中詳細介紹,這里作為實例來配合講解。

      運行結果如下:

      ['\n為什么很多人喜歡提及「拉丁語系」這個詞? \n',?'\n在沒有水的情況下水系寶可夢如何戰斗?\n',? '\n有哪些經驗可以送給?Kindle?新人?\n',?'\n谷歌的廣告業務是如何賺錢的?\n', ?'\n程序員該學習什么,能在上學期間掙錢?\n',?'\n有哪些原本只是一個小消息, ?但回看發現是個驚天大新聞的例子?\n',?'\n如何評價今敏?\n',?'\n源氏是怎么把那么長的刀從背后拔出來的?\n',? ?'\n年輕時得了絕癥或大病是怎樣的感受?\n',?'\n年輕時得了絕癥或大病是怎樣的感受?\n']

      我們發現,這里成功提取出了所有的問題內容。

      抓取二進制數據

      在上面的例子中,我們抓取的是知乎的一個頁面,實際上它返回的是一個HTML文檔。如果想抓去圖片、音頻、視頻等文件,應該怎么辦呢?

      圖片、音頻、視頻這些文件本質上都是由二進制碼組成的,由于有特定的保存格式和對應的解析方式,我們才可以看到這些形形色 色的多媒體。所以,想要抓取它們,就要拿到它們的二進制碼。

      下面以GitHub的站點圖標為例來看一下:

      import?requests r?=?requests.get("https://github.com/favicon.ico") print(r.text) print(r.content)

      這里抓取的內容是站點圖標,也就是在瀏覽器每一個標簽上顯示的小圖標,如圖3-3所示。

      圖3-3 站點圖標

      這里打印了Response對象的兩個屬性,一個是text,另一個是content。

      運行結果如圖3-4所示,其中前兩行是r.text的結果,最后一行是r.content的結果。

      圖3-4 運行結果

      可以注意到,前者出現了亂碼,后者結果前帶有一個b,這代表是bytes類型的數據。由于圖片是二進制數據,所以前者在打印時轉化為str類型,也就是圖片直接轉化為字符串,這理所當然會出現亂碼。

      接著,我們將剛才提取到的圖片保存下來:

      import?requests r?=?requests.get("https://github.com/favicon.ico") with?open('favicon.ico',?'wb')?as?f: ????f.write(r.content)

      這里用了open()方法,它的第一個參數是文件名稱,第二個參數代表以二進制寫的形式打開,可以向文件里寫入二進制數據。

      運行結束之后,可以發現在文件夾中出現了名為favicon.ico的圖標,如圖3-5所示。

      【Python3網絡爬蟲開發實戰】 3.2.1-基本用法

      圖3-5 圖標

      同樣地,音頻和視頻文件也可以用這種方法獲取。

      添加headers

      與urllib.request一樣,我們也可以通過headers參數來傳遞頭信息。

      比如,在上面“知乎”的例子中,如果不傳遞headers,就不能正常請求:

      import?requests r?=?requests.get("https://www.zhihu.com/explore") print(r.text)

      運行結果如下:

      500?Server?Error

      An?internal?server?error?occured.

      但如果加上headers并加上User-Agent信息,那就沒問題了:

      import?requests headers?=?{ ????'User-Agent':?'Mozilla/5.0?(Macintosh;?Intel?Mac?OS?X?10_11_4)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/52.0.2743.116?Safari/537.36' } r?=?requests.get("https://www.zhihu.com/explore",?headers=headers) print(r.text)

      當然,我們可以在headers這個參數中任意添加其他的字段信息。

      4. POST請求

      前面我們了解了最基本的GET請求,另外一種比較常見的請求方式是POST。使用requests實現POST請求同樣非常簡單,示例如下:

      import?requests data?=?{'name':?'germey',?'age':?'22'} r?=?requests.post("http://httpbin.org/post",?data=data) print(r.text)

      這里還是請求http://httpbin.org/post,該網站可以判斷如果請求是POST方式,就把相關請求信息返回。

      運行結果如下:

      { ??"args":?{},? ??"data":?"",? ??"files":?{},? ??"form":?{ ????"age":?"22",? ????"name":?"germey" ??},? ??"headers":?{ ????"Accept":?"*/*",? ????"Accept-Encoding":?"gzip,?deflate",? ????"Content-Length":?"18",? ????"Content-Type":?"application/x-www-form-urlencoded",? ????"Host":?"httpbin.org",? ????"User-Agent":?"python-requests/2.10.0" ??},? ??"json":?null,? ??"origin":?"182.33.248.131",? ??"url":?"http://httpbin.org/post" }

      可以發現,我們成功獲得了返回結果,其中form部分就是提交的數據,這就證明POST請求成功發送了。

      5. 響應

      發送請求后,得到的自然就是響應。在上面的實例中,我們使用text和content獲取了響應的內容。此外,還有很多屬性和方法可以用來獲取其他信息,比如狀態碼、響應頭、Cookies等。示例如下:

      import?requests r?=?requests.get('http://www.jianshu.com') print(type(r.status_code),?r.status_code) print(type(r.headers),?r.headers) print(type(r.cookies),?r.cookies) print(type(r.url),?r.url) print(type(r.history),?r.history)

      這里分別打印輸出status_code屬性得到狀態碼,輸出headers屬性得到響應頭,輸出cookies屬性得到Cookies,輸出url屬性得到URL,輸出history屬性得到請求歷史。

      運行結果如下:

      ?200 ?{'X-Runtime':?'0.006363',?'Connection':?'keep-alive',?'Content-Type':?' text/html;?charset=utf-8',?'X-Content-Type-Options':?'nosniff',?'Date':?'Sat,?27?Aug?2016?17:18:51?GMT',?'Server':?'nginx', ?'X-Frame-Options':?'DENY',?'Content-Encoding':?'gzip',?'Vary':?'Accept-Encoding',?'ETag':?'W/"3abda885e0e123bfde06d9b61e696159"',? ?'X-XSS-Protection':?'1;?mode=block',?'X-Request-Id':?'a8a3c4d5-f660-422f-8df9-49719dd9b5d4',? ?'Transfer-Encoding':?'chunked',?'Set-Cookie':?'read_mode=day;?path=/,?default_font=font2;?path=/,?_session_id=xxx;? ?path=/;?HttpOnly',?'Cache-Control':?'max-age=0,?private,?must-revalidate'} ?,? ,?]> ?http://www.jianshu.com/ ?[]

      因為session_id過長,在此簡寫??梢钥吹?,headers和cookies這兩個屬性得到的結果分別是CaseInsensitiveDict和RequestsCookieJar類型。

      狀態碼常用來判斷請求是否成功,而requests還提供了一個內置的狀態碼查詢對象requests.codes,示例如下:

      import?requests r?=?requests.get('http://www.jianshu.com') exit()?if?not?r.status_code?==?requests.codes.ok?else?print('Request?Successfully')

      這里通過比較返回碼和內置的成功的返回碼,來保證請求得到了正常響應,輸出成功請求的消息,否則程序終止,這里我們用requests.codes.ok得到的是成功的狀態碼200。

      那么,肯定不能只有ok這個條件碼。下面列出了返回碼和相應的查詢條件:

      #?信息性狀態碼 100:?('continue',), 101:?('switching_protocols',), 102:?('processing',), 103:?('checkpoint',), 122:?('uri_too_long',?'request_uri_too_long'), #?成功狀態碼 200:?('ok',?'okay',?'all_ok',?'all_okay',?'all_good',?'\\o/',?'?'), 201:?('created',), 202:?('accepted',), 203:?('non_authoritative_info',?'non_authoritative_information'), 204:?('no_content',), 205:?('reset_content',?'reset'), 206:?('partial_content',?'partial'), 207:?('multi_status',?'multiple_status',?'multi_stati',?'multiple_stati'), 208:?('already_reported',), 226:?('im_used',), #?重定向狀態碼 300:?('multiple_choices',), 301:?('moved_permanently',?'moved',?'\\o-'), 302:?('found',), 303:?('see_other',?'other'), 304:?('not_modified',), 305:?('use_proxy',), 306:?('switch_proxy',), 307:?('temporary_redirect',?'temporary_moved',?'temporary'), 308:?('permanent_redirect', ??????'resume_incomplete',?'resume',),?#?These?2?to?be?removed?in?3.0 #?客戶端錯誤狀態碼 400:?('bad_request',?'bad'), 401:?('unauthorized',), 402:?('payment_required',?'payment'), 403:?('forbidden',), 404:?('not_found',?'-o-'), 405:?('method_not_allowed',?'not_allowed'), 406:?('not_acceptable',), 407:?('proxy_authentication_required',?'proxy_auth',?'proxy_authentication'), 408:?('request_timeout',?'timeout'), 409:?('conflict',), 410:?('gone',), 411:?('length_required',), 412:?('precondition_failed',?'precondition'), 413:?('request_entity_too_large',), 414:?('request_uri_too_large',), 415:?('unsupported_media_type',?'unsupported_media',?'media_type'), 416:?('requested_range_not_satisfiable',?'requested_range',?'range_not_satisfiable'), 417:?('expectation_failed',), 418:?('im_a_teapot',?'teapot',?'i_am_a_teapot'), 421:?('misdirected_request',), 422:?('unprocessable_entity',?'unprocessable'), 423:?('locked',), 424:?('failed_dependency',?'dependency'), 425:?('unordered_collection',?'unordered'), 426:?('upgrade_required',?'upgrade'), 428:?('precondition_required',?'precondition'), 429:?('too_many_requests',?'too_many'), 431:?('header_fields_too_large',?'fields_too_large'), 444:?('no_response',?'none'), 449:?('retry_with',?'retry'), 450:?('blocked_by_windows_parental_controls',?'parental_controls'), 451:?('unavailable_for_legal_reasons',?'legal_reasons'), 499:?('client_closed_request',), #?服務端錯誤狀態碼 500:?('internal_server_error',?'server_error',?'/o\\',?'?'), 501:?('not_implemented',), 502:?('bad_gateway',), 503:?('service_unavailable',?'unavailable'), 504:?('gateway_timeout',), 505:?('http_version_not_supported',?'http_version'), 506:?('variant_also_negotiates',), 507:?('insufficient_storage',), 509:?('bandwidth_limit_exceeded',?'bandwidth'), 510:?('not_extended',), 511:?('network_authentication_required',?'network_auth',?'network_authentication')

      比如,如果想判斷結果是不是404狀態,可以用requests.codes.not_found來比對。

      python

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:物聯網項目實施中的五大挑戰
      下一篇:震驚 | 只需3分鐘!極速部署個人Docker云平臺
      相關文章
      国产L精品国产亚洲区久久| 亚洲一区二区三区国产精品无码| 亚洲视频在线观看地址| 人人狠狠综合久久亚洲婷婷| 国产精品亚洲mnbav网站 | 亚洲视频在线免费观看| 国产v亚洲v天堂无码网站| 国产亚洲大尺度无码无码专线| 亚洲人成网站18禁止一区| 亚洲片国产一区一级在线观看| 精品久久久久久亚洲中文字幕 | 亚洲精品无码鲁网中文电影| 久久乐国产精品亚洲综合| 亚洲国产综合久久天堂| 亚洲第一福利网站在线观看| 国产精品亚洲精品久久精品| 国产综合激情在线亚洲第一页| 蜜臀亚洲AV无码精品国产午夜.| 国产亚洲福利精品一区二区| 亚洲七七久久精品中文国产| 国产亚洲精品免费视频播放| 国产AV无码专区亚洲AV手机麻豆| 亚洲中文字幕无码久久2017| 日韩va亚洲va欧洲va国产| 久久精品国产亚洲AV网站| 亚洲宅男永久在线| 亚洲欧洲高清有无| 99亚偷拍自图区亚洲| 亚洲av无码一区二区三区天堂| www.亚洲色图| 不卡一卡二卡三亚洲| 亚洲精品成人片在线播放 | 亚洲高清有码中文字| 亚洲国产精品99久久久久久| 国产成人精品亚洲| 久久伊人亚洲AV无码网站| 亚洲va国产va天堂va久久| 亚洲精品动漫在线| 亚洲欧洲专线一区| 亚洲精品黄色视频在线观看免费资源| 久久久久国产亚洲AV麻豆 |