Python之路【第二十三篇】爬蟲
difference between urllib and urllib2
自己翻譯的裝逼必備
What is the difference between urllib and urllib2 modules of Python? #python的urllib2模組和urllib模組之間有什麼不同呢? You might be intrigued by the existence of two separate URL modules in Python - urllib and urllib2. Even more intriguing: they are not alternatives foreach other. So what is the difference between urllib and urllib2, and do we need them both? #這兩個模組你可能好奇,他們不是互相替代的模組。所以什麼是他們之間的不同呢?什麼時候我們使用他們? urllib and urllib2 are both Python modules that do URL request related stuff but offer different functionalities. Their two most significant differences are listed below:#urlib和urlib2他們都是訪問URL相關請求功能的模組,下面列出了他們之間的重要差異: urllib2 can accept a Request object to set the headers for a URL request, urllib accepts only a URL. That means, you cannot masquerade your User Agent string etc. #urlib2 可以接受請求物件去設定這個請求的頭部,urlib僅能接收一個URL意思是你不能偽裝你的使用者代理字串。 urllib provides the urlencode method which isused for the generation of GET query strings, urllib2 doesn't have such a function. This is one of the reasons why urllib is often used along with urllib2. #urlib 提供了 urlencode 方法使用者生成和查詢字串,urlib2不支援這個功能,這是為什麼常常urlib和urlib2一起使用的原因 For other differences between urllib and urllib2 refer to their documentations, the links are given in the References section. #看下面的連結 Tip: if you are planning to do HTTP stuff only, check out httplib2, it is much better than httplib or urllib or urllib2. #如果你僅僅是要獲取http頁面的東西的話,看看httplib2,它是比httplib or urlib or urlib2 更好的~~
在查詢的時候看到的文章很不錯:
http://www.hacksparrow.com/python-difference-between-urllib-and-urllib2.html
References
在Python3中合併了 urllib 和 urllib2, 統一命名為 urllib 了
urllib
整個Urllib的原始碼也就1000來行可以自己看下原始碼~~,並且urllib2和urllib一樣也就一個檔案~
1、urllib.urlopen(url, data=None, proxies=None, context=None)
開啟一個url的方法,返回一個檔案物件,然後可以進行類似檔案物件的操作。
import urllib f = urllib.urlopen('http://www.baidu.com/') content = f.readlines() print content
物件返回的物件提供的方法如下:
#這些方法的使用方式與檔案物件完全一樣 read() , readline() ,readlines() , fileno() , close() #返回一個請求頭資訊 content = f.info() print content ''' info方法內部呼叫的是headers方法 def info(self): return self.headers ''' #返回請求的狀態碼資訊 content = f.getcode() print content #返回請求的url資訊 content = f.geturl() print content
2、urllib.urlencode(query) 將URL中的鍵值對一連結符&劃分
>>> urllib.urlencode({'word':'luotianshuai','age':18}) 'age=18&word=luotianshuai'
所以我們可以結合urllib.urlopen來實現GET和POST請求
GET
import urllib params = urllib.urlencode({'word':'luotianshuai','age':18}) ''' >>> urllib.urlencode({'word':'luotianshuai','age':18}) 'age=18&word=luotianshuai' ''' f = urllib.urlopen('http://zhidao.baidu.com/search?%s' % params) print f.read()
POST
import urllib params = urllib.urlencode({'word':'luotianshuai','age':18}) ''' >>> urllib.urlencode({'word':'luotianshuai','age':18}) 'age=18&word=luotianshuai' ''' f = urllib.urlopen('http://zhidao.baidu.com/search',params) for i in f.read().split('\n'): print i
urllib2
import urllib2 import json import cookielib def urllib2_request(url, method="GET", cookie="", headers={}, data=None): """ :param url: 要請求的url :param cookie: 請求方式,GET、POST、DELETE、PUT.. :param cookie: 要傳入的cookie,cookie= 'k1=v1;k1=v2' :param headers: 傳送資料時攜帶的請求頭,headers = {'ContentType':'application/json; charset=UTF-8'} :param data: 要傳送的資料GET方式需要傳入引數,data={'d1': 'v1'} :return: 返回元祖,響應的字串內容 和 cookiejar物件 對於cookiejar物件,可以使用for迴圈訪問: for item in cookiejar: print item.name,item.value """ if data: data = json.dumps(data) cookie_jar = cookielib.CookieJar() handler = urllib2.HTTPCookieProcessor(cookie_jar) opener = urllib2.build_opener(handler) opener.addheaders.append(['Cookie', 'k1=v1;k1=v2']) request = urllib2.Request(url=url, data=data, headers=headers) request.get_method = lambda: method response = opener.open(request) origin = response.read() return origin, cookie_jar # GET result = urllib2_request('http://127.0.0.1:8001/index/', method="GET") # POST result = urllib2_request('http://127.0.0.1:8001/index/', method="POST", data= {'k1': 'v1'}) # PUT result = urllib2_request('http://127.0.0.1:8001/index/', method="PUT", data= {'k1': 'v1'}) 封裝urllib請求
requests
上面是吧urllib2進行了封裝並沒有實現上傳檔案要是上傳檔案的話就更麻煩了,所以又出現了一個模組requests上面的操作就相當於底層的東西了,requests對其進行了封裝!
所以我們只需安裝個包就OK了~
# 1、基本POST例項 import requests payload = {'key1': 'value1', 'key2': 'value2'} ret = requests.post("http://httpbin.org/post", data=payload) print ret.text # 2、傳送請求頭和資料例項 import requests import json url = 'https://api.github.com/some/endpoint' payload = {'some': 'data'} headers = {'content-type': 'application/json'} ret = requests.post(url, data=json.dumps(payload), headers=headers) print ret.text print ret.cookies #向https://api.github.com/some/endpoint傳送一個POST請求,將請求和相應相關的內容封裝在 ret 物件中。
二、其他請求
requests.get(url, params=None, **kwargs) requests.post(url, data=None, json=None, **kwargs) requests.put(url, data=None, **kwargs) requests.head(url, **kwargs) requests.delete(url, **kwargs) requests.patch(url, data=None, **kwargs) requests.options(url, **kwargs) # 以上方法均是在此方法的基礎上構建 requests.request(method, url, **kwargs)
requests模組已經將常用的Http請求方法為使用者封裝完成,使用者直接呼叫其提供的相應方法即可,其中方法的所有引數有:
def request(method, url, **kwargs): """Constructs and sends a :class:`Request <Request>`. :param method: method for the new :class:`Request` object. :param url: URL for the new :class:`Request` object. :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`. :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. :param json: (optional) json data to send in the body of the :class:`Request`. :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`. :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`. :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': ('filename', fileobj)}``) for multipart encoding upload. :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple :param allow_redirects: (optional) Boolean. Set to True if POST/PUT/DELETE redirect following is allowed. :type allow_redirects: bool :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy. :param verify: (optional) whether the SSL cert will be verified. A CA_BUNDLE path can also be provided. Defaults to ``True``. :param stream: (optional) if ``False``, the response content will be immediately downloaded. :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair. :return: :class:`Response <Response>` object :rtype: requests.Response Usage:: >>> import requests >>> req = requests.request('GET', 'http://httpbin.org/get') <Response [200]> """ # By using the 'with' statement we are sure the session is closed, thus we # avoid leaving sockets open which can trigger a ResourceWarning in some # cases, and look like a memory leak in others. with sessions.Session() as session: return session.request(method=method, url=url, **kwargs)
更多requests模組相關的文件見:http://cn.python-requests.org/zh_CN/latest/
結合reques可以進行瀏覽器一模一樣的工作!
#!/usr/bin/env python #-*- coding:utf-8 -*- __author__ = 'luotianshuai' import requests import json login_dic = { 'email':'[email protected]', 'password':'shuaige!', '_ref':'frame', } login_ret = requests.post(url='https://huaban.com/auth/', data=login_dic, ) print login_ret.text print '*' * 50 check_my_info = requests.get(url='http://huaban.com/ugb8cx9ky3/following/') print check_my_info.text
舉例來說如果是在web上聊天原理上也是通過get或者post傳送資料過去那麼我們就可以通過reques來進行傳送訊息訪問各種url 大讚~~
scrapy
Scrapy是一個為了爬取網站資料,提取結構性資料而編寫的應用框架。 其可以應用在資料探勘,資訊處理或儲存歷史資料等一系列的程式中。
其最初是為了頁面抓取 (更確切來說, 網路抓取 )所設計的, 也可以應用在獲取API所返回的資料(例如 Amazon Associates Web Services ) 或者通用的網路爬蟲。Scrapy用途廣泛,可以用於資料探勘、監測和自動化測試。
requests本質就是就是傳送http請求,如果在requests基礎上做個封裝,我去某個網站或者某個域名一直去傳送請求找到所有的url,下載東西的請求在寫個方法源源不斷的下載東西!這樣我們就寫了個框架。
Scrapy 使用了 Twisted非同步網路庫來處理網路通訊。整體架構大致如下
Scrapy主要包括了以下元件:
- 引擎(Scrapy)
用來處理整個系統的資料流處理, 觸發事務(框架核心) - 排程器(Scheduler)
用來接受引擎發過來的請求, 壓入佇列中, 並在引擎再次請求的時候返回. 可以想像成一個URL(抓取網頁的網址或者說是連結)的優先佇列, 由它來決定下一個要抓取的網址是什麼, 同時去除重複的網址 - 下載器(Downloader)
用於下載網頁內容, 並將網頁內容返回給蜘蛛(Scrapy下載器是建立在twisted這個高效的非同步模型上的) - 爬蟲(Spiders)
爬蟲是主要幹活的, 用於從特定的網頁中提取自己需要的資訊, 即所謂的實體(Item)。使用者也可以從中提取出連結,讓Scrapy繼續抓取下一個頁面 - 專案管道(Pipeline)
負責處理爬蟲從網頁中抽取的實體,主要的功能是持久化實體、驗證實體的有效性、清除不需要的資訊。當頁面被爬蟲解析後,將被髮送到專案管道,並經過幾個特定的次序處理資料。 - 下載器中介軟體(Downloader Middlewares)
位於Scrapy引擎和下載器之間的框架,主要是處理Scrapy引擎與下載器之間的請求及響應。 - 爬蟲中介軟體(Spider Middlewares)
介於Scrapy引擎和爬蟲之間的框架,主要工作是處理蜘蛛的響應輸入和請求輸出。 - 排程中介軟體(Scheduler Middewares)
介於Scrapy引擎和排程之間的中介軟體,從Scrapy引擎傳送到排程的請求和響應。
Scrapy中的資料流由執行引擎控制,其過程如下:
- 引擎開啟一個網站(open a domain),找到處理該網站的Spider並向該spider請求第一個要爬取的URL(s)。
- 引擎從Spider中獲取到第一個要爬取的URL並在排程器(Scheduler)以Request排程。
- 引擎向排程器請求下一個要爬取的URL。
- 排程器返回下一個要爬取的URL給引擎,引擎將URL通過下載中介軟體(請求(request)方向)轉發給下載器(Downloader)。
- 一旦頁面下載完畢,下載器生成一個該頁面的Response,並將其通過下載中介軟體(返回(response)方向)傳送給引擎。
- 引擎從下載器中接收到Response並通過Spider中介軟體(輸入方向)傳送給Spider處理。
- Spider處理Response並返回爬取到的Item及(跟進的)新的Request給引擎。
- 引擎將(Spider返回的)爬取到的Item給Item Pipeline,將(Spider返回的)Request給排程器。
- (從第二步)重複直到排程器中沒有更多地request,引擎關閉該網站。
一、安裝
pip install Scrapy #windows平臺需要依賴pywin32,請根據自己系統32/64位選擇下載安裝,https://sourceforge.net/projects/pywin32/
在MAC安裝的時候遇到了個有趣的問題自己總結了下面的文件~~,順便贊下Google
I resolved a problem ,when you you install scrapy-----{mac os system}, maybe you will get error like: ''' sted>=10.0.0->Scrapy) Installing collected packages: six, w3lib, parsel, PyDispatcher, Twisted, Scrapy Found existing installation: six 1.4.1 DEPRECATION: Uninstalling a distutils installed project (six) has been deprecated and will be removed in a future version. This is due to the fact that uninstalling a distutils project will only partially uninstall the project. Uninstalling six-1.4.1: Exception: Traceback (most recent call last): File "/Library/Python/2.7/site-packages/pip-8.1.1-py2.7.egg/pip/basecommand.py", line 209, in main status = self.run(options, args) File "/Library/Python/2.7/site-packages/pip-8.1.1-py2.7.egg/pip/commands/install.py", line 317, in run prefix=options.prefix_path, File "/Library/Python/2.7/site-packages/pip-8.1.1-py2.7.egg/pip/req/req_set.py", line 726, in install requirement.uninstall(auto_confirm=True) File "/Library/Python/2.7/site-packages/pip-8.1.1-py2.7.egg/pip/req/req_install.py", line 746, in uninstall paths_to_remove.remove(auto_confirm) File "/Library/Python/2.7/site-packages/pip-8.1.1-py2.7.egg/pip/req/req_uninstall.py", line 115, in remove renames(path, new_path) File "/Library/Python/2.7/site-packages/pip-8.1.1-py2.7.egg/pip/utils/__init__.py", line 267, in renames shutil.move(old, new) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/shutil.py", line 302, in move copy2(src, real_dst) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/shutil.py", line 131, in copy2 copystat(src, dst) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/shutil.py", line 103, in copystat os.chflags(dst, st.st_flags) OSError: [Errno 1] Operation not permitted: '/tmp/pip-ZVi5QO-uninstall/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/six-1.4.1-py2.7.egg-info' You are using pip version 8.1.1, however version 8.1.2 is available. You should consider upgrading via the 'pip install --upgrade pip' command. LuoTimdeMacBook-Pro-2:~ luotim$ sudo pip install Scrapy --ingnore-installed six ''' Six is a Python 2 and 3 compatibility library. frist thanks google and what's fuck baidu ! so you should be do this to resolved the problem: 1、Download the six-1.10.0.tar.gz package wget https://pypi.python.org/packages/b3/b2/238e2590826bfdd113244a40d9d3eb26918bd798fc187e2360a8367068db/six-1.10.0.tar.gz#md5=34eed507548117b2ab523ab14b2f8b55 2、UnZip software package tar -zxvf six-1.10.0.tar.gz 3、Use this command to install it. cd cd six-1.10.0 sudo python setup.py install http://stackoverflow.com/questions/29485741/unable-to-upgrade-python-six-package-in-mac-osx-10-10-2
二、基本使用
1、建立專案
執行命令他和Django一樣要想穿件Project必須執行下面的命令:
scrapy startproject your_project_name
將會在執行命令的目錄自動建立如下檔案:
LuoTimdeMacBook-Pro-2:day26 luotim$ tree meinv/ meinv/ ├── meinv │ ├── __init__.py │ ├── items.py │ ├── pipelines.py │ ├── settings.py │ └── spiders │ └── __init__.py └── scrapy.cfg 2 directories, 6 files
- scrapy.cfg 專案的配置資訊,主要為Scrapy命令列工具提供一個基礎的配置資訊。(真正爬蟲相關的配置資訊在settings.py檔案中)
- items.py 設定資料儲存模板,用於結構化資料,如:Django的Model
- pipelines 資料處理行為,如:一般結構化的資料持久化
- settings.py 配置檔案,如:遞迴的層數、併發數,延遲下載等
- spiders 爬蟲目錄,如:建立檔案,編寫爬蟲規則
2、編寫爬蟲
注意:一般建立爬蟲檔案時,以網站域名命名
在spiders目錄中新建 xiaohuar_spider.py 檔案
#!/usr/bin/env python #-*- coding:utf-8 -*- __author__ = 'luotianshuai' import scrapy #定義一個類 class XiaoHuarSpider(scrapy.spiders.Spider): #這個類是有名字的可以隨便定義 name = "xiaohuar" #定義限制只能在這個域名下爬 allowed_domains = ["xiaohuar.com"] #起始URL start_urls = [ "http://www.xiaohuar.com/hua/", ] ''' #當程式執行的時候,會自動執行我們定義的上面的類,並訪問start_urls並下載裡面的內容封裝起來傳給parese中的"response" 這個都是scrapy內部乾的 ''' def parse(self, response): # print(response, type(response)) # from scrapy.http.response.html import HtmlResponse # print(response.body_as_unicode()) '''然後就可以通過response獲取這次請求的相關資訊''' current_url = response.url body = response.body unicode_body = response.body_as_unicode()
3、執行
進入project_name目錄,執行命令!
#進入scrapy專案目錄裡 cd meinv #相關推薦
Python之路【第二十三篇】爬蟲
difference between urllib and urllib2 自己翻譯的裝逼必備 What is the difference between urllib and urllib2 modules of Python? #python的urllib2
Python之路【第五篇】:面向對象及相關
訪問 遊戲 font raise 內置 無法 sys 接下來 print 面向對象基礎 基礎內容介紹詳見一下兩篇博文: 面向對象初級篇 面向對象進階篇 其他相關 一、isinstance(obj, cls) 檢查是否obj是否是類 cls 的對象 class F
Python之路【第八篇】:堡壘機實例以及數據庫操作
流程 plain ima update 相關操作 tcs tmp int /tmp 堡壘機前戲 開發堡壘機之前,先來學習Python的paramiko模塊,該模塊機遇SSH用於連接遠程服務器並執行相關操作 SSHClient 用於連接遠程服務器並執行基本命令 基於用戶名密
Python之路【第三篇】:Python基礎之雜貨鋪
對齊 表示 microsoft 小數點 true per 字符串 orm bsp 字符串格式化 Python的字符串格式化有兩種方式:百分號方式、format方式 百分號的方式相對來說比較老,而format方式則是比較先進的方式,企圖替換古老的方式,目前兩者並存。 1
Python之路【第五篇】:面向物件及相關 面向物件基礎
其他相關 一、isinstance(obj, cls) 檢查是否obj是否是類 cls 的物件 1 2
Python之路【第二篇】計算機組成
時鐘頻率 space font 存儲 bit 硬件組成 第二篇 時鐘 速度慢 硬件組成:輸入單元、輸出單元、中央處理單元、存儲單元 南橋:I/O操作 北橋:CPU操作 0/1的單位稱為bit(位) bit是計算機中能識別的最小單位。 字節是計算機中最小的存儲單位。 8b
python全棧開發基礎【第二十三篇】線程
不同 控制 上海 strong 執行 不能 子進程 申請 什麽 一、什麽是線程 線程:顧名思義,就是一條流水線工作的過程,一條流水線必須屬於一個車間,一個車間的工作過程是一個進程 所以,進程只是用來把資源集中到一起(進程只是一個資源單位,或者說資源集合),而線程才是cpu上
Python成長之路【第五篇】:Python基礎之文件處理
閱讀 關註 src 文件路徑 程序 opened IT 寫入 文件操作 一、文件操作 1、介紹 計算機系統分為:計算機硬件,操作系統,應用程序三部分。 我們用python或其他語言編寫的應用程序若想要把數據永久保存下來,必須要保存於硬盤中,這就涉及到應用程序要操作硬件,
Python成長之路【第五篇】:Python基礎之裝飾器
brush urn 新功能 clas 現在 hide rom 接收 調用 一、什麽是裝飾器 裝飾:裝飾既修飾,意指為其他函數添加新功能 器:器既函數 裝飾器定義:本質就是函數,功能是為其他函數添加新功能 二、裝飾器需要遵循的原則 1、不能修改裝飾器的源代碼(開放封閉原則)
Python成長之路【第五篇】:Python基礎之模塊
module 應用程序 過程 解釋器 amp 之路 Python標準庫 pre 使用 模塊&包 模塊(module)的概念: 在計算機程序開發的過程中,隨著程序代碼越寫越多,在一個文件裏代碼就會越來越長,越來越不容易維護。為了編寫可維護的代碼,我們把很多函數分組,分
Python全棧開發之路 【第八篇】:面向對象編程設計與開發(2)
ssi pen 解析 執行 示例 動態 類型 put 所有 一、繼承與派生 什麽是繼承? 繼承指的是類與類之間的關系,是一種什麽是什麽的關系,繼承的功能之一就是用來解決代碼重用問題。 繼承是一種創建新的類的方式,在python中,新建的類可以繼承一個或多個父類,父類又可以成
Django 【第二十三篇】優化查詢
所有 一次 inf app related 方式 del filter model 一、假設有三張表 Room id 1 2 .. 1000 User: id 1 .. 10000
Python之路(第三十三篇) 網路程式設計:socketserver深度解析
一、socketserver 模組介紹 socketserver是標準庫中的一個高階模組,用於網路客戶端與伺服器的實現。(version = "0.4") 在python2中寫作SocketServer,在python3中寫作socketserver。 socoketserver兩個主要的類,一個是S
Python之路【第14章】:Python之快取 RabbitMQ、Redis、Memcache、SQLAlchemy
Python之快取 RabbitMQ、Redis、Memcache、SQLAlchemy 一、Memcached Memcached 是一個高效能的分散式記憶體物件快取系統,用於動態Web應用以減輕資料庫負載。它通過在記憶體中快取資料和物件來減少讀取資料庫的次數,從而提高動態、資料庫驅動網站的速度。Mem
Python之路【第一篇】:Python簡介和入門
源碼 world 網絡服務 換行 編程風格 大小寫 utf8 編譯安裝 比較 python簡介: 一、什麽是python Python(英國發音:/ pa θ n/ 美國發音:/ pa θɑ n/),是一種面向對象、直譯式的計算機程序語言。 每一門語言都有自己的哲學: py
Python之路【第十四篇】:Python的內置函數
blank function ocs 函數 alt 分享 詳細 png bsp Python中自帶了一些內置函數,如下圖所示 詳細說明可以戳這裏Python之路【第十四篇】:Python的內置函數
Python之路【第十七篇】:Django【進階篇 】
HP aid 超時 args lan 內置 resp hang ive Model 到目前為止,當我們的程序涉及到數據庫相關操作時,我們一般都會這麽搞: 創建數據庫,設計表結構和字段 使用 MySQLdb 來連接數據庫,並編寫數據訪問層代碼 業務邏輯層去調用數據
Python之路【第十九篇】:sys與os模塊
改變 python 隱藏 post 系統 rmdir 最大的 mman 就是 與解釋器相關的一些操作在sys模塊中,與系統相關的一些操作在os模塊中 sys模塊 sys.argv 命令行參數List,第一個元素是程序本身路徑 sys.exit(n)
Python之路【第十六篇】:Django【基礎篇】
web框架 imp self. tap resp 默認 進行 頁面 終端 Python的WEB框架有Django、Tornado、Flask 等多種,Django相較與其他WEB框架其優勢為:大而全,框架本身集成了ORM、模型綁定、模板引擎、緩存、Session等諸
Python之路【第一篇】:使用miniconda安裝python多版本
ase alias linux 1.10 ade ror another 離開 cer 一、簡介 Anaconda是一個發行包,裏面集成打包了很多的軟件包,使用conda包管理器來安裝軟件,比較方便,但是Anaconda軟件包太大,個人不太喜歡,想自己定制。Minicond