【第1周】網(wǎng)絡爬蟲之規(guī)則

單元1:Requests庫入門

Requests庫安裝

命令提示符,pip安裝

Requests庫的7個主要方法

方法 說明
requests.request() 構(gòu)造一個請求,支撐以下各方法的基礎
requests.get() 獲取HTML網(wǎng)頁的主要方法,對應于HTTP的GET
requests.head() 獲取HTML網(wǎng)頁頭信息的方法,對應于HTTP的HEAD
requests.post() 向HTML網(wǎng)頁提交POST請求的方法,對應于HTTP的POST
requests.put() 向HTML網(wǎng)頁提交PUT請求的方法,對應于HTTP的PUT
requests.patch() 向HTML網(wǎng)頁提交局部修改請求,對應于HTTP的PATCH
requests.delete() 向HTML頁面提交刪除請求,對應于HTTP的DELETE

Requests庫的get()方法

r=requests.get(url)

構(gòu)造一個向服務器請求資源的Requests對象,返回一個包含服務器資源的Response對象。
完整方法為

requests.get(url, params = None, **kwargs)
  • url:獲取頁面的url鏈接
  • params:url中的額外參數(shù),字典或字節(jié)流格式,可選
  • **kwargs:12個控制訪問的參數(shù)

調(diào)用.requests()方法實現(xiàn)

2個重要對象:Response和Requests
Response對象包含爬蟲返回的內(nèi)容

Response對象的屬性

屬性 說明
r.status_code HTTP請求的返回狀態(tài),200表示連接成功,404表示失敗
r.text HTTP響應內(nèi)容的字符串形式,即,url對應的頁面內(nèi)容
r.encoding 從HTTP header中猜測的響應內(nèi)容編碼方式
r.apparent_encoding 從內(nèi)容中分析出的響應內(nèi)容編碼方式(備用編碼方式)
r.content HTTP響應內(nèi)容的二進制形式

爬取網(wǎng)頁的通用代碼框架

網(wǎng)絡連接有危險,異常處理很重要。
理解Requests的異常

異常 說明
requests.ConnectionError 網(wǎng)絡連接錯誤異常,如DNS查詢失敗、拒絕連接等
requests.HTTPError HTTP錯誤異常
requests.URLRequired HRL缺失異常
requests.TooManyRedirects 超過最大重定向次數(shù),產(chǎn)生重定向異常
requests.ConnectTimeout 連接遠程服務器超時異常
requests.Timeout 請求URL超時,產(chǎn)生超時異常

理解Requests庫的異常

異常 說明
r.raise_for_status() 如果不是200,產(chǎn)生異常requests.HTTPError

爬取網(wǎng)頁的通用代碼框架

def getHTMLText(url):
    try:
        r = requests.get(url, timeout = 30)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return "產(chǎn)生異常"

使用該框架,例如:

if __name__ == "__main__":
    url = "http://www.baidu.com"
    print(getHTMLText(url))

HTTP協(xié)議及Requests庫方法

Requests有7個主要方法
理解HTTP協(xié)議:

  • 超文本傳輸協(xié)議
  • 基于請求與響應模式的、無狀態(tài)的應用層協(xié)議
  • 采用URL作為定位網(wǎng)絡資源的標識http://host[:port][path],host:合法的Internet主機域名或地址;port:端口號,默認80;path:請求資源的路徑
  • URL:通過HTTP協(xié)議存取資源的Internet路徑,一個URL對應一個數(shù)據(jù)資源

HTTP協(xié)議對資源的操作

方法 說明
GET 請求獲取URL位置的資源
HEAD 請求獲取URL位置資源的響應消息報告,即獲得該資源的頭部信息
POST 請求向URL位置的資源后附加新的數(shù)據(jù)
PUT 請求向URL位置存儲一個資源,覆蓋原URL位置的資源
PATCH 請求局部更新URL位置的資源,即改變該處資源的部分內(nèi)容
DELETE 請求刪除URL位置存儲的資源
HTTP協(xié)議對資源的操作

