Python 之用 BeautifulSoup 爬取網頁簡單示例

之前用於 Python 爬過一些網頁,都寫在程序裏一直沒有整理,最近工作上要用到一些新聞,爬取百度新聞的一些信息,於是將用 BeautifulSoup 爬取網頁的一些步驟整理下。

目的

爬取百度體育新聞的幾個板塊信息,如NBA新聞,國內足球,國際足球等,鏈接是 http://news.baidu.com/sports。

分析

我用的是 Chrome 瀏覽器,按 F12 打開頁面的請求,可以發現該頁面的 NBA 新聞是鏈接一打開就獲取的,剩下的幾個板塊則是後來通過接口請求後填充的。
在這裏插入圖片描述

步驟

1、使用 Python 的 requests 模塊請求頁面信息,獲取 NBA 新聞
2、通過接口請求其他幾個板塊的信息

之前學習爬蟲技術的時候,使用的是 Python 最原始的 urllib 庫,後來推出了 requests 庫,將 urllib 庫的功能集成了。
可以直接使用 requests 的幾個方法進行數據的獲取,我寫後面做接口測試自己使用 requests 的幾個方法進行測試。

1 請求頁面數據
通過查看網頁源代碼,定位到 NBA 新聞的位置,發現其信息都位於一個 class 爲 ulist 的 ul 下面,然後我們可以定位到該地方,以下是代碼演示。

import requests
from bs4 import BeautifulSoup
response = requests.get('http://news.baidu.com/sports')
#將網頁內容作爲 html 信息進行解析
resp = BeautifulSoup(response.text, "html.parser")

注意:
1)response.text 內容是字符串,而 response.content 是二進制數據,當我們爬取圖片時 使用 response.content 進行保存
2)如果爬取的網頁打印出來是亂碼,可以通過如下代碼來指定編碼

 response.encoding = 'utf-8'

經過 BeautifulSoup 將網頁內容處理以後,如果整個打印出來,可以看到內容都按照 HTML 有縮進的方式展現出來。
我們之前通過查看網頁源代碼找到 新聞的展現地址都在一個 class 爲 ulist 的 ul 下面:
在這裏插入圖片描述
然後我們可以使用 findAll() 函數進行選擇。
在這裏 有兩個用於尋找的函數,一個是 find() 函數,一個是 findAll() 函數。
前者 find() 函數的功能是找到一個符合搜索條件的就停止搜索,返回單個內容,
findAll() 返回的是頁面所有符合搜索條件的內容,相當於是一個 所有 find() 內容的列表,即使只找到一個內容,也是元素爲一的列表。
這兩者相當於:

find() = findAll()[0]

尋找到NBA 新聞的代碼如下:

uls = resp.findAll("ul", attrs = {"class": "ulist"})

以上的意思是,在 resp 中找到所有 class 屬性值爲 ulist 的 ul 標籤。
返回的是一個列表。
通過查看,一共返回了四個 ul 標籤,我們要尋找的 NBA 新聞爲後兩個。

uls = uls[2:]

對於 ul 下每一個 li 標籤,我們需要獲取 li 標籤的標題和網頁鏈接,方法如下:

for ul in uls:
	for li in ul.findAll('li'):
		title = li.text
		href = li.find('a')['href']

通過這種方法就獲取到了 NBA 新聞的標題以及網頁的連接。

2、接口獲取數據
因爲還要採集 CBA 新聞,足球等板塊信息,通過觀察頁面,可以知道這幾個板塊的信息都是通過接口的方式請求之後進行填充的。
請求的 url 是:

http://news.baidu.com/widget?id=CbaNews&channel=sports&t=1572713532837

可以知道這是一個 get 請求,參數有三個, id, channel 以及 t。
其中, id 是定義新聞的類別,幾個接口都是固定的,可以直接獲取,
channel 是sports ,表明是體育新聞,在這個頁面上是不變的,
t 是一個時間戳,之前和前端合作的時候,加上時間戳作用一般是防止瀏覽器取緩存信息,可以不傳。

    news_params_list = [
            {"id":"WorldSoccerNews", "channel":"sports"}, 
            {"id":"ChinaSoccerNews", "channel":"sports"},   
            {"id":"CbaNews", "channel":"sports"},          
            {"id":"OtherNews", "channel":"sports"},         
            {"id":"LatestNews", "channel":"sports"},       
        ]

通過遍歷上述的參數連接,將其挨個添加到請求鏈接的後面,就可以通過接口獲取相應的信息。
Python 裏有個庫是用來將字典整合到鏈接的後面,這樣我們就不用手動去拼湊鏈接:

import urllib
params = {"id":"WorldSoccerNews", "channel":"sports"}
url = 'http://news.baidu.com/widget'
suffix = urllib.parse.urlencode(params)
print(suffix)
# id=WorldSoccerNews&channel=sports
resq_url = url + '?' + suffix 
response = requests.get(resp_url)

其實之前是可以直接使用 requests.get(url, params) 這種方式的,不用自己拼湊鏈接,但是忘了 python3.4 還是 python3.6 裏面,好像不支持這個方法了,我也沒有再驗證,但以上代碼是確保可以使用的。

通過請求以上鍊接,打印出返回的內容,如下:

在這裏插入圖片描述
也是一串 HTML 代碼,使用 BeautifulSoup 解析的方法同上,就可以獲取其他版塊的新聞信息了。

然後可以寫一個存儲的函數,將採集的信息存儲到文件,或者 MySQL 數據庫都行。

關於爬蟲我有幾點想要說的,

一、爬蟲的意義,只是使用代碼獲取數據的一種方式。
二、爬蟲的基礎知識,我覺得要學習這種方式最好還是學習一點前端的知識,比如頁面的組成,HTML,CSS,JS。最起碼HTML的相關標籤要了解。
三、爬取數據的方式,就示例來說,爬取數據的方式要麼就是直接 requests.get 方法獲取網頁的所有數據,要麼是通過接口向頁面填充。
四、頁面的 Python 解析庫不只 BeautifulSoup 這一個,還有其他如 xpath 等,但我習慣用這個,我覺得使用起來蠻順手的。
五、我提供的這個示例只是一個最簡單的無需登錄,無需驗證,無需使用其他模擬 JS 請求的一個例子,其他的還有更復雜的方法可以學習一下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章