通過三個函數了解Python網路爬蟲

前言:

最近在學習Python網路爬蟲,在這裡分享一下自己的學習成果,這篇文章我不打算細究語法細節,而是想通過幾個函數梳理下網路爬蟲的過程。個人理解有不當的地方,還望大家指出。我認為網路爬蟲就是用自己的電腦去web伺服器(另一台電腦)上下載東西,其中涉及到兩個問題:

(1)怎麼讓自己的電腦和web伺服器連接

(2)正常連接之後,怎麼把想要的信息提取出來

爬蟲相關函數:

def get_html_text(url): #解決第一個問題
pass
def get_info_list(html): #解決第二個問題
pass
def print_info_list(info_list): #def download_info_list(info_list):
pass

接下來,就讓我們圍繞這兩個問題和三個函數,去看看Python是怎麼解決的。

示例代碼:列舉了6個實際的爬蟲例子(基本只用到上面三個函數)

淘寶商品:鏈接: pan.baidu.com/s/1JUm_V2 密碼: kwvw

大學排名信息:鏈接: pan.baidu.com/s/1qzzOux 密碼: qenn

豆瓣電影Top:鏈接: pan.baidu.com/s/18cbIPm 密碼: 92ep

Github demo:鏈接: pan.baidu.com/s/1e9WCk6 密碼: eprg

股票信息:鏈接: pan.baidu.com/s/1XzGOJ5 密碼: vk5y

知乎圖片:鏈接: pan.baidu.com/s/1U2JOz5 密碼: cgpv

requests獲取html:

我們想要的資源,比如文字、圖片等,其實都在html裡面。一個網頁的url,對應一個html,我們可以通過requests庫,輕鬆地和伺服器上的url建立連接,得到html信息。通過Response對象的status_code、text、encoding、content等方法,查看這次連接的情況如何。

def get_html_text(url):
try:
r = requests.get(url, timeout=30)
r.raise_for_status
r.encoding = r.apparent_encoding
return r.text
except:
return "requests error"

但是,該函數返回的是一個str類型的html,這是非常不方便我們獲取信息的

BeautifulSoup解析html:

html頁面得到了,我們的爬蟲就完成了一半了。。。哈哈,開玩笑的,其實爬蟲最難的地方就在定位信息,特別是定位大量信息的時候。不過不著急,BeautifulSoup很好地幫我們解決了這個問題。它可以解析我們通過requests獲得的str類型的html,使其成為一個真正的html,我們可以通過標籤的屬性或名稱去定位標籤,可以定位標籤之後,獲取信息就方便多了。

def get_info_list(html):
"""
獲取目標圖片的url鏈接
"""
soup = BeautifulSoup(html,"html.parser")
img_tags = soup.find_all("noscript")
img_urls = []
for tag in img_tags:
try:
img_urls.append(re.findall(rsrc=".*?",tag.get_text())[0][5:-1])
except:
continue
return img_urls

在上面的代碼中,除了用標籤名字定位標籤外,還使用了正則表達式來輔助我們找到想要的信息。上圖可以看出,圖片url在src屬性上,可以愉快地下載小姐姐的美照了。

值得注意的是,定位標籤是網路爬蟲中很重要的一件事,我給出的幾個爬蟲demo中都有體現。通過要找的信息,到跟信息相關的標籤,再到標籤之間的邏輯關係,都值得我們仔細思考。選取哪個標籤,才能通過一次遍歷就可以得到我們想要的所有的信息,而且還沒有冗餘信息呢?

再舉一個例子說明這個問題

def get_info_list(html):
ulist = []
soup = BeautifulSoup(html,html.parser)
for tr in soup.find(tbody).children:
if isinstance(tr,bs4.element.Tag):
tds = tr.find_all(td)
ulist.append([tds[0].string,tds[1].string,tds[2].string])
return ulist

這個例子是爬取中國大學的排名信息,從圖中可以看出所有大學的信息都在tbody一個標籤里,而tbody有好多子標籤tr,每一個tr存儲的是一個學校的各種信息,那麼邏輯就很清楚了,只要遍歷tbody的每一個子標籤tr,就可以通過一個循環,得到我們想要的所有信息了。

print or download?

接下來的事就比較簡單了,數據量較少可以選擇列印出來,數據如果是圖片等二進位文件可以選擇下載到本地

def print_info_list(ulist,num):
tplt = {0:^10} {1:{3}^10} {2:^10}
print(tplt.format(排名,學校名稱,省份,chr(12288)))
for i in range(num):
u = ulist[i]
print(tplt.format(u[0],u[1],u[2],chr(12288)))

def download_imgs(img_urls):
start_name = 0
root = "./images001/"
for url in img_urls:
if not os.path.exists(root):
os.mkdir(root)
path = root + str(start_name) + ".jpg"
r = requests.get(url)
with open(path, "wb") as f:
f.write(r.content)
start_name += 1

進階:

在爬取Github Python Trending和知乎圖片的時候,涉及到幾個有趣的問題:

(1)在爬取到一個url的時候,我們可以通過python命令的方式打開這個鏈接,而不需要手動打開,是不是很酷呢,通過webbrowser.open就可以實現。

(2)爬取網頁的時候,我們可能需要模擬滑鼠滑動的操作,來獲取更多信息,這個時候需要用到selenium,來自動運行JS腳本,完成滑鼠滑動的操作

展望:

(1)在與web伺服器連接的時候,公司肯定會設置很多障礙(robots協議等)。因為如果讓別人無限制爬蟲的話,對公司的網站是有很大影響的。在以後的學習里,反爬技巧和分散式爬蟲(框架如Scrapy等)是我們要研究的,從而可以更好更快的爬取想要的信息

(2)在與網頁的交互中,會涉及到大量的JS函數,要想爬蟲更加順利,對JS函數要很熟悉

(3)數據的存儲問題,數據量大的話,肯定要存在資料庫里里的

參考鏈接:

Python網路爬蟲與信息提取_北京理工大學_中國大學MOOC(慕課)

github.com/huntingzhu/w

總結:

作為一個正在找實習的生物狗,寫這篇文章只是為了對上周的學習做一個總結,主要是理一下思路,包括程序設計方法(自頂向下設計,自底向上實現)。

推薦閱讀:

TAG:Python入門 | Python開發 | python爬蟲 |