每一次操作獨立無狀態(tài)。

理解PATCH和PUT區(qū)別:
假設URL位置有一組數(shù)據(jù)UserInfo,包括UserID、UserName等20個字段。
需求:用戶只修改了UserName。

  • 采用PATCH,僅向URL提交UserName的局部更新請求
  • 采用PUT,必須將所有20個字段一并提交到URL,未提交字段被刪除

與Requests庫方法一一對應

head()方法

  • 用很少流量獲取網(wǎng)絡資源概要信息

post()方法

  • 向URL POST一個字典,自動編碼為form(表單)
  • POST一個字符串,自動編碼為data

put()方法:

  • 與post()方法類似,將原數(shù)據(jù)覆蓋掉

Requests庫主要方法解析

7個主要方法

requests.request(method, url, **kwargs)
  • method:請求方式,對應get/put/post等7種
  • **kwargs:控制訪問的參數(shù),13種:
    params:字典或字節(jié)序列,作為參數(shù)增加到url中
    data:字典、字節(jié)序列或文件對象,作為Request的內(nèi)容
    json:JSON格式的數(shù)據(jù),作為Requests的內(nèi)容
    headers:字典,HTTP定制頭
    cookies:字典或CookieJar,Request中的cookie
    auth:元組,支持HTTP認證功能
    files:字典類型,傳輸文件
    timeout:設定超時時間,秒為單位
    proxies:字典類型,設定訪問代理服務器,可以增加登錄認證
    allow_redirects:True/False,默認為True,重定向開關
    stream:True/False,默認為True,獲取內(nèi)容立即下載開關
    verify:True/False,默認為True,認證SSL證書開關
    cert:本地SSL證書路徑
requests.get(url, params = None, **kwargs)
  • params:url中的額外參數(shù),字典或字節(jié)流格式,可選
  • **kwargs:12個控制訪問的參數(shù)
requests.head(url, **kwargs)
  • **kwargs:13個控制訪問參數(shù)
requests.post(url, data = None, json = None, **kwargs)
  • data:字典、字節(jié)序列或文件,Request的內(nèi)容
  • json:JSON格式的數(shù)據(jù),Request的內(nèi)容
  • **kwargs:11個控制訪問參數(shù)
requests.put(url, data = None, **kwargs)
  • data:字典、字節(jié)序列或文件,Request的內(nèi)容
  • **kwargs:12個控制訪問參數(shù)
requests.patch(url, data = None, **kwargs)
  • data:字典、字節(jié)序列或文件,Request的內(nèi)容
  • **kwargs:12個控制訪問參數(shù)
requests.delete(url, **kwargs)
  • **kwargs:13個控制訪問參數(shù)

由于網(wǎng)絡安全限制,最常用的是get()方法

單元2:網(wǎng)絡爬蟲的“盜亦有道”

網(wǎng)絡爬蟲引發(fā)的問題

網(wǎng)絡爬蟲尺寸:

  • 爬取網(wǎng)頁,玩轉(zhuǎn)網(wǎng)頁:小規(guī)模,數(shù)據(jù)量小,爬取速度不敏感,Requests庫
  • 爬取網(wǎng)站,爬取系列網(wǎng)站:中規(guī)模,數(shù)據(jù)規(guī)模較大,爬取速度敏感,Scrapy庫
  • 爬取全網(wǎng):大規(guī)模,搜索引擎,爬取速度關鍵,定制開發(fā)

網(wǎng)絡爬蟲的“騷擾”

受限于編寫水平和目的,網(wǎng)絡爬蟲會對Web服務器帶來巨大的資源開銷。

網(wǎng)絡爬蟲的法律風險

服務器上的數(shù)據(jù)有產(chǎn)權歸屬。
網(wǎng)絡爬蟲獲取數(shù)據(jù)后牟利將帶來法律風險。

網(wǎng)絡爬蟲泄露隱私

網(wǎng)絡爬蟲可能具備突破簡單訪問控制的能力,獲得被保護數(shù)據(jù)從而泄露個人隱私。

