在過去的實踐中,我們通常透過爬取HTML網頁來解析並提取所需資料,然而這只是一種方法。另一種更為直接的方式是透過傳送HTTP請求來獲取資料。考慮到大多數常見服務商的資料都是透過HTTP介面封裝的,因此我們今天的討論主題是如何透過呼叫介面來獲取所需資料。
目前來看,大多數的http介面資料都採用restful風格,通常使用JSON格式來傳送和接收資料。對於那些對此不太瞭解的零基礎學者,建議先學習相關知識點。在本章學習過程中,我們將主要以騰訊雲開發者社群作為主要平臺,練習爬取介面資料。
介面爬取
介面爬取並不複雜,首先需要在瀏覽器中開啟騰訊雲社群的網頁,然後按下F12開啟控制檯,接著瀏覽控制檯中的請求資料介面,有些介面可能一眼難以識別,但通常可以跳過細緻檢視,因為在開發過程中,最關鍵的是能從名稱中直觀理解其作用,大型公司通常設計得相當清晰。我們首先嚐試爬取主頁的活動資料。
我們可以選擇使用XHR來單獨檢視請求,這樣就能排除掉頁面、js、css等無關的請求,逐個檢查介面,找到我們需要的內容。這個特定介面就是我們必須記住的,其他的都是多餘的。
便利工具
在這裡,我們想向大家介紹一個非常實用的開發爬蟲工具,它就是https://curlconverter.com/
我是透過偶然的機會發現了這個工具的,它的確大大提升了我的爬蟲效率。通常情況下,當我們找到了需要爬取的介面時,我們需要編寫Python程式碼來發起請求,可能還要處理各種請求頭和cookie,這一過程會消耗大量時間。而這個工具則幫助我們省去了這些繁瑣的步驟,使得整個過程變得更加高效。
首先,我們在後臺查詢到目標請求,然後透過右鍵點選複製該請求。以Edge瀏覽器為例,具體操作如下所示:
在將內容複製後,我們可以直接前往這個線上工具網站,將其貼上進去,從而生成相應的Python程式碼。這裡以使用requests庫為例進行演示。當你瀏覽該網站時,你可以選擇你喜歡的任何程式語言進行相應程式碼的生成。
我們只需簡單地將其複製貼上到IDE中,然後便可直接執行程式碼。
社群首頁
一旦我們掌握了這種方法,基本上就可以獲取想要爬取的所有資料,只要避免頻繁請求而被識別為機器人爬蟲。讓我們首先嚐試爬取社群首頁的文章,以瞭解今年哪些類別的文章備受關注。以下是示例程式碼:
import datetime
import requests
ad_list = []
article_list = []
article_total = 0
def get_article_list(pageNumber):
global article_total,article_list
## 這裡不需要cookie也是可以的。
headers = {
'authority': 'cloud.tencent.com',
'accept': 'application/json, text/plain, */*',
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
'content-type': 'application/json',
'cookie': 'qcloud_uid=3db7bb7a1663470df3290f692c4a7206; language=zh; lastLoginIdentity=e382a0dd45ecf7f063e05751e7321e14; _ga_6WSZ0YS5ZQ=GS1.1.1685003902.1.1.1685004114.0.0.0; loginType=email; _ga_7PG2H0XLX2=GS1.2.1705284469.2.1.1705284470.59.0.0; lastLoginType=email; _gcl_au=1.1.315225951.1705902067; _ga_95GG3X2GMT=GS1.1.1707206895.14.0.1707212112.0.0.0; _ga=GA1.2.100014169188; mfaRMId=0092627a989e3ef79957c2257ea910f8; qcloud_from=qcloud.google.seo-1709083904498; qcstats_seo_keywords=%E5%93%81%E7%89%8C%E8%AF%8D-%E5%93%81%E7%89%8C%E8%AF%8D-%E8%85%BE%E8%AE%AF%E4%BA%91; from_column=20421; cpskey=1f39dac98ac4cc96c6503bdb4f49994f; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%22100014169188%22%2C%22first_id%22%3A%221878e0e485111b-0be585a75d9ef-7e57547d-2073600-1878e0e4852ec0%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_utm_medium%22%3A%22ocpc%22%7D%2C%22identities%22%3A%22eyIkaWRlbnRpdHlfY29va2llX2lkIjoiMTg3OGUwZTQ4NTExMWItMGJlNTg1YTc1ZDllZi03ZTU3NTQ3ZC0yMDczNjAwLTE4NzhlMGU0ODUyZWMwIiwiJGlkZW50aXR5X2xvZ2luX2lkIjoiMTAwMDE0MTY5MTg4In0%3D%22%2C%22history_login_id%22%3A%7B%22name%22%3A%22%24identity_login_id%22%2C%22value%22%3A%22100014169188%22%7D%2C%22%24device_id%22%3A%221878e0e485111b-0be585a75d9ef-7e57547d-2073600-1878e0e4852ec0%22%7D; qcmainCSRFToken=NSsz_8Bfx1S_; qcloud_visitId=3e799aa8be55222ade40e7ab9b8be875; intl=; _gat=1; trafficParams=***%24%3Btimestamp%3D1710467373372%3Bfrom_type%3Dserver%3Btrack%3Da7699f0f-3309-4c6b-9740-475f6c5f11ba%3B%24***',
'origin': 'https://cloud.tencent.com',
'referer': 'https://cloud.tencent.com/developer',
'sec-ch-ua': '"Chromium";v="122", "Not(A:Brand";v="24", "Microsoft Edge";v="122"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-origin',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0',
}
json_data = {
'pageNumber': pageNumber,
'pageSize': 100,
'type': 'recommend', ## 文章是否被推薦到首頁
}
response = requests.post(
'https://cloud.tencent.com/developer/api/home/article-list',
headers=headers,
json=json_data,
)
news_list = response.json()
for article in news_list['list']:
## 處理一下文章的類別
handle_tag(article)
## 可以自己解析首頁的文章,只拿你想要的
article_list.append({
"article_title": article['title'],
"article_date": article['createTime'],
"article_summary": article['summary']
})
article_total = news_list['total']
fixed_time = datetime.datetime(2023, 1, 1)
timestamp = int(fixed_time.timestamp())
print(f'{article_list[-1]["article_date"]}和{timestamp}')
## 判斷一下是否已經是最後一頁
return 0 if article_list[-1]['article_date'] < timestamp else 1
def handle_tag(article):
# 遍歷解析後的資料,統計每個tagName的資料量
for item in article['tags']:
tag_name = item["tagName"]
if tag_name in tag_counts:
tag_counts[tag_name] += 1
else:
tag_counts[tag_name] = 1
def get_top_10():
# 根據資料量對tagName進行排序
sorted_tag_counts = sorted(tag_counts.items(), key=lambda x: x[1], reverse=True)
# 取前10個tagName
top_10_tags = sorted_tag_counts[:10]
# 列印前10個tagName的資料量統計
for tag, count in top_10_tags:
print(f"{tag}: {count}")
page_num = 1
while True:
num = get_article_list(page_num)
page_num = page_num + 1
if num == 0:
break
get_top_10()
程式碼首先透過API獲取文章列表資料,然後遍歷每篇文章的標籤資訊,統計每個標籤出現的次數,最後輸出每個標籤和其對應的資料量。這樣可以幫助使用者瞭解哪些標籤在文章中出現頻率較高。除了這些,我還額外處理輪播活動的資料,獲取更全面的活動資訊。
import datetime
import requests
ad_list = []
def get_ads():
global ad_list
headers = {
'authority': 'cloud.tencent.com',
'accept': 'application/json, text/plain, */*',
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
'content-type': 'application/json',
'origin': 'https://cloud.tencent.com',
'referer': 'https://cloud.tencent.com/developer',
'sec-ch-ua': '"Chromium";v="122", "Not(A:Brand";v="24", "Microsoft Edge";v="122"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-origin',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0',
}
json_data = {
'cate': 'cloud_banner',
'preview': False
}
response = requests.post('https://cloud.tencent.com/developer/api/common/getAds', headers=headers, json=json_data)
news_list = response.json()
ad_list = [{'pcTitle': item['content']['pcTitle'], 'url': item['content']['url']} for item in news_list['list']]
get_ads()
print(ad_list)
我的文章
如果我們希望對我們自己的文章進行分析和處理,首先需要進行登入。原本我打算嘗試透過編寫程式碼實現免登入,但是仔細研究後臺 JavaScript 和登入驗證後發現實現起來涉及的內容過多,對我們這樣以學習為主的學者來說並不適合。
確保我已經登入的標識是透過 cookie 實現的。Cookie 在這裡的作用是保持使用者登入狀態,使使用者在不同頁面之間保持登入狀態。由於 HTTP 是無狀態的,需要一種方法來保持會話連線,而這種方法就是使用 Cookie。對於請求來說,Cookie 就是一串字串,伺服器會自動解析它,無需我們手動管理。因此,我只需在網頁登入後使用工具複製貼上 Cookie 即可。儘管我花費了一整天,但仍未成功編寫程式碼實現登入並獲取 Cookie。因此,我們最好選擇最簡單的方法。
示例程式碼如下:
import requests
def get_my_article(page_num):
headers = {
'authority': 'cloud.tencent.com',
'accept': 'application/json, text/plain, */*',
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
'content-type': 'application/json',
'cookie': '',# 這裡需要復貼上你自己的cookie。
'origin': 'https://cloud.tencent.com',
'referer': 'https://cloud.tencent.com/developer/creator/article',
'sec-ch-ua': '"Chromium";v="122", "Not(A:Brand";v="24", "Microsoft Edge";v="122"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-origin',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0',
}
page_size = 20
json_data = {
'hostStatus': 0,
'sortType': 'create',
'page': page_num,
'pagesize': page_size,
}
response = requests.post(
'https://cloud.tencent.com/developer/api/creator/articleList',
headers=headers,
json=json_data,
)
news_list = response.json()
for article in news_list['list']:
# handle_tag(article)
# 這裡我就不解析了,簡單列印一下吧。
my_article_list.append({
"article_title": article['title'],
"article_date": article['createTime'],
"article_summary": article['summary']
})
article_total = news_list['total']
if page_num*page_size > article_total:
return 0
else:
return 1
在這個函式中,引數page_num代表著要獲取的文章列表頁數。請務必留意,請求頭中的headers需要包含使用者自行提供的Cookie資訊,這樣才能確保程式正常執行。您可以在這裡獲取到Cookie資訊,只需將其複製貼上即可。詳見下圖:
總結
在過去的實踐中,我們常常透過爬取HTML網頁來解析和提取資料,因此今天我們討論瞭如何透過呼叫介面來獲取所需資料。本文透過示例程式碼展示瞭如何爬取社群首頁的文章和活動資料,以及如何爬取自己的文章列表。透過這些實踐,我們可以更好地理解和運用介面爬取技術。