<label id="bh7tp"><big id="bh7tp"></big></label>

<em id="bh7tp"><tr id="bh7tp"><u id="bh7tp"></u></tr></em>
<th id="bh7tp"></th>

<li id="bh7tp"><acronym id="bh7tp"></acronym></li>
  • <em id="bh7tp"></em>

    <tbody id="bh7tp"><pre id="bh7tp"></pre></tbody>
  • Python教程自學網歡迎您來學習!
    當前位置: 首頁 > Python爬蟲 > python3爬蟲基本用法

    python3爬蟲基本用法

       

    python3爬蟲基本用法

    1. 準備工作

    在開始之前,請確保已經正確安裝好了requests庫。如果沒有安裝,可以參考爬蟲利器:requests庫的安裝。

    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)

    運行結果如下:

    <class?'requests.models.Response'>
    200
    <class?'str'>
    <html>
    <head>
    ????<script>
    ????????location.replace(location.href.replace("https://","http://"));
    ????</script>
    </head>
    <body>
    ????<noscript><meta?http-equiv="refresh"?content="0;url=http://www.baidu.com/"></noscript>
    </body>
    </html>
    <RequestsCookieJar[<Cookie?BIDUPSID=992C3B26F4C4D09505C5E959D5FBC005?for?.baidu.com/>,?<Cookie?PSTM=1472227535?
    for?.baidu.com/>,?<Cookie?__bsi=15304754498609545148_00_40_N_N_2_0303_C02F_N_N_N_0?for?.www.baidu.com/>,?
    <Cookie?BD_NOT_HTTPS=1?for?www.baidu.com/>]>

    這里我們調用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()))

    運行結果如下:

    <class?'str'>
    {'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'}
    <class?'dict'>

    可以發現,調用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.*?>(.*?)</a>',?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所示。

    python3爬蟲基本用法

    圖3-3 站點圖標

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

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

    python3爬蟲基本用法

    圖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-5 圖標

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

    添加headers

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

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

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

    運行結果如下:

    <html><body><h1>500?Server?Error</h1>
    An?internal?server?error?occured.
    </body></html>

    但如果加上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屬性得到請求歷史。

    運行結果如下:

    <class?'int'>?200
    <class?'requests.structures.CaseInsensitiveDict'>?{'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'}
    <class?'requests.cookies.RequestsCookieJar'>?<RequestsCookieJar[<Cookie?_session_id=xxx?for?www.jianshu.com/>,?
    <Cookie?default_font=font2?for?www.jianshu.com/>,?<Cookie?read_mode=day?for?www.jianshu.com/>]>
    <class?'str'>?http://www.jianshu.com/
    <class?'list'>?[]

    因為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來比對。

    人人爽人人澡人人人妻
    <label id="bh7tp"><big id="bh7tp"></big></label>

    <em id="bh7tp"><tr id="bh7tp"><u id="bh7tp"></u></tr></em>
    <th id="bh7tp"></th>

    <li id="bh7tp"><acronym id="bh7tp"></acronym></li>
  • <em id="bh7tp"></em>

    <tbody id="bh7tp"><pre id="bh7tp"></pre></tbody>