Python 爬蟲入門(一)urllib的基本使用

參考資料
1.用python開發爬蟲 https://www.gitbook.com/book/germey/python3webspider/details
2.論一只爬蟲的自我修養 http://blog.fishc.com/category/python/spider
3.Python爬蟲學習系列教程 http://cuiqingcai.com/1052.html
4.Beautiful Soup 4.2.0 中文文檔 https://wizardforcel.gitbooks.io/bs4-doc/content/
5.Requests: 讓 HTTP 服務人類 http://docs.python-requests.org/zh_CN/latest/

前言:
urllib包含四個模塊:

  • urllib.request可以用來發送request和獲取request的結果
  • urllib.error包含了urllib.request產生的異常
  • urllib.parse用來解析和處理URL
  • urllib.robotparse用來解析頁面的robots.txt文件
1. urllib.request的基本使用方法屬性
1.1. 使用urllib.request.urlopen()來爬取網頁
In [1]: import urllib.request
In [2]: r=urllib.request.urlopen('http://blog.fishc.com/3597.html')
In [3]: r.read().decode('utf-8')
Out[3]: '<!DOCTYPE html>\n<html xmlns="http://www.w3.org/1999/xhtml"><head profile="http://gmpg.org/xfn/11">\n<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\n<title>論一只爬蟲的自我修養2:實戰 – 零基礎入門學習Python054 | 魚C工作室</title>\n<meta name="description" content="論一只爬蟲的自我修養2:實戰" />\n<meta name="keywords" content="Python3下載網頁,Python3爬蟲,Python3蜘蛛,urllib" />\n<link rel="stylesheet" type="......
In [4]: type(r)
Out[4]: http.client.HTTPResponse

可以看到,使用urllib.request.urlopen()返回的對象是一個http.client.HTTPResponse類型的對象,它主要包含的方法有read(),readinto(),getheader(name),getheaders(),fileno()等函數和msg,versionstatus,reason,debuglevel,closed等屬性。

In [8]: r.getheaders()
Out[8]: 
[('Date', 'Sun, 19 Feb 2017 13:08:21 GMT'),
 ('Content-Type', 'text/html; charset=UTF-8'),
 ('Transfer-Encoding', 'chunked'),
 ('Connection', 'close'),
 ('Set-Cookie', 'acw_tc=AQAAANMMjDotOggAUUhyyn/OUgglngLJ; Path=/; HttpOnly'),
 ('Server', 'Fishc'),
 ('Vary', 'Accept-Encoding'),
 ('X-Powered-By', 'PHP/5.6.15'),
 ('X-Pingback', 'http://blog.fishc.com/xmlrpc.php'),
 ('Link', '<http://blog.fishc.com/?p=3597>; rel=shortlink')]
In [9]: r.getheader('server')
Out[9]: 'Fishc'
In [10]: r.status
Out[10]: 200

urllib.request.urlopen()使用具體參數如下:

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)

(1)使用data參數可發起數據提交請求,相當于post,詳細見文章最后實戰代碼。
(2)使用timeout參數可以限定超時時間,超過則報錯,默認不設置,表示始終請求直至手動關閉程序。
(3)context參數,它必須是ssl.SSLContext類型,用來指定SSL設置。cafile和capath兩個參數是指定CA證書和它的路徑,這個在請求HTTPS鏈接時會有用。cadefault參數現在已經棄用了,默認為False。

1.2 修改head或者使用代理來防止爬蟲被服務器阻攔

使用爬蟲對網頁發起請求時,若訪問量過大則常常會被服務器阻攔,此時可通過修改headers或者使用代理進行訪問。
1.修改headers方法有兩種:(1)通過Request的headers參數來進行修改 (2)通過Request.add_header()方法來進行添加headers。

# (1)通過Request的headers參數來進行修改
head={}
head['User-Agent']='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
request=urllib.request.Request(url, data, head)     # 創建一個Request對象
response=urllib.request.urlopen(request)  # 爬取網頁

# (2)通過`Request.add_header()`方法來進行添加head
request=urllib.request.Request(url, data)     # 創建一個Request對象
 # 添加head
request.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36')  
response=urllib.request.urlopen(request)  # 爬取網頁

2.使用代理來進行爬蟲可簡單分為3步:

# (1)參數是一個字典{'類型':'代理ip:端口號'}
proxy_support=urllib.request.ProxyHandler({})

# (2)定制、創建一個opener(代理)
opener=urllib.request.build_opener(proxy_support)
# opener也可以添加head信息
opener.addheaders=[('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36')]

# (3a)安裝opener,安裝后以后訪問都會使用此代理
urllib.request.install_opener(opener)

# (3b)不安裝,調用opener(也即代理)來打開網頁
opener.open(url)

# opener也可以添加head信息

2. 使用urllib.error處理異常

主要異常詳見使用urllib.error處理異常.
這里主要了解下try,except用法:

import urllib.request
import urllib.error
try:    
   response=urllib.request.urlopen('http://suibiankankan.com')
except urllib.error.URLError as e:
   print(e.reason)

# [Errno -2] Name or service not known   
3. 使用urllib.parse解析鏈接

使用urllib.parse.urlparse()進行鏈接解析,拆解鏈接的各部分內容。

In [17]: import urllib.parse
In [19]: result = urllib.parse.urlparse('http://www.baidu.com/index.html;user?id=5#comment')
In [20]: type(result)
Out[20]: urllib.parse.ParseResult
In [21]: result
Out[21]: ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html', params='user', query='id=5', fragment='comment')
In [22]: result[1]
Out[22]: 'www.baidu.com'
In [24]: result.netloc
Out[24]: 'www.baidu.com'

