csdn

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 14, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package csdn is the library behind the csdn command line: the HTTP client, the open hot-rank board, the search and HTML surfaces, and the typed data models for CSDN (CSDN博客).

CSDN is open: every surface serves anonymously over plain HTTPS GET, with no request signing. The catch is an anti-bot edge that returns an HTTP 521 or an HTML challenge when a request lacks full browser headers, so the client sends a real desktop Chrome User-Agent, an Accept-Language, and a Referer on every request. When the edge still wins it serves a challenge shell; the client returns ErrWalled and the command layer reports it honestly instead of a silent empty result.

Index

Constants

View Source
const DefaultUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"

DefaultUserAgent is a current desktop Chrome string. An honest, real User-Agent is both polite and the thing most likely to keep a request from tripping the anti-bot edge, which scores non-browser callers.

View Source
const Host = "https://www.csdn.net"

Host is the CSDN front-page origin, the default Referer for HTML reads.

Variables

View Source
var ErrNotFound = errors.New("not found")

ErrNotFound means the call parsed but carried no record for the request, for example an article id or username that does not exist.

View Source
var ErrWalled = errors.New("CSDN served an anti-bot challenge (try again, or this surface needs a residential session)")

ErrWalled means the anti-bot edge served a challenge instead of the surface. The request needs a residential session (or a retry).

Functions

func BaseIdentity added in v0.1.1

func BaseIdentity() kit.Identity

BaseIdentity is the help and version identity shared by the standalone binary and any host that links the package.

func Defaults added in v0.1.1

func Defaults(c *kit.Config)

Defaults seeds the framework baseline from the csdn defaults, so an unset --rate/--retries/--timeout keeps the library's own pacing.

func MapErr added in v0.1.1

func MapErr(err error) error

MapErr converts a library error into the kit error kind that carries the right exit code, so a host renders the same walled and not-found outcomes the standalone binary does. An anti-bot challenge is exit 4, a missing record is exit 6.

func ParseArticleID added in v0.1.1

func ParseArticleID(in string) (string, error)

ParseArticleID reads just the numeric article id from a full url, the username/id shorthand, or a bare id. Unlike ParseArticleRef it accepts a bare id, because the surfaces keyed only by id (such as the comment list) do not need the author username.

func ParseArticleRef added in v0.1.1

func ParseArticleRef(in string) (username, id string, err error)

