本博客帶大家一起寫一個網絡爬蟲,主要是爬取一個新聞網站的新聞列表,在項目正式開始之前,需要補充兩個知識點,分別是如何通過Python訪問網絡和如果通過Python解析JSON
1、前提知識點:
1.1、Python如何訪問網絡
Python公告urllib來訪問網絡
import urllib.request #導入模塊
url = "https://www.baidu.com" #設置url地址
param = {} #設置參數,參數是字典
param = urllib.parse.urlencode(param).encode('utf_8') #將參數以utf-8編碼方式來編碼
req = urllib.request.Request(url, param)
#設置header的User-Agent屬性,模擬該請求是由狐火瀏覽器發送的,也就是說欺騙服務器是人爲發送的並未程序發送的
req.add_header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:53.0) Gecko/20100101 Firefox/53.0")
response = urllib.request.urlopen(req) #訪問網絡
html = response.read() #讀取響應的結果
result = html.decode("utf-8") #按照utf-8編碼來進行解碼
print(result) #輸出
運行結果:
1.2、如何解析JSON
import json #導入模塊
temp = "{\"name\":\"張三\", \"age\":18}" #定義一個JSON
target = json.loads(temp) #解析JSON
print(type(target)) #獲取解析後的類型
print(target)
運行結果:
2、爬蟲項目開始
如圖,爬蟲要爬取數據的網站是一個用HTML5製作的手機網站
2.1、需求說明
如上圖,通過網絡爬蟲爬取網站的新聞列表數據,並且將新聞的標題輸出在控制檯
2.2、需求分解
1、通過Python訪問網址獲取網站響應的數據
2、判斷網站響應的數據,本網站的數據傳輸方式是JSON
3、通過Python解析JSON,將解析好的數據輸出到控制檯
2.3、實現步驟(本博文使用的是Mac版的火狐瀏覽器,其實大部分的瀏覽器都是大同小異的)
- 1、使用火狐瀏覽器訪問網站地址:http://121.42.8.95:8090/EasyApp/HuiEdu/html/index_m.html
- 2、在網頁上單擊右鍵,選擇“檢查元素”,如下圖
- 3、點擊NetWork(網絡)找到請求狀態爲200的鏈接,查看Response(響應)是否是我們要爬取的數據,如下圖
- 4、點擊Header可以獲取該鏈接的詳細地址,點擊Params可以獲取訪問該鏈接所需要傳遞的參數,如下圖
- 5、到此,我們所需要的所有前期數據就都準備OK了,接下來按照上面的需求分解進行詳細的代碼實現
2.4、實現
import urllib.request #導入網絡請求模塊
import json #導入JSON解析模塊
url = "http://121.42.8.95:8090/EasyApp/app/mobile/article/list.action" #瀏覽器獲取的鏈接地址
data = {} #瀏覽器獲取的訪問該地址需要傳遞的參數
data['cid'] = "huihai.xuexifangfa"
data['start'] = "0"
data['size'] = "15"
data = urllib.parse.urlencode(data).encode('utf_8') #以utf8的編碼格式進行編碼參數
response = urllib.request.urlopen(url, data) #訪問網絡
html = response.read().decode("utf-8") #將響應的數據按照utf8的編碼格式進行解碼
# print(html) #通過控制檯輸出,發現響應的結果是JSON格式
target = json.loads(html) #解析JSON
print(type(target)) #查看JSON解析後的數據類型是數組,也就是新聞列表
print(type(target[0])) #查看數組第一個元素髮現是字典,也就是每一條新聞
for arr in target: #循環獲取每一條新聞
print(arr['title']) #控制檯輸出新聞的標題
運行結果:
3、豐滿需求
3.1、需求說明
以上的實現雖然已經滿足了我們的需求,但是往往並不是客戶想要的,如果可以讓用戶輸入欄目名稱,爬取欄目下對應的文章,似乎更加的友好
3.2、需求分解
- 1、爬取所有欄目的數據
- 2、將爬取的欄目數據封裝到字典當中,用戶輸入字典的key即可獲取欄目下的文章列表
- 3、獲取文章列表的方式在上一個需求中已經實現了
3.3、需求實現
import urllib.request #導入網絡請求模塊
import json #導入JSON解析模塊
#爬取新聞列表的函數
def getArticles(cid): #將爬取新聞列表的代碼封裝成一個函數
url = "http://121.42.8.95:8090/EasyApp/app/mobile/article/list.action" #瀏覽器獲取的鏈接地址
data = {} #瀏覽器獲取的訪問該地址需要傳遞的參數
data['cid'] = cid
data['start'] = "0"
data['size'] = "15"
data = urllib.parse.urlencode(data).encode('utf_8') #以utf8的編碼格式進行編碼參數
response = urllib.request.urlopen(url, data) #訪問網絡
html = response.read().decode("utf-8") #將響應的數據按照utf8的編碼格式進行解碼
# print(html) #通過控制檯輸出,發現響應的結果是JSON格式
target = json.loads(html) #解析JSON
print(type(target)) #查看JSON解析後的數據類型是數組,也就是新聞列表
print(type(target[0])) #查看數組第一個元素髮現是字典,也就是每一條新聞
for arr in target: #循環獲取每一條新聞
print(arr['title']) #控制檯輸出新聞的標題
#爬取新聞欄目列表的函數
def getChannels():
url = "http://121.42.8.95:8090/EasyApp/app/mobile/channel/list.action" #瀏覽器獲取的鏈接地址
response = urllib.request.urlopen(url) #訪問網絡
html = response.read().decode("utf-8") #將響應的數據按照utf8的編碼格式進行解碼
# print(html) #通過控制檯輸出,發現響應的結果是JSON格式
target = json.loads(html) #解析JSON
print(type(target)) #查看JSON解析後的數據類型是數組,也就是欄目列表
dic = {} #定義一個用來映射欄目的字典
for i in range(0, len(target), 1): #通過一個for循環將所有欄目映射到字典中
dic[i] = target[i]
return dic #返回欄目字典
channels = getChannels()
print("爬取的欄目如下:")
for i in range(0, len(channels), 1): #輸出所有的欄目
print("%s=%s" %(i, channels[i]['name']))
x = int(input("請輸入要欄目來查詢欄目下的文章\n"))
getArticles(channels[x]['id']) #通過欄目ID爬取文章列表
運行結果: