註:文章原文為Dr. Charles Severance 的 《Python for Informatics》。文中代碼用3.4版改寫,併在本機測試通過。 12.9 辭彙表 BeautifulSoup: 一個用於分析HTML文檔,並從中抓取數據的Python庫。它彌補了大部分在瀏覽器中被忽略的HTM ...
註:文章原文為Dr. Charles Severance 的 《Python for Informatics》。文中代碼用3.4版改寫,併在本機測試通過。
12.9 辭彙表
BeautifulSoup: 一個用於分析HTML文檔,並從中抓取數據的Python庫。它彌補了大部分在瀏覽器中被忽略的HTML缺陷。你可以從www.crummy.com下載BeautifulSoup代碼。
port:埠。當你用套接字鏈接伺服器,通常表示正在聯繫的的伺服器應用程式的數字。例如,網頁服務使用80埠,電子郵件服務使用25埠。
scrape:一個程式偽裝成一個網頁瀏覽器,獲取一個頁面,然後查看網頁的內容。經常程式會跟隨一個頁面中鏈路去找到下個頁面,這樣它們可以穿越一個網頁網路或社交網路。
socket:套接字。兩個應用程式之間的網路連接。這樣程式可以雙向發送和接收數據。
spider:網路爬蟲。網頁搜索引擎通過獲取一個頁面和此頁面的所有鏈接,迴圈搜索至幾乎擁有互聯網所有頁面,並據此建立搜索索引的一種行為。
12.10 練習
以下練習代碼均為譯者編寫,僅供參考
練習 12.1 修改socket1.py,提示用戶輸入URL,使程式可以讀取任何網頁。你可以用split('/')方法分解URL的組成部門,使你可以抽取套接字連接調用的主機名。使用try和except語句添加錯誤校驗,處理用戶輸入不正確格式的或不存在的URL。
import socket import re url = input('Enter an URL like this: http://www.py4inf.com/code/socket1.py\n') if (re.search('^http://[a-zA-Z0-9]+\.[a-zA-Z0-9]+\.[a-zA-Z0-9]+/',url)): words = url.split('/') hostname = words[2] mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: mysocket.connect((hostname, 80)) # 註意是兩個圓括弧 except: print(hostname, ' is not a correct web server') exit mysocket.send(str.encode('GET ' + url + ' HTTP/1.0\n\n')) while True: data = mysocket.recv(1024).decode('utf-8') if (len(data) < 1): break print (data) mysocket.close() else: print("The URL that you input is bad format")
練習12.2 修改你的socket程式,使它具備對接收的字元進行計數的功能,併在顯示3000個字元後停機顯示。程式應該獲取整個文檔,對所有字元進行計數,併在文檔最後顯示字元數。
import socket import re url = input('Enter an URL like this: http://www.py4inf.com/code/socket1.py\n') if (re.search('^http://[a-zA-Z0-9]+\.[a-zA-Z0-9]+\.[a-zA-Z0-9]+/',url)): words = url.split('/') hostname = words[2] mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: mysocket.connect((hostname, 80)) # 註意是兩個圓括弧 except: print(hostname, ' is not a correct server') exit mysocket.send(str.encode('GET ' + url + ' HTTP/1.0\n\n')) count = 0 while True: data = mysocket.recv(3000).decode('utf-8') if (len(data) < 1): break count = count + len(data) if (count <= 3000): print (data) print("The total count of this web is", count) mysocket.close() else: print("The URL that you input is bad format")
練習12.3 使用urllib庫複製先前練習中的功能。(1)通過URL獲取文檔。(2)最多顯示3000個字元。(3)對整個文檔進行計數。不要擔心這個練習的文件頭,只需簡單顯示文檔內容的前3000個字元。
import urllib.request import re url = input('Enter an URL like this: http://www.py4inf.com/code/socket1.py\n') if (re.search('^http://[a-zA-Z0-9]+\.[a-zA-Z0-9]+\.[a-zA-Z0-9]+/',url)): try: web = urllib.request.urlopen(url) except: print(url, ' is not a valid url') exit counts = 0 while True: data = web.read(3000) if (len(data) < 1): break counts = counts + len(data) if (counts <= 3000): print (data.decode('utf-8')) print("The total counts of this web is", counts) else: print("The URL that you input is bad format")
練習12.4 修改urllinks.py程式,使它抽取和統計所獲取的HTML文檔中的段標簽(p),並顯示段標簽的數量。不需顯示段的內容,只是統計即可。分別在幾個小網頁和一些長網頁上測試你的程式。
from bs4 import BeautifulSoup import urllib.request url = input('Enter - ') html = urllib.request.urlopen(url).read() soup = BeautifulSoup(html,"html.parser") tags = soup('p') counts = 0 for tag in tags: counts = counts + 1 print('This web has ',counts, ' tags of p.')
練習12.5(高級)修改socket程式,使它只顯示文件頭和空行之後的數據。切記recv只接收字元(換行符及所有),而不是行。
import socket import re url = input('Enter an URL like this: http://www.py4inf.com/code/socket1.py\n') if (re.search('^http://[a-zA-Z0-9]+\.[a-zA-Z0-9]+\.[a-zA-Z0-9]+/',url)): words = url.split('/') hostname = words[2] mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: mysocket.connect((hostname, 80)) # 註意是兩個圓括弧 except: print(hostname, ' is not a correct server') exit mysocket.send(str.encode('GET ' + url + ' HTTP/1.0\n\n')) web = b'' while True: data = mysocket.recv(1024) if (len(data) < 1): break web = web + data mysocket.close() pos = web.find(b'\r\n\r\n') print(web[pos+4:].decode('utf-8')) else: print("The URL that you input is bad format")