Skip to content

Commit 1fae3c6

Browse files
author
雷科伟
committed
update api url and signature
1 parent b44e35f commit 1fae3c6

File tree

4 files changed

+97
-41
lines changed

4 files changed

+97
-41
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
.idea/
1+
.idea/
2+
*.md
3+
*.html

README.md

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
# 批量导出CSDN博客
22
> 批量导出`csnd`博客,并转化为`hexo`博客样式,如果你是用富文本编辑器写的则会导出`html`样式
33
4-
注:有些文章可能获取不到造成进度条无法达到100%,如果走到90%多,走不动了,直接取消即可
4+
注:有些文章可能获取不到造成进度条无法达到100%,如果走到99%,走不动了,直接取消即可
55

66
# Quick start
7+
8+
**安装**
79
```bash
8-
go run main.go -username 你的csdn用户名 -cookie 你csdn的cookie -page 1
10+
go get github.com/pibigstar/csdn-hexo
911
```
10-
> page不写,默认为下载全部页
1112

12-
# Demo
13+
**使用**
14+
```bash
15+
csdn-hexo -username 你的csdn用户名 -cookie 你csdn的cookie -page 1
16+
```
17+
> page不写,默认为下载全部页
1318
19+
**完整示例**
1420
```bash
1521
go run main.go -username "junmoxi" -cookie "UserName=junmoxi; UserToken=c3c29cca48be43c4884fe36d052d5851"
1622
```
@@ -21,13 +27,6 @@ go run main.go -username "junmoxi" -cookie "UserName=junmoxi; UserToken=c3c29cca
2127
2228
[点击下载](https://github.com/pibigstar/csdn-hexo/releases/tag/v1.1)
2329

24-
**使用**
25-
> 以Windows用户为例
26-
27-
```bash
28-
main.exe -username 你的csdn用户名 -cookie 你csdn的cookie
29-
```
30-
3130

3231
# cookie获取
3332
![](cookie.png)

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module csdn-hexo
1+
module github.com/pibigstar/csdn-hexo
22

33
go 1.12
44

main.go

Lines changed: 83 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package main
22

33
import (
4+
"crypto/hmac"
5+
"crypto/sha256"
6+
"encoding/base64"
47
"encoding/json"
58
"flag"
69
"fmt"
710
"io/ioutil"
811
"math/rand"
912
"net/http"
13+
"net/url"
1014
"os"
1115
"regexp"
1216
"strings"
@@ -21,7 +25,7 @@ import (
2125

2226
const (
2327
ListPostURL = "https://blog.csdn.net/%s/article/list/%d?"
24-
PostDetailURL = "https://mp.csdn.net/mdeditor/getArticle?id=%s"
28+
PostDetailURL = "https://bizapi.csdn.net/blog-console-api/v3/editor/getArticle?id=%s&model_type="
2529
HexoHeader = `
2630
---
2731
title: %s
@@ -40,7 +44,6 @@ categories: %s
4044
</html>`
4145
)
4246

43-
var postTime = time.Now()
4447

4548
type DetailData struct {
4649
Data PostDetail `json:"data"`
@@ -63,39 +66,45 @@ var (
6366
count int
6467
wg sync.WaitGroup
6568
bar *pgbar.Bar
69+
postTime = time.Now()
70+
)
71+
72+
const (
73+
appSecret = "9znpamsyl2c7cdrr9sas0le9vbc3r6ba"
74+
appCaKey = "203803574"
75+
signHeaders = "x-ca-key,x-ca-nonce"
6676
)
6777

6878
func init() {
6979
flag.StringVar(&username, "username", "junmoxi", "your csdn username")
70-
flag.StringVar(&cookie, "cookie", "UserName=junmoxi; UserToken=c3c29cca48be43c4884fe36d052d5851;", "your csdn cookie")
80+
flag.StringVar(&cookie, "cookie", "UserName=junmoxi;UserToken=b9023fb39b534543a5e65f7cae7cb3c4;", "your csdn cookie")
7181
flag.IntVar(&page, "page", -1, "download pages")
7282
flag.Parse()
83+
rand.Seed(time.Now().Unix())
7384
}
7485

7586
func main() {
7687
urls, err := crawlPosts(username)
7788
if err != nil {
7889
panic(err)
7990
}
80-
8191
bar = pgbar.NewBar(0, "下载进度", len(urls))
82-
for _, url := range urls {
92+
93+
for _, ul := range urls {
8394
wg.Add(1)
84-
go crawlPostMarkdown(url)
95+
go crawlPostMarkdown(ul)
8596
}
86-
8797
wg.Wait()
8898
}
8999

90100
// Crawl posts by username
91101
func crawlPosts(username string) ([]string, error) {
92-
client := http.Client{}
93-
var (
94-
urls []string
95-
)
102+
defer fmt.Println("地址抓取完成,开始下载...")
96103

104+
var urls []string
97105
for {
98-
resp, err := client.Get(fmt.Sprintf(ListPostURL, username, currentPage))
106+
fmt.Printf("正在抓取第%d页文章地址... \n", currentPage)
107+
resp, err := http.DefaultClient.Get(fmt.Sprintf(ListPostURL, username, currentPage))
99108
if err != nil {
100109
return nil, err
101110
}
@@ -124,34 +133,50 @@ func crawlPosts(username string) ([]string, error) {
124133
}
125134

126135
func crawlPostMarkdown(url string) {
136+
defer wg.Done()
137+
defer bar.Add()
138+
defer func() {
139+
if err := recover(); err != nil {
140+
fmt.Println(err)
141+
}
142+
}()
143+
127144
index := strings.LastIndex(url, "/")
128145
id := url[index+1:]
146+
apiUrl := fmt.Sprintf(PostDetailURL, id)
129147

130-
client := http.Client{}
148+
uuid := createUUID()
149+
sign := createSignature(uuid, apiUrl)
131150

132-
req, _ := http.NewRequest("GET", fmt.Sprintf(PostDetailURL, id), nil)
151+
req, _ := http.NewRequest("GET",apiUrl, nil)
133152
req.Header.Set("cookie", cookie)
153+
req.Header.Set("x-ca-key", appCaKey)
154+
req.Header.Set("x-ca-nonce", uuid)
155+
req.Header.Set("x-ca-signature", sign)
156+
req.Header.Set("x-ca-signature-headers", signHeaders)
157+
req.Header.Set("Accept", "*/*")
134158

135-
resp, err := client.Do(req)
159+
resp, err := http.DefaultClient.Do(req)
136160
if err != nil {
137161
return
138162
}
139-
163+
if resp.StatusCode != http.StatusOK {
164+
return
165+
}
140166
data, err := ioutil.ReadAll(resp.Body)
141167
if err != nil {
142168
return
143169
}
144-
145-
post := new(DetailData)
146-
err = json.Unmarshal(data, post)
170+
var post DetailData
171+
err = json.Unmarshal(data, &post)
147172
if err != nil {
148173
return
149174
}
150175

151176
if post.Data.Markdowncontent != "" {
152-
go buildMarkdownPost(post.Data)
177+
buildMarkdownPost(post.Data)
153178
} else if post.Data.Content != "" {
154-
go buildHtmlPost(post.Data)
179+
buildHtmlPost(post.Data)
155180
}
156181
}
157182

@@ -171,15 +196,10 @@ func buildMarkdownPost(post PostDetail) {
171196
rand.Seed(time.Now().UnixNano())
172197
d := rand.Intn(3) + 1
173198
postTime = postTime.AddDate(0, 0, -d).Add(time.Hour)
174-
175199
count++
176-
177-
defer wg.Done()
178-
defer bar.Add()
179200
}
180201

181202
func buildHtmlPost(post PostDetail) {
182-
183203
html := fmt.Sprintf(HtmlBody, post.Title, post.Content)
184204
err := ioutil.WriteFile(
185205
fmt.Sprintf("%s.html", post.Title),
@@ -188,7 +208,42 @@ func buildHtmlPost(post PostDetail) {
188208
if err != nil {
189209
return
190210
}
211+
}
191212

192-
defer wg.Done()
193-
defer bar.Add()
213+
func createSignature(uuid, apiUrl string) string {
214+
u, err := url.Parse(apiUrl)
215+
if err != nil {
216+
panic(err)
217+
}
218+
query := u.Query().Encode()
219+
query = query[:len(query)-1]
220+
message := fmt.Sprintf("GET\n*/*\n\n\n\nx-ca-key:%s\nx-ca-nonce:%s\n%s?%s", appCaKey, uuid, u.Path, query)
221+
hc := hmac.New(sha256.New, []byte(appSecret))
222+
hc.Write([]byte(message))
223+
res := hc.Sum(nil)
224+
225+
result := base64.StdEncoding.EncodeToString(res)
226+
return result
194227
}
228+
229+
func createUUID() string {
230+
s := strings.Builder{}
231+
chars := make([]string, 0, 10)
232+
for i := 97; i < 103; i++ {
233+
chars = append(chars, string(i))
234+
}
235+
for i := 49; i < 58; i++ {
236+
chars = append(chars, string(i))
237+
}
238+
xs := "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
239+
for _, k := range xs {
240+
x := string(k)
241+
if x == "4" || x == "-" {
242+
s.WriteString(x)
243+
} else {
244+
i := rand.Intn(len(chars))
245+
s.WriteString(chars[i])
246+
}
247+
}
248+
return s.String()
249+
}

0 commit comments

Comments
 (0)