之前我們已經詳細討論了如何使用BeautifulSoup這個強大的工具來解析HTML頁面,另外還介紹了利用在線工具來抓取HTTP請求以獲取數據的方法。在今天的學習中,我們將繼續(xù)探討另一種常見的網絡爬蟲技巧:XPath。XPath是一種用于定位和選擇XML文檔中特定部分的語言,雖然它最初是為XML設計的,但同樣適用于HTML文檔的解析。
HTML和XML有很多相似之處,比如標簽、屬性等,因此XPath同樣可以在HTML文檔中有效地定位元素。爬蟲可以利用XPath表達式來指定需要提取的數據的位置,然后通過XPath解析器來解析HTML文檔,從而提取所需的信息。
好的,我們不多說,直接開始今天的任務,爬取36kr的熱榜新聞以及新聞搜索。
XPath爬蟲
如果對XPath不熟悉也沒關系,可以直接使用它,就能發(fā)現它與我們之前使用的BeautifulSoup有著相同的目的。只是在表達式和方法的使用上略有不同。在進行爬蟲之前,我們可以先下載一個XPath工具。之前我們編寫B(tài)eautifulSoup代碼時,需要自行查找HTML代碼中的標簽并編寫代碼進行解析,這樣很費眼。而在瀏覽器中可以使用插件工具來直接提取XPath元素。
XPath插件
有很多瀏覽器插件可供選擇,我們只需直接獲取一個即可。最重要的是,這些插件可以讓我們在選擇時輕松復制表達式,就像這樣:
當我打開插件工具后,立即觸發(fā)左鍵操作,從而開始顯示紅色框框,用戶選擇后,系統(tǒng)會呈現一系列XPath表達式供選擇,用戶只需選取適當的表達式即可。
熱榜新聞
會使用工具后,我們將繼續(xù)進行數據爬取和頁面信息解析。在此之前,需要安裝一個新的依賴庫lxml。以下是一個示例代碼供參考:
from lxml import etree
import requests
hot_article_list = []
headers = {
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36"
}
def get_hot_article():
url = 'https://36kr.com/hot-list/catalog'
response = requests.get(url=url,headers=headers)
# 獲取的html內容是字節(jié),將其轉化為字符串
#使用etree進行解析
data = etree.HTML(response.text)
# 使用XPath定位元素
# 提取a標簽的article-item-title文本數據以及url連接
article_titles = data.xpath("(//a[@class='article-item-title weight-bold'])")
article_desc = data.xpath("(//a[@class='article-item-description ellipsis-2'])")
if len(article_titles) == len(article_desc):
for article, desc in zip(article_titles, article_desc):
# 獲取元素的鏈接(href 屬性)
link = article.get('href')
# 獲取元素的文本內容
title = article.text
desc = desc.text
hot_article_list.append({
"title":title,
"link":link,
"desc":desc
})
else:
print("未找到指定元素")
print(hot_article_list)
這段代碼的功能是從36氪網站的熱門文章列表中提取文章的標題、鏈接和描述信息,并將這些信息存儲在一個列表中。其中,lxml庫用于HTML解析,requests庫用于發(fā)送HTTP請求。接著,定義了一個空列表hot_article_list,用于存儲提取的文章信息。
踩個小坑
在前面已經成功提取了熱門文章標題和鏈接,接下來通常應該開始逐個訪問這些鏈接以查看新聞詳情。然而,在發(fā)送請求獲取單個URL鏈接時,卻未能獲得預期的新聞信息,出現了以下情況:
通常情況下,網頁中的數據要么直接包含在靜態(tài)HTML中,比如之前我們解析的美食菜譜等;要么是通過Ajax的HTTP請求獲取的,比如我們嘗試獲取騰訊云社區(qū)的文章列表。通常,這些數據都可以在搜索中找到相應的匹配項。然而,我花了一個小時的時間仍未能成功獲取所需信息。最初,我懷疑可能是因為網頁中存在跳轉頁面?zhèn)鬏敂祿?,因此我特意使用抓包工具進行了下載,但令人失望的是,并沒有發(fā)現相關數據。
因此,我又仔細檢查了一遍靜態(tài)HTML代碼,并在代碼末尾發(fā)現了一個奇怪之處——HTML頁面的部分竟然被加密了。讓我們來看看這段代碼吧。
如果你對這些內容感到疑惑,建議再次在搜索框中輸入相關關鍵字以查找更多信息。很可能存在解密函數。果然如此。我們接下來看下。
既然官方對數據進行了加密處理,顯然是出于一定的考慮,其中可能包括對爬蟲的防護等因素。鑒于此,我決定不再嘗試對其進行解密操作,這個就這樣吧。
信息搜索
36氪網站不僅提供了熱門文章信息,還支持新聞搜索功能。讓我們深入探討一下搜索功能的實現方式。通常情況下,靜態(tài)頁面即可滿足需求進行信息提取。但若希望獲取更多數據,就需要通過發(fā)送ajax請求來實現。
接著看代碼:
from lxml import etree
from urllib.parse import quote
import requests
def get_article_search(keyword):
qk = quote(keyword)
url = f'https://36kr.com/search/articles/{qk}'
response = requests.get(url=url,headers=headers)
# 獲取的html內容是字節(jié),將其轉化為字符串
#使用etree進行解析
data = etree.HTML(response.text)
# 使用XPath定位元素
# 提取a標簽的article-item-title文本數據以及url連接
article_detail = data.xpath("(//p[@class='title-wrapper ellipsis-2']//a)")
for a_tag in article_detail:
text = a_tag.xpath("string()").strip()
url = a_tag.get("href")
print("文本:", text)
print("URL連接:", url)
def get_article_url(keyword):
headers = {
'Accept': '*/*',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
'Connection': 'keep-alive',
'Content-Type': 'application/json',
'Cookie': 'Hm_lvt_713123c60a0e86982326bae1a51083e1=1710743069; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2218b40a4b8576e0-0508814adc1724-745d5774-2073600-18b40a4b858109a%22%2C%22%24device_id%22%3A%2218b40a4b8576e0-0508814adc1724-745d5774-2073600-18b40a4b858109a%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_referrer%22%3A%22%22%2C%22%24latest_referrer_host%22%3A%22%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%7D%7D; Hm_lvt_1684191ccae0314c6254306a8333d090=1710743069; aliyungf_tc=9f944307bb330cb7a00e123533aad0ee8a0e932e77510b0782e3ea63cddc99cf; Hm_lpvt_713123c60a0e86982326bae1a51083e1=1710750569; Hm_lpvt_1684191ccae0314c6254306a8333d090=1710750569',
'Origin': 'https://36kr.com',
'Referer': 'https://36kr.com/',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-site',
'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',
'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"',
}
json_data = {
'partner_id': 'web',
'timestamp': 1710751467467,
'param': {
'searchType': 'article',
'searchWord': keyword,
'sort': 'score',
'pageSize': 20,
'pageEvent': 1,
'pageCallback': 'eyJmaXJzdElkIjo5NSwibGFzdElkIjo1MSwiZmlyc3RDcmVhdGVUaW1lIjo3NTU4MSwibGFzdENyZWF0ZVRpbWUiOjIzOTk3LCJsYXN0UGFyYW0iOiJ7XCJwcmVQYWdlXCI6MSxcIm5leHRQYWdlXCI6MixcInBhZ2VOb1wiOjEsXCJwYWdlU2l6ZVwiOjIwLFwidG90YWxQYWdlXCI6MTAsXCJ0b3RhbENvdW50XCI6MjAwfSJ9',
'siteId': 1,
'platformId': 2,
},
}
response = requests.post(
'https://gateway.36kr.com/api/mis/nav/search/resultbytype',
headers=headers,
json=json_data,
)
data = response.json()
for parsed_data in data['data']['itemList']:
widget_title = parsed_data['widgetTitle'].replace('<em>', '').replace('</em>', '')
print(widget_title)
widget_url = parsed_data['route']
print(widget_url)
get_article_search('OpenAI')
get_article_url('我要')
get_article_search
和 get_article_url
。這兩個函數都是用來從36氪網站上獲取文章信息的。
-
get_article_search(keyword)
:- 首先,將關鍵詞進行URL編碼。
- 構建搜索URL并發(fā)送GET請求獲取頁面內容。
- 使用lxml庫的etree模塊解析HTML內容。
- 使用XPath定位元素,提取文章標題和URL連接。
-
get_article_url(keyword)
:- 函數中定義了請求頭(headers)和請求體(json_data)。
- 發(fā)送POST請求到指定的API接口獲取文章URL數據。
- 解析返回的JSON數據,提取文章標題和URL連接。
總結
在這篇文章中,我們深入學習了XPath作為一種常見的網絡爬蟲技巧。XPath是一種用于定位和選擇XML文檔中特定部分的語言,盡管最初是為XML設計的,但同樣適用于HTML文檔的解析。我們探討了如何使用XPath來定位元素并提取所需信息。文章來源:http://www.zghlxwxcb.cn/news/detail-841981.html
通過這篇文章的學習,我們對XPath的應用有了更深入的了解,也提升了我們在網絡爬蟲領域的技能。繼續(xù)努力學習和實踐,相信我們可以在爬蟲技術上取得更大的進步!文章來源地址http://www.zghlxwxcb.cn/news/detail-841981.html
到了這里,關于爬蟲實戰(zhàn):探索XPath爬蟲技巧之熱榜新聞的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!