限制網(wǎng)絡爬蟲

來源審查:判斷User-Agent進行限制

  • 只響應瀏覽器或友好爬蟲的訪問

發(fā)布公告:Robots協(xié)議

  • 告知所有爬蟲網(wǎng)站的爬取策略,需要爬蟲遵守

Robots協(xié)議

Robots Exclusion Standard 網(wǎng)絡爬蟲排除標準
作用:告知網(wǎng)絡爬蟲哪些頁面可以抓取,哪些不行。
形式:在網(wǎng)站根目錄下的robots.txt文件
例如:京東的Robots協(xié)議:https://www.jd.com/robots.txt

User-agent: *
Disallow: /?*
Disallow: /pop/.html
Disallow: /pinpai/
.html?*
User-agent: EtaoSpider
Disallow: /
User-agent: HuihuiSpider
Disallow: /
User-agent: GwdangSpider
Disallow: /
User-agent: WochachaSpider
Disallow: /

Robots協(xié)議基本語法

# 注釋,*代表所有,/代表根目錄
User-agent: *
Disallow: /

Robots協(xié)議的遵守方式

Robots協(xié)議的使用

網(wǎng)絡爬蟲:自動或人工識別robots.txt文件,再進行內(nèi)容爬取。
約束性:Robots協(xié)議是建議但非約束性,如果不遵守可能存在法律風險。
類人行為可以不參考Robots協(xié)議。

單元3:Requests網(wǎng)絡爬蟲實戰(zhàn)

實例1:京東商品頁面的爬取

爬取商品:https://item.jd.com/100002716279.html

>>> import requests
>>> r = requests.get("https://item.jd.com/100002716279.html")
>>> r.status_code
200
>>> r.encoding
'gbk'
>>> r.text[:1000]
'<!DOCTYPE HTML>\n<html lang="zh-CN">\n<head>\n    <!-- shouji -->\n    <meta http-equiv="Content-Type" content="text/html; charset=gbk" />\n    <title>【AppleiPad mini】Apple iPad mini 5 2019年新款平板電腦 7.9英寸(64G WLAN版/A12芯片/MUQW2CH/A)深空灰色【行情 報價 價格 評測】-京東</title>\n    <meta name="keywords" content="AppleiPad mini,AppleiPad mini,AppleiPad mini報價,AppleiPad mini報價"/>\n    <meta name="description" content="【AppleiPad mini】京東JD.COM提供AppleiPad mini正品行貨,并包括AppleiPad mini網(wǎng)購指南,以及AppleiPad mini圖片、iPad mini參數(shù)、iPad mini評論、iPad mini心得、iPad mini技巧等信息,網(wǎng)購AppleiPad mini上京東,放心又輕松" />\n    <meta name="format-detection" content="telephone=no">\n    <meta http-equiv="mobile-agent" content="format=xhtml; url=//item.m.jd.com/product/100002716279.html">\n    <meta http-equiv="mobile-agent" content="format=html5; url=//item.m.jd.com/product/100002716279.html">\n    <meta http-equiv="X-UA-Compatible" content="IE=Edge">\n    <link rel="canonical" />\n        <link rel="dns-prefetch" href="http://mi'

說明頁面返回信息,全部代碼為:

import requests
url = "https://item.jd.com/100002716279.html"
try:
    r = requests.get(url)
    r.raise_for_status()
    r.encoding = r.apparent_encoding
    print(r.text[:1000])
except:
    print("爬取失敗")

實例2:亞馬遜商品頁面的爬取

爬取商品:https://www.amazon.cn/dp/B005T63BEM/ref=lp_1559274071_1_1?s=electronics&ie=UTF8&qid=1569760137&sr=1-1

