Python 备份 豆瓣 读过的书的记录
HDUZN

原文章写于:2021年02月20日
本来想升级下 selenium,原来用的3,现在准备改代码换成4的版本。结果发现现在都会检测是selenium webdriver,不让代码登录了。
于是,又重新折腾了下。

之前总是担心某一天豆瓣撑不下去了会倒闭。于是,总想着把自己在豆瓣标记的读过的书,看过的电影都备份存下来,主要还有一些看完当时的短评记录。

电影的页面和读书的页面差不多的,所以这里就介绍一下备份读过的书的方法。
最终存到Excel表格中和数据库(sqlite)表中。

此项目所有代码开源放在Github上了,文章下面有地址,所以此文只是记录这个实现、使用的过程。

一、准备工作

1.安装Selenium 测试环境

用来自动化操作豆瓣的页面,爬取数据。
之前有篇笔记写了:Python Selenium使用举例

如果是Windows环境也是一样的,主要就是3步。

  • 安装Chrome浏览器;
  • 安装浏览器驱动(要对应浏览器的版本,就是一个chromedriver.exe这样的可执行文件)
  • 安装Selenium包(现在装的版本都是4)

安装Selenium包Windows下命令为:

1
pip install selenium

2.安装 openpyxl 包

这个是用来操作Excel表的,把数据写入到Excel表里需要用到。

1
pip install openpyxl

自己简单的数据库,就直接用Python自带的sqlite3了,很喜欢就这样一个数据库(.db)文件。

二、代码实现

思路

  • 1).登录进豆瓣账号,点开【读过的书】的页面;
  • 2).获取最大的页面数 max_page_num;
  • 3).获取每个页面的链接,得到一个所有链接的List:page_site_list;
  • 4).写一个获取一个页面信息的方法/函数:get_one_page,存成一个List;
  • 4).循环page_site_list,读取每个页面的数据信息List存到全部数据的List中:all_page_data_list;
  • 5).最后把全部数据 all_page_data_list 写入到Excel表中和存到数据库中。

1.建立数据库、表

建立一个数据库文件 douban.db,然后建一张存书信息的 books表。

里面有书籍的name(名称),site(豆瓣链接),author(作者),tags(标签),date(已读日期),comments(评论),rating_num(评分数字等级), rating(评分,星级),pic(书籍图片链接)

存了书籍的图片链接,主要为了以后别的地方也可以用。
所以如果你不需要的信息,可以不存。

1
2
3
4
5
6
7
8
9
10
11
12
CREATE TABLE "books" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
"name" TEXT NOT NULL,
"site" TEXT,
"author" TEXT,
"tags" TEXT,
"date" TEXT,
"comments" TEXT,
"rating_num" INTEGER,
"rating" TEXT,
"pic" TEXT
);

2.获取所有页面的链接List 的方法

思路:
获取最大页面数的时候,把对应的链接存下来,这就是一个模板链接,model_site 如下:
其中[id]为每个人自己的豆瓣用户id。

1
https://book.douban.com/people/[id]/collect?start=285&sort=time&rating=all&filter=all&mode=grid

可以看到,start=后面的数字即是每个页面不同的地方。

  • 第1页:没写,其实是0;
  • 第2页:15;
  • 第3页:30;
  • 第4页:45;
  • 第n页:(n-1)*15

所以可以把 model_site 切分成3段,数字前面是第一段,中间是页面相关的数字,第三段是 &sort开始的后面这段。

第一段和第三段是固定的,通过一个循环就可以了。

代码实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 获取所有页数的链接List
def get_page_site_list(max_page_num, model_site):
# model_site: https://book.douban.com/people/[id]/collect?start=300&sort=time&rating=all&filter=all&mode=grid
cop = '[0-9]'
site_part2 = ''.join(re.findall(cop, model_site)) # 用正则取出数字'300'
site_part1 = model_site.split(site_part2)[0] # https://book.douban.com/people/[id]/collect?start=
site_part3 = model_site.split(site_part2)[1] # &sort=time&rating=all&filter=all&mode=grid

site_list = []
for i in range(max_page_num):
site_part2_num = str(i * 15)
page_site = site_part1 + site_part2_num + site_part3
site_list.append(page_site)
return site_list

3.获取一页的内容方法

获取一页的内容,最后返回一个data_list。
data_list中每一项包括:书籍名、书籍链接、书籍作者信息、书籍标签、阅读日期、评论、评分(数字)、评分、书籍图片链接。

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# 获取一页的数据内容
def get_one_page(wd, page_site):
try:
wd.get(page_site)
time.sleep(2)
except selenium.common.exceptions.TimeoutException:
time.sleep(5)
wd.get(page_site)

pic_list = [] # 图书图片List
pic_values = wd.find_elements(By.XPATH, '//li[@class="subject-item"]//img') # 图书图片
for value in pic_values:
pic_site = value.get_attribute('src')
pic_list.append(pic_site)
# print(pic_list)

