您好,登錄后才能下訂單哦!
爬蟲是我們快速獲取需要的數據的一個非常有效的途徑,而爬蟲的第一步便是能夠請求遠方服務器為我們返回所需的網頁信息。我們知道,正常情況下在瀏覽器上我們只要輸入正確的統一資源定位器url,即網頁地址便可輕松打開我們想要看到頁面。同理,在設計python爬蟲程序時,我們也可以調用對應的庫通過參數設置來連接網絡處理http協議。針對靜態的網頁,常常被使用到的庫有urllib, urllib2, requests等等,通過它們可以很方便的請求服務器返回特定地址的網頁內容。但是如果遇到JS加載的動態網頁,用前面的方法往往收不到我們想要的結果。這時候就可以召喚出強大的自動化測試工具Selenium并喊上它的小伙伴PhantomJS來一起升級打怪了。
(一) urllib, urllib2,直接上例子:
[python] view plain copy
import urllib2
response = urllib2.urlopen("http://www.baidu.com")
print response.read()
上面只要給一個url,例如百度,調用urllib2庫便可以單槍匹馬讀到這個網址對應的網頁源碼,代碼特別簡潔。實際爬蟲中由于考慮到對方的反爬蟲機制,網絡響應時間或者發送請求需要添加額外的信息 ,我們需要多添加幾行代碼,目的是讓服務器盡量相信收到的請求都是來自正常的訪問對象。為了程序邏輯清晰,我們可以為urlopen設計一個request對象作為傳入參數,例如:
[python] view plain copy
import urllib
import urllib2
#添加url
url = 'xxx'
request = urllib2.Request(url)
#為了模擬瀏覽器行為,偽裝對方識別問題,可以添加Headers屬性,例如下面的agent便是設置請求身份:
user_agent = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36'
headers = { 'User-Agent' : user_agent}
request = urllib2.Request(url, headers)
#有時訪問某些網站需要提供一些信息,例如用戶名和密碼,這時可以這樣:
values = {"username":"yourname","password":"????"}
data = urllib.urlencode(values)
request = urllib2.Request(url, data, headers)
#在遇到網絡狀況不好時可以設置timeout來設置等待多久超時
response = urllib2.urlopen(request,timeout=18)
print response.read()
更多的相關內容可以查看這個urllib和urllib2。
(二)requests,一款簡單美觀而友好的外部庫。
requests所有的功能都可以通過以下7個方法訪問。它們全部都會返回一個response對象的實例。
[python] view plain copy
#創建并發送一個request
requests.request(method, url, **kwargs)
參數:
method -- method for the new Request object.
url -- URL for the new Request object.
params -- (optional) Dictionary or bytes to be sent in the query string for the Request.
data -- (optional) Dictionary, bytes, or file-like object to send in the body of the Request.
json -- (optional) json data to send in the body of the Request.
headers -- (optional) Dictionary of HTTP Headers to send with the Request.
cookies -- (optional) Dict or CookieJar object to send with the Request.
files -- (optional) Dictionary of 'name': file-like-objects (or {'name': file-tuple}) for multipart encoding upload. file-tuple can be a 2-tuple ('filename', fileobj), 3-tuple ('filename', fileobj, 'content_type') or a 4-tuple ('filename', fileobj, 'content_type', custom_headers), where 'content-type' is a string defining the content type of the given file and custom_headers a dict-like object containing additional headers to add for the file.
auth -- (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.
timeout (float or tuple) -- (optional) How long to wait for the server to send data before giving up, as a float, or a (connect timeout, read timeout) tuple.
allow_redirects (bool) -- (optional) Boolean. Set to True if POST/PUT/DELETE redirect following is allowed.
proxies -- (optional) Dictionary mapping protocol to the URL of the proxy.
verify -- (optional) whether the SSL cert will be verified. A CA_BUNDLE path can also be provided. Defaults to True.
stream -- (optional) if False, the response content will be immediately downloaded.
cert -- (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.
#例如:
import requests
url='xxxx'
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36'}
proxies = { 'http' : '127.0.0.1:8118'}
response=requests.request('GET',url, timeout=20, proxies=proxies, headers=headers)
返回類型requests.Response
另:
#發送一個HEAD request.
requests.head(url, **kwargs)
#發送一個GET request
requests.get(url, params=None, **kwargs)
#發送一個POST request
requests.post(url, data=None, json=None, **kwargs)
#發送一個PUT request
requests.put(url, data=None, **kwargs)
#發送一個PATCH request
requests.patch(url, data=None, **kwargs)
#發送一個DELETE request
requests.delete(url, **kwargs)
更詳細的介紹可以參考官網requests。
(三)Selenium + PhantomJs,高效處理動態網頁的完美組合。
我們使用前面的方法可以單純的獲取網頁的html代碼,如若是遇到要經過JS渲染的網頁內容時則會變得非常麻煩。所以我們需要能夠像瀏覽器一樣處理要JS渲染的頁面的工具,而PhantomJs正是一款基于WebKit的×××面的網頁交互工具,其提供的JavaScript API可以實現自動化瀏覽、定坤丹截屏等瀏覽器功能。Selenium是一款自動化測試工具,其支持Firefox,Chrome,Safari等主流的瀏覽器,借助selenium就可以模擬人類的各種網頁操作行為,例如打開瀏覽器,輸入信息,點擊,翻頁等等。PhantomJS作為一款×××面的瀏覽器,Selenium會對它感冒嗎?答案是非常感冒,因為PhantomJs不僅能完成瀏覽器的功能,其效率相對來說還更高。例如:
[python] view plain copy
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
phantomjs_path = '/data/opt/brew/lib/node_modules/phantomjs/lib/phantom/bin/phantomjs'
driver = webdriver.PhantomJS(executable_path=phantomjs_path)
url = 'xxxx'
driver.get(url)
#輕松得到到JS渲染頁面的源碼
page_source = driver.page_source.encode('utf8')
有時候我們需要做到頁面交互,即可以模擬人在瀏覽器上點擊,輸入,鼠標移動等各種行為時,這就需要先做到對頁面元素的定位問題。其中WebDriver提供了多種方法來實現元素定位:
[python] view plain copy
#定位一個元素的方法有
find_element_by_id
find_element_by_name
find_element_by_xpath
find_element_by_link_text
find_element_by_partial_link_text
find_element_by_tag_name
find_element_by_class_name
find_element_by_css_selector
#定位多元素,返回一個list,方法有
find_elements_by_name
find_elements_by_xpath
find_elements_by_link_text
find_elements_by_partial_link_text
find_elements_by_tag_name
find_elements_by_class_name
find_elements_by_css_selector
#例如有如下網頁源碼:
<html>
<body>
<form id="loginForm">
<input name="username" type="text" />
<input name="password" type="password" />
<input name="continue" type="submit" value="Login" />
<input name="continue" type="button" value="Clear" />
</form>
</body>
<html>
#form可以這樣來定位
login_form = driver.find_element_by_id('loginForm')
#username&password兩個元素定位如下
username = driver.find_element_by_name('username')
password = driver.find_element_by_name('password')
#如果使用xpath來定位username,以下方法都ok
username = driver.find_element_by_xpath("http://form[input/@name='username']")
username = driver.find_element_by_xpath("http://form[@id='loginForm']/input[1]")
username = driver.find_element_by_xpath("http://input[@name='username']")
更多內容可以參考selenium_python,PhantomJS。
這篇文章簡短介紹了網頁源碼內容獲取的各種方法,包括靜態網頁常常使用到的urllib,urllib2,requests和動態網頁使用到的selenium,phantomjs組合。在爬蟲過程中,我們往往需要提取并保留網頁中有用的信息,所以接下來要介紹的是如何針對獲得的網頁源碼提取出有用信息的工作。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。