ParseArticleRef reads the author username and numeric id of an article from a full url (https://blog.csdn.net/{user}/article/details/{id}) or the shorthand username/123456. A bare numeric id is rejected: CSDN article urls carry the author username, so an id alone cannot be located.

func ParseUsername added in v0.1.1

func ParseUsername(in string) (string, error)

ParseUsername reads a CSDN username from a profile url (https://blog.csdn.net/{username}) or a bare token. Reserved path segments such as article or phoenix are rejected.

func Register added in v0.1.1

func Register(app *kit.App)

Register is the convenience a host or the binary calls without naming the zero-value Domain.

Types

type Article

type Article struct {
	ID        string   `json:"id" kit:"id"`
	Title     string   `json:"title" table:"title,truncate"`
	Author    string   `json:"author"`
	Username  string   `json:"username"`
	Summary   string   `json:"summary" table:"summary,truncate"`
	Content   string   `json:"content" kit:"body"`
	Tags      []string `json:"tags"`
	Published string   `json:"published"`
	Updated   string   `json:"updated"`
	Views     int64    `json:"views"`
	Likes     int64    `json:"likes"`
	Collects  int64    `json:"collects"`
	Comments  int64    `json:"comments"`
	URL       string   `json:"url"`
}

Article is a single blog post with its body and counters.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client talks to CSDN over HTTP.

func NewClient

func NewClient(cfg Config) *Client

NewClient builds a Client from cfg.

func (*Client) ArticleByRef added in v0.1.1

func (c *Client) ArticleByRef(ctx context.Context, username, id string) (Article, error)

ArticleByRef fetches and parses one article page.

func (*Client) Comments added in v0.1.1

func (c *Client) Comments(ctx context.Context, articleID string, limit int) ([]Comment, error)

Comments pages the comment list under an article and returns up to limit top-level comments.

func (*Client) GetHTML added in v0.1.1

func (c *Client) GetHTML(ctx context.Context, fullURL, referer string) ([]byte, error)

GetHTML fetches an HTML page with the HTML Accept header and the given referer, and returns its body untouched. It does not classify the body: the caller inspects it with isNotFoundHTML and isChallengeHTML, because a CSDN 404 page is a normal 200 HTML document, not a transport error.

func (*Client) GetJSON added in v0.1.1

func (c *Client) GetJSON(ctx context.Context, fullURL, referer string) ([]byte, error)

GetJSON fetches a JSON endpoint with the JSON Accept header and the given referer, and returns its body. A body that is not JSON is the anti-bot challenge, so it maps to ErrWalled.

func (*Client) Hot

func (c *Client) Hot(ctx context.Context, typ string, limit int) ([]Hot, error)

Hot fetches the hot-rank board and returns up to limit ranked entries.

func (*Client) Posts added in v0.1.1

func (c *Client) Posts(ctx context.Context, username string, limit int) ([]Article, error)

Posts pages a user's article list and returns up to limit articles.

func (*Client) Raw added in v0.1.1

func (c *Client) Raw(ctx context.Context, url string) ([]byte, error)

Raw fetches an arbitrary url with the browser HTML headers and returns the body untouched. It is the escape hatch behind `csdn raw`: it does no parsing, so it shows exactly what a surface returns, challenge included. An empty body maps to ErrWalled.

func (*Client) Search

func (c *Client) Search(ctx context.Context, query, typ string, limit int) ([]SearchHit, error)

Search runs a blog search and returns thin, normalized hits. The typ maps to the `t` parameter (blog|all|ask|download|bbs).

func (*Client) UserAgent added in v0.1.1

func (c *Client) UserAgent() string

UserAgent returns the configured User-Agent.

func (*Client) UserByName added in v0.1.1

func (c *Client) UserByName(ctx context.Context, username string) (User, error)

UserByName fetches and parses one profile page, then merges the tab totals.

type Comment added in v0.1.1

type Comment struct {
	ID        string `json:"id" kit:"id"`
	ArticleID string `json:"article_id"`
	Text      string `json:"text" kit:"body" table:"text,truncate"`
	Author    string `json:"author"`
	Nickname  string `json:"nickname"`
	ParentID  string `json:"parent_id"`
	PostTime  string `json:"post_time"`
	Likes     int64  `json:"likes"`
	Region    string `json:"region"`
	URL       string `json:"url"`
}

Comment is one comment under an article, with its parent id for replies.

type Config

type Config struct {
	UserAgent string
	Rate      time.Duration
	Timeout   time.Duration
	Retries   int
}

Config holds the tunable client settings.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns polite defaults: a 600ms gap between requests, a 30s timeout, and five retries on transient errors.

type Domain added in v0.1.1

type Domain struct{}

Domain is the CSDN driver. It carries no state; the per-run client is built by the factory Register hands kit.

func (Domain) Classify added in v0.1.1

func (Domain) Classify(input string) (uriType, id string, err error)

Classify turns any accepted input into the canonical (type, id), so `ant resolve` and `ant url` need no network. An article url or username/id maps to an article; a profile url or a bare username maps to a user.

func (Domain) Info added in v0.1.1

func (Domain) Info() kit.DomainInfo

Info describes the scheme, the hostnames a pasted link is matched against, and the identity a host reuses for help and version.

func (Domain) Locate added in v0.1.1

func (Domain) Locate(uriType, id string) (string, error)

Locate is the inverse: the live https URL for a (type, id), built without a fetch. An article id is the username/id pair Classify produced.

func (Domain) Register added in v0.1.1

func (Domain) Register(app *kit.App)

Register installs the client factory and every CSDN operation onto app. It is the single point both surfaces go through: cli.NewApp calls it for the standalone binary, and a host calls Domain.Register for csdn:// URIs.

type Hot added in v0.1.1

type Hot struct {
	Rank     int    `json:"rank"`
	Title    string `json:"title" kit:"id" table:"title,truncate"`
	Author   string `json:"author"`
	Username string `json:"username"`
	Score    int64  `json:"score"`
	Views    int64  `json:"views"`
	Comments int64  `json:"comments"`
	Favors   int64  `json:"favors"`
	URL      string `json:"url"`
}

Hot is one hot-rank board entry, ranked 1-based.

type SearchHit added in v0.1.1

type SearchHit struct {
	Type     string `json:"type"`
	ID       string `json:"id" kit:"id"`
	Title    string `json:"title" table:"title,truncate"`
	Author   string `json:"author"`
	Username string `json:"username"`
	Summary  string `json:"summary" table:"summary,truncate"`
	Views    int64  `json:"views"`
	Likes    int64  `json:"likes"`
	Comments int64  `json:"comments"`
	URL      string `json:"url"`
}

SearchHit is a thin, normalized search result row.

type Session added in v0.1.1

type Session struct {
	Client *Client
	Quiet  bool
}

Session is the per-run client kit injects into every operation. It pairs the HTTP client with the resolved quiet flag, so an operation can pace its own stderr progress without reaching for a global.

func (*Session) Progressf added in v0.1.1

func (s *Session) Progressf(format string, args ...any)

Progressf prints a one-line progress note to stderr unless the run is quiet.

type User added in v0.1.1

type User struct {
	Username      string `json:"username" kit:"id"`
	Nickname      string `json:"nickname"`
	Intro         string `json:"intro" kit:"body" table:"intro,truncate"`
	Level         string `json:"level"`
	CodeAge       string `json:"code_age"`
	Region        string `json:"region"`
	School        string `json:"school"`
	Company       string `json:"company"`
	Registered    string `json:"registered"`
	Gender        string `json:"gender"`
	VIP           bool   `json:"vip"`
	OriginalCount int64  `json:"original_count"`
	Rank          int64  `json:"rank"`
	Fans          int64  `json:"fans"`
	Follows       int64  `json:"follows"`
	LoyalFans     int64  `json:"loyal_fans"`
	TotalViews    int64  `json:"total_views"`
	BlogCount     int64  `json:"blog_count"`
	ColumnCount   int64  `json:"column_count"`
	DownloadCount int64  `json:"download_count"`
	AskCount      int64  `json:"ask_count"`
	Avatar        string `json:"avatar"`
	URL           string `json:"url"`
}

User is a public CSDN profile, addressed by its username.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL