實戰案例:部落格園熱門新聞採集
一、分析頁面
開啟部落格園網址https://www.cnblogs.com/,點選【新聞】再點選【本週】
本次採集,我們以頁面新聞標題為案例來採集。這裡可以看到標題“ 李彥宏:以後不會存在“程式設計師”這種職業了”。
1.1、分析請求
F12開啟開發者模式,然後點選Network後點選任意一個請求,Ctrl+F開啟搜尋,輸入標題李彥宏:以後不會存在“程式設計師”這種職業了
,開始搜尋
可以看到請求地址為https://news.cnblogs.com/n/digg?type=week
但是返回的內容不是json格式,而是html原始碼,說明該頁面是部落格園後端拼接html原始碼返回給前端的,這裡我們就不能簡單的直接透過API介面來獲取資料了,還需要對html原始碼進行解析。
1.2、分析頁面
點選檢視元素,然後點選新聞標題。
對應的html原始碼是<a href="/n/766062/" target="_blank">李彥宏:以後不會存在“程式設計師”這種職業了</a>
透過原始碼我們可以看出,標題是被一個id=news_list的div包裹,然後news_div下還有news_block這個div包裹,然後是逐級向下,一直到a標籤才是我們想要的資料。
1.3、分頁資訊處理
透過頁面分析,可以看到分頁很簡單,直接在Query String QueryParamters裡傳入type: week、page: 2兩個引數即可。
1.4、判斷反爬及cookie
如何判斷該請求需要哪些header和cookie引數?或者有沒有反爬策略
首先複製curl,在另一臺機器上執行,curl程式碼如下
透過逐步刪除程式碼中header引數來判斷哪些是必要的引數,首先把cookie引數刪除試試,發現可以獲取到結果。由此判斷,該網站沒有設定cookie請求機制。
那就很簡單了,直接發請求,解析html原始碼。
二、程式碼實現
新建Cnblogs類,並在init裡設定預設header引數
class Cnblogs:
def __init__(self):
self.headers = {
'authority': 'news.cnblogs.com',
'referer': 'https://news.cnblogs.com/n/digg?type=yesterday',
'user-agent': USERAGENT
}
新建獲取新聞get_news函式
def get_news(self):
result = []
for i in range(1, 4):
url = f'https://news.cnblogs.com/n/digg?type=today&page={i}'
content = requests.get(url)
html = etree.HTML(content.text)
news_list = html.xpath('//*[@id="news_list"]/div[@class="news_block"]')
for new in news_list:
title = new.xpath('div[@class="content"]/h2[@class="news_entry"]/a/text()')
push_date = new.xpath('div[@class="content"]/div[@class="entry_footer"]/span[@class="gray"]/text()')
result.append({
"news_title": str(title[0]),
"news_date": str(push_date[0]),
"source_en": spider_config['name_en'],
"source_cn": spider_config['name_cn'],
})
return result
程式碼主要使用了requests和lxml兩個庫來實現
測試執行
def main():
cnblogs = Cnblogs()
results = cnblogs.get_news()
print(results)
if __name__ == '__main__':
main()
完整程式碼
# -*- coding: utf-8 -*-
import os
import sys
import requests
from lxml import etree
opd = os.path.dirname
curr_path = opd(os.path.realpath(__file__))
proj_path = opd(opd(opd(curr_path)))
sys.path.insert(0, proj_path)
from app.utils.util_mysql import db
from app.utils.util_print import Print
from app.conf.conf_base import USERAGENT
spider_config = {
"name_en": "https://news.cnblogs.com",
"name_cn": "部落格園"
}
class Cnblogs:
def __init__(self):
self.headers = {
'authority': 'news.cnblogs.com',
'referer': 'https://news.cnblogs.com/n/digg?type=yesterday',
'user-agent': USERAGENT
}
def get_news(self):
result = []
for i in range(1, 4):
url = f'https://news.cnblogs.com/n/digg?type=week&page={i}'
content = requests.get(url)
html = etree.HTML(content.text)
news_list = html.xpath('//*[@id="news_list"]/div[@class="news_block"]')
for new in news_list:
title = new.xpath('div[@class="content"]/h2[@class="news_entry"]/a/text()')
push_date = new.xpath('div[@class="content"]/div[@class="entry_footer"]/span[@class="gray"]/text()')
result.append({
"news_title": str(title[0]),
"news_date": str(push_date[0]),
"source_en": spider_config['name_en'],
"source_cn": spider_config['name_cn'],
})
return result
def main():
cnblogs = Cnblogs()
results = cnblogs.get_news()
print(results)
if __name__ == '__main__':
main()
總結
透過以上程式碼,我們實現了採集部落格園的功能。
本文章程式碼只做學習交流使用,作者不負責任何由此引起的法律責任。
各位看官,如對你有幫助歡迎點贊,收藏,轉發,關注公眾號【Python魔法師】獲取更多Python魔法~