Python爬蟲實戰系列1:部落格園cnblogs熱門新聞採集

Python魔法师發表於2024-03-13

實戰案例:部落格園熱門新聞採集

一、分析頁面

開啟部落格園網址https://www.cnblogs.com/,點選【新聞】再點選【本週】

今日新聞.png

本次採集,我們以頁面新聞標題為案例來採集。這裡可以看到標題“ 李彥宏:以後不會存在“程式設計師”這種職業了”。

1.1、分析請求

F12開啟開發者模式,然後點選Network後點選任意一個請求,Ctrl+F開啟搜尋,輸入標題李彥宏:以後不會存在“程式設計師”這種職業了 ,開始搜尋

請求分析.png

可以看到請求地址為https://news.cnblogs.com/n/digg?type=week 但是返回的內容不是json格式,而是html原始碼,說明該頁面是部落格園後端拼接html原始碼返回給前端的,這裡我們就不能簡單的直接透過API介面來獲取資料了,還需要對html原始碼進行解析。

1.2、分析頁面

點選檢視元素,然後點選新聞標題。

頁面原始碼.png

對應的html原始碼是<a href="/n/766062/" target="_blank">李彥宏:以後不會存在“程式設計師”這種職業了</a>

透過原始碼我們可以看出,標題是被一個id=news_list的div包裹,然後news_div下還有news_block這個div包裹,然後是逐級向下,一直到a標籤才是我們想要的資料。

標題原始碼分析.png

1.3、分頁資訊處理

分頁資訊.png

透過頁面分析,可以看到分頁很簡單,直接在Query String QueryParamters裡傳入type: week、page: 2兩個引數即可。

1.4、判斷反爬及cookie

如何判斷該請求需要哪些header和cookie引數?或者有沒有反爬策略

copy_curl.png

首先複製curl,在另一臺機器上執行,curl程式碼如下

curl程式碼.png

透過逐步刪除程式碼中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()

程式執行效果.png

完整程式碼

# -*- 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魔法~

qrcode.jpg

相關文章