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
- Variables
- func BaseIdentity() kit.Identity
- func Defaults(c *kit.Config)
- func MapErr(err error) error
- func ParseArticleID(in string) (string, error)
- func ParseArticleRef(in string) (username, id string, err error)
- func ParseUsername(in string) (string, error)
- func Register(app *kit.App)
- type Article
- type Client
- func (c *Client) ArticleByRef(ctx context.Context, username, id string) (Article, error)
- func (c *Client) Comments(ctx context.Context, articleID string, limit int) ([]Comment, error)
- func (c *Client) GetHTML(ctx context.Context, fullURL, referer string) ([]byte, error)
- func (c *Client) GetJSON(ctx context.Context, fullURL, referer string) ([]byte, error)
- func (c *Client) Hot(ctx context.Context, typ string, limit int) ([]Hot, error)
- func (c *Client) Posts(ctx context.Context, username string, limit int) ([]Article, error)
- func (c *Client) Raw(ctx context.Context, url string) ([]byte, error)
- func (c *Client) Search(ctx context.Context, query, typ string, limit int) ([]SearchHit, error)
- func (c *Client) UserAgent() string
- func (c *Client) UserByName(ctx context.Context, username string) (User, error)
- type Comment
- type Config
- type Domain
- type Hot
- type SearchHit
- type Session
- type User
Constants ¶
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.
const Host = "https://www.csdn.net"
Host is the CSDN front-page origin, the default Referer for HTML reads.
Variables ¶
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.
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
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
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
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
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
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
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.
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"`
Pinned bool `json:"pinned"`
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 (*Client) ArticleByRef ¶ added in v0.1.1
ArticleByRef fetches and parses one article page.
func (*Client) Comments ¶ added in v0.1.1
Comments pages the comment list under an article and returns up to limit comments, flattening each thread so top-level comments and their replies (which CSDN nests under "sub") both appear. A reply carries its parentId, so the thread can be reconstructed from the flat stream.
func (*Client) GetHTML ¶ added in v0.1.1
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
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) Posts ¶ added in v0.1.1
Posts pages a user's article list and returns up to limit articles.
func (*Client) Raw ¶ added in v0.1.1
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 ¶
Search runs a blog search and returns thin, normalized hits. The typ maps to the `t` parameter (blog|all|ask|download|bbs).
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"`
ParentNick string `json:"parent_nick"`
PostTime string `json:"post_time"`
Likes int64 `json:"likes"`
Region string `json:"region"`
Avatar string `json:"avatar"`
URL string `json:"url"`
}
Comment is one comment under an article, with its parent id for replies.
type Config ¶
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
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.
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"`
Cover string `json:"cover"`
Avatar string `json:"avatar"`
}
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"`
Published string `json:"published"`
Tags []string `json:"tags"`
Views int64 `json:"views"`
Likes int64 `json:"likes"`
Collects int64 `json:"collects"`
Comments int64 `json:"comments"`
URL string `json:"url"`
}
SearchHit is a thin, normalized search result row.
type Session ¶ added in v0.1.1
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.
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.