>>> import requests
>>> r = requests.get("https://www.amazon.cn/dp/B005T63BEM/ref=lp_1559274071_1_1?s=electronics&ie=UTF8&qid=1569760137&sr=1-1")
>>> r.status_code
200
>>> r.encoding
'UTF-8'
>>> r.text[:1000]
'\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  \n  \n\n\n\n\n\n\n\n    \n\n    \n\n\n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        \n            \n            \n        \n\n\n\n\n\n \n \n\n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n    \n\n\n\n\n\n    <!doctype html><html class="a-no-js" data-19ax5a9jf="dingo">\n    <head><script>var aPageStart = (new Date()).getTime();</script><meta charset="utf-8">\n\n    \n\n\n\n    <link rel="dns-prefetch" >\n\n\n\n\n  \n\n\n\n\n    \n\n\n\n\n\n\n    \n    \n\n\n\n\n\n\n\n  \n  \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n    \n    \n\n\n    \n    \n\n\n\n\n\n\n\n\n\n\n\n\n<script type="text/javascript">\nvar iUrl = "https://images-cn.ssl-images-amazon.com/images/I/415tpDfFbTL._SX300_QL70_.jpg";\n(function(){var i=new Image; i.src = iUrl;})();\n</script>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  \n\n   \n    \n\n\n\n\n\n\n\n<!--  -->\n<link rel="stylesheet" 
>>> r.request.headers
{'User-Agent': 'python-requests/2.22.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}

User-Agent為'python-requests/2.22.0,如果被拒絕,可以更改頭部信息的User-Agent為其他瀏覽器。

>>> kv = {'User-Agent':'Mozilla/5.0'}
>>> url = 'https://www.amazon.cn/dp/B005T63BEM/ref=lp_1559274071_1_1?s=electronics&ie=UTF8&qid=1569760137&sr=1-1'
>>> r = requests.get(url, headers = kv)
>>> r.status_code
200
>>> r.request.headers
{'User-Agent': 'Mozilla/5.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}
>>> r.text[:1000]
'\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  \n  \n\n\n\n\n\n\n\n    \n\n    \n\n\n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n\n\n    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n    \n\n\n\n\n\n    <!doctype html><html class="a-no-js" data-19ax5a9jf="dingo">\n    <head>\n<script type="text/javascript">var ue_t0=ue_t0||+new Date();</script>\n<script type="text/javascript">\nwindow.ue_ihb = (window.ue_ihb || window.ueinit || 0) + 1;\nif (window.ue_ihb === 1) {\nvar ue_hob=+new Date();\nvar ue_id=\'E5W4931DMCTPC168HBBY\',\nue_csm = window,\nue_err_chan = \'jserr-rw\',\nue = {};\n(function(d){var e=d.ue=d.ue||{},f=Date.now||function(){return+new Date};e.d=function(b){return f()-(b?0:d.ue_t0)};e.stub=function(b,a){if(!b[a]){var c=[];b[a]=function(){c.push([c.slice.call(arguments),e.d(),d.ue_id])};b[a].replay=function(b){for(var a;a=c.shift();)b(a[0],a[1],a[2])};b[a].isStub=1}};e.exec=function(b,a){return function(){try{return b.apply(this,arguments)}catch(c){ueLogError(c,{attribution:a||"undefined",logLevel:"WARN"})}}}})(ue_csm);\n\nue.stub(ue,"log");ue.stub(ue,"onunload");ue.stub(ue,"onflu'

全部代碼

import requests
url = 'https://www.amazon.cn/dp/B005T63BEM/ref=lp_1559274071_1_1?s=electronics&ie=UTF8&qid=1569760137&sr=1-1'
try:
    kv = {'User-Agent':'Mozilla/5.0'}
    r = requsts.get(url, headers = kv)
    r.raise_for_status()
    r.encoding = r.apparent_encoding
    print(r.text[1000:2000])
except:
    print('爬取失敗')

實例3:百度/360搜索關鍵詞提交

自動提交關鍵詞并獲得結(jié)果。
搜索引起關鍵詞提交接口
百度關鍵詞接口:http://www.baidu.com/s?wd=keyword
360關鍵詞接口:http://www.so.com/s?q=keyword
使用params

>>> import requests
>>> kv = {'wd':'Python'}
>>> r = requests.get('http://www.baidu.com/s', params = kv)
>>> r.status_code
200
>>> r.request.url
'http://www.baidu.com/s?wd=Python'
>>> len(r.text)
358258

完整代碼

import requests
keyword = 'Python'
try:
    kv = {'wd':keyword}
    r = requests.get('http://www.baidu.com/s', params = kv)
    print(r.request.url)
    r.raise_for_status()
    print(len(r.text))
except:
    print('爬取失敗')

360的方法類似,代碼為

import requests
keyword = 'Python'
try:
    kv = {'q':keyword}
    r = requests.get('http://www.so.com/s', params = kv)
    print(r.request.url)
    r.raise_for_status()
    print(len(r.text))
except:
    print('爬取失敗')

實例4:網(wǎng)路圖片的爬取和存儲

網(wǎng)絡圖片鏈接的格式:
http://www.example.com/picture.jpg
圖片網(wǎng)址為:https://www.nationalgeographic.com/content/dam/expeditions/landing-pages/North-America/hero-national-parks2.adapt.1900.1.jpg
保存為C盤abc.jpg

>>> import requests
>>> path = 'C:/abc.jpg'
>>> url = 'https://www.nationalgeographic.com/content/dam/expeditions/landing-pages/North-America/hero-national-parks2.adapt.1900.1.jpg'
>>> r = requests.get(url)
>>> r.status_code
200
>>> with open(path, 'wb') as f:
    f.write(r.content)

    
300340
>>> f.close()

完整代碼為

import requests
import os
url = 'https://www.nationalgeographic.com/content/dam/expeditions/landing-pages/North-America/hero-national-parks2.adapt.1900.1.jpg'
root = "C://"
path = root + url.split('/')[-1] #保存圖片原有名字
try:
    if not os.path.exists(root):    #判斷根目錄是否存在,若不存在,建立根目錄
        os.mkdir(root)
    if not os.path.exists(path):    #判斷文件是否存在,若不存在,獲取文件
        r = requests.get(url)
        with open(path, 'wb') as f:
            f.write(r.content)
            f.close()
            print('文件保存成功')
    else:
        print('文件已存在')
except:
    print('爬取失敗')

考慮出現(xiàn)的問題,并對相應的異常進行處理。
修改代碼,可以獲取不同的資源。

實例5:IP地址歸屬地的自動查詢

通過ip138網(wǎng)站提交ip地址后,鏈接變?yōu)椋?br> http://m.ip138.com/ip.asp?ip=ipaddress

>>> f.close()
>>> import requests
>>> url = 'http://m.ip138.com/ip.asp?ip='
>>> r = requests.get(url + '202.204.80.112')
>>> r.status_code
200
>>> r.text[-500:]
'value="查詢" class="form-btn" />\r\n\t\t\t\t\t</form>\r\n\t\t\t\t</div>\r\n\t\t\t\t<div class="query-hd">ip138.com IP查詢(搜索IP地址的地理位置)</div>\r\n\t\t\t\t<h1 class="query">您查詢的IP:202.204.80.112</h1><p class="result">本站主數(shù)據(jù):北京市海淀區(qū) 北京理工大學 教育網(wǎng)</p><p class="result">參考數(shù)據(jù)一:北京市 北京理工大學</p>\r\n\r\n\t\t\t</div>\r\n\t\t</div>\r\n\r\n\t\t<div class="footer">\r\n\t\t\t<a  rel="nofollow" target="_blank">滬ICP備10013467號-1</a>\r\n\t\t</div>\r\n\t</div>\r\n\r\n\t<script type="text/javascript" src="/script/common.js"></script></body>\r\n</html>\r\n'

完整代碼

import requests
url = 'http://m.ip138.com/ip.asp?ip='
try:
    r = requests.get(url + '202.204.80.112')
    r.raise_for_status()
    r.encoding = r.apparent_encoding
    print(r.text[-500:])
except:
    print('爬取失敗')

許多網(wǎng)站人機交互都是以鏈接的方式提交,知道提交的鏈接形式可以用Python模擬提交。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容