觀察可以看到,返回結果是一個ParseResult類型的對象,它包含了六個部分,分別是schemenetlocpathparamsqueryfragment。使用索引或者屬性可以查看解析結果。
由上可以得出一個標準的鏈接格式如下:

scheme://netloc/path;parameters?query#fragment

使用urllib.parse.urlunparse()可以將幾個部分連接起來。

In [25]: data = ['http', 'www.baidu.com', 'index.html', 'user', 'a=6', 'comment']
In [26]: urllib.parse.urlunparse(data)
Out[26]: 'http://www.baidu.com/index.html;user?a=6#comment'

其他的一些方法:
(1)urllib.parse.urlsplit(),這個和urlparse()方法非常相似,只不過它不會單獨解析parameters這一部分,只返回五個結果。上面例子中的parameters會合并到path中。
(2)urllib.parse.urlunsplit(),與urlunparse()類似,也是將鏈接的各個部分組合成完整鏈接的方法,傳入的也是一個可迭代對象。 例如list、tuple等等,唯一的區別是,長度必須為5。
(3)urllib.parse.urljoin(),利用urljoin()方法我們可以提供一個base_url(基礎鏈接),新的鏈接作為第二個參數,方法會分析base_url的scheme、netloc、path這三個內容對新鏈接缺失的部分進行補充,作為結果返回。如果這三項在新的鏈接里面不存在,那么就予以補充,如果新的鏈接存在,那么就使用新的鏈接的部分。base_url中的parameters、query、fragments是不起作用的。

In [27]: urllib.parse.urljoin('http://www.baidu.com', 'FAQ.html')
Out[27]: 'http://www.baidu.com/FAQ.html'
4. 使用urllib.robotparser分析robots協議

robots協議也被稱作爬蟲協議、機器人協議,它的全名叫做網絡爬蟲排除標準(Robots Exclusion Protocol),同來告訴爬蟲和搜索引擎哪些頁面可以抓取,哪些不可以抓取。它通常是一個叫做robots.txt的文本文件,放在網站的根目錄下。
當一個搜索蜘蛛訪問一個站點時,它首先會檢查下這個站點根目錄下是否存在robots.txt文件,如果存在,搜索蜘蛛會根據其中定義的爬取范圍來爬取。如果沒有找到這個文件,那么搜索蜘蛛便會訪問所有可直接訪問的頁面。

User-agent: *
Disallow: /
Allow: /public/

以上的兩行實現了對所有搜索蜘蛛只允許爬取public目錄的作用。
如上簡單的兩行,保存成robots.txt文件,放在網站的根目錄下,和網站的入口文件放在一起。比如index.php、index.html、index.jsp等等。
那么上面的User-agent就描述了搜索蜘蛛的名稱,在這里將值設置為*,則代表該協議對任何的爬取蜘蛛有效。比如你可以設置User-agent: Baiduspider,就代表我們設置的規則對百度搜索引擎是有效的。如果有多條User-agent記錄,則就會有多個爬取蜘蛛會受到爬取限制,但你至少需要指定一條。
Disallow指定了不允許抓取的目錄,比如上述例子中設置為/則代表不允許抓取所有頁面。
Allow它一般和Disallow一起使用,一般不會單獨使用,現在我們設置為/public/,起到的作用是所有頁面不允許抓取,但是public目錄是可以抓取的。

urllib.robotparser提供了一個類,叫做RobotFileParser。它可以根據某網站的robots.txt文件來判斷一個爬取蜘蛛是否有權限來爬取這個網頁。
使用方法:

urllib.robotparser.RobotFileParser(url='')

例子:

rom urllib.robotparser import RobotFileParser

rp = RobotFileParser('http://www.lxweimin.com/robots.txt')
rp.read()
print(rp.can_fetch('*', 'http://www.lxweimin.com/p/b67554025d7d'))
print(rp.can_fetch('*', "http://www.lxweimin.com/search?q=python&page=1&type=collections"))

# True
# False

以上簡單介紹urllib的簡單用法,下面給出一個實戰例子,交互式有道翻譯請求:

import urllib.request
import urllib.parse
import json

url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=https://www.google.com.hk/'
data=dict()
data['type']='AUTO'
data['i']=input("Plz input what you want to translate: ")
data['doctype']='json'
data['xmlVersion']='1.8'
data['keyfrom']='fanyi.web'
data['ue']='UTF-8'
data['action']='FY_BY_CLICKBUTTON'
data['typoResult']='true'
data=urllib.parse.urlencode(data).encode('utf-8')
# 必須對data進行轉碼

response=urllib.request.urlopen(url,data)
html=response.read().decode('utf-8')

target=json.loads(html)

print('翻譯結果:',target['translateResult'][0][0]['tgt'])
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1 前言 作為一名合格的數據分析師,其完整的技術知識體系必須貫穿數據獲取、數據存儲、數據提取、數據分析、數據挖掘、...
    whenif閱讀 18,105評論 45 523
  • 本內容為《用Python寫網絡爬蟲》書籍內容,有興趣的讀者可以購買本書,本章的代碼皆可在Python3中運行。為了...
    海人為記閱讀 2,270評論 0 5
  • Python版本管理:pyenv和pyenv-virtualenvScrapy爬蟲入門教程一 安裝和基本使用Scr...
    inke閱讀 35,603評論 7 93
  • 對電視劇,對讀書,對工作,對興趣,一切都是半拉柯基。讀透,讀懂,那太慢了。 可是有那么多的東西都想看看,也是浮光掠...
    金地陽光閱讀 1,344評論 0 0
  • 曾有朋友和我說過,不談以后。因為“以后”是由每一個“現在”組成的:如果現在都不能做好,又何來得以后,所以想做的事,...
    向應昌閱讀 1,114評論 5 23