book_site_list = [] # 图片链接List
book_name_list = [] # 图书名称List
book_values = wd.find_elements(By.XPATH, '//li[@class="subject-item"]//div[@class="info"]//h2//a')
for value in book_values:
book_site = value.get_attribute('href')
book_site_list.append(book_site)
book_name = value.text
book_name_list.append(book_name)
# print(book_site_list)
# print(book_name_list)

author_list = [] # 作者信息List
author_info = wd.find_elements(By.XPATH, '//li[@class="subject-item"]//div[@class="info"]//div[@class="pub"]')
for value in author_info:
author_list.append(value.text)
# print(author_list)

tags_list = [] # 标签List
tag_values = wd.find_elements(By.XPATH, '//li[@class="subject-item"]//div[@class="info"]//div[@class="short-note"]//span[@class="tags"]')
for value in tag_values:
tags_list.append(value.text.split(':')[1].strip())
# print(tags_list)

date_list = [] # 读过日期List
date_values = wd.find_elements(By.XPATH, '//li[@class="subject-item"]//div[@class="info"]//div[@class="short-note"]//span[@class="date"]')
for value in date_values:
date_list.append(value.text.split()[0])
# print(date_list)

rating_list = [] # 评分List(星星)
rating_num_list = [] # 评分List(数字)
rating_values = wd.find_elements(By.XPATH, '//li[@class="subject-item"]//div[@class="info"]//div[@class="short-note"]//span[1]')
for value in rating_values:
rate = value.get_attribute('class')[6] # str 5/4/3/2/1
rating_num_list.append(int(rate))
rating_list.append(douban_config.rating_dict[rate])
# print(rating_list)
# print(rating_num_list)

comment_list = [] # 短评List
comment_values = wd.find_elements(By.XPATH, '//li[@class="subject-item"]//div[@class="info"]//div[@class="short-note"]//p[@class="comment"]')
for value in comment_values:
comment_list.append(value.text)
# print(comment_list)

num = len(book_name_list)
data_list = []
for i in range(num):
data_list.append([book_name_list[i], book_site_list[i], author_list[i], tags_list[i], date_list[i], comment_list[i], rating_num_list[i], rating_list[i], pic_list[i]])
return data_list

注意
因为每一页中是每一项取一个List、最后合成的。
所以如果书籍标记的时候,没有标签、没有评分(打星)的话,会报错,获取不到信息。

4.用selenium登录前提设置

为了跳过selenium的webdriver检测,所以使用的是本地debugger模式登录。
使用方法看后面的使用说明,代码如下:

1
2
3
4
5
6
option = webdriver.ChromeOptions()
# 使用本地debugger模式,可以提前登录
option.add_experimental_option('debuggerAddress','127.0.0.1:9222')
wd = webdriver.Chrome(options=option)
wd.implicitly_wait(10)
wd.get(site)

三、整个项目打包

整个项目放在 Github上了。链接: own_douban_backup

看README.md文档即可。

项目文件说明:

1
2
3
4
5
6
7
8
9
10
douban_backup
- db
- douban.db
- ex
- douban.xlsx
- books.py
- douban.sql
- douban_config.py
- main.py
- z_db.py

db/douban.db : sqlite数据库文件,最后保存的数据都在这里
ex/douban.xlsx : Excel文件,最后保存的数据同步保存在这里
books.py :调用 main()方法,将Douban 读过的书的记录保存到数据库books表中和douban.xlsx 文件中
douban.sql : 表创建的sql语句(books表)
douban_config.py :配置文件
main.py :主文件
z_db.py :数据库操作文件

四、使用说明

运行main.py中的方法

1.先运行init_create_table()方法初始化,创建数据库中的表

2.备份看过的书
去掉 #books.main()前面的 #注释,再 注释init_create_table()方法即可运行。

3.怎么运行

1).第一步,用Windows PowerShell或命令提示符运行chrome.exe

找到Chrome浏览器的安装路径,比如我的在:C:\Program Files (x86)\Google\Chrome\Application,里面就有chrome.exe程序。

运行以下命令:

1
2
3
cd "C:\Program Files (x86)\Google\Chrome\Application"

.\chrome.exe --remote-debugging-port=9222 --user-data-dir=D:\cdsf

remote-debugging-port:是代码中指定的端口debuggerAddress;
user-data-dir:随便指定一个目录就行(真实没有这个目录也没关系,名字随便取)

如图所示:

运行完后会打开Chrome浏览器。

2).第二步,运行 main.py

在main.py中运行程序。就会在打开的Chrome浏览器中正常运行了。

PS.如果自己提前登录过,还能记住密码。再登录的时候可以不需要登录了。(所以登录部分的代码做了这个判断)

  • 本文标题:Python 备份 豆瓣 读过的书的记录
  • 本文作者:HDUZN
  • 创建时间:2022-05-13 10:28:00
  • 本文链接:http://hduzn.cn/2022/05/13/Python-备份-豆瓣-读过的书的记录/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
 评论