需安装 wkhtmltopdf 软件 并添加软件bin目录至环境变量 https://wkhtmltopdf.org/downloads.html
下载对应版本chromdriver.exe并放入仁义环境变量目录 如上述目录 或 C:\\windows
pip install requests,selenium,pdfkit
import
os
import
sys
import
time
import
requests
from
selenium
import
webdriver
import
pdfkit
import
re
class
JikeDownloadPDF
:
def
__init__
(
self
,
username
,
passwd
,
article_list_url
)
:
:param username: 用户名
:param passwd: 密码
:param article_list_url:文章列表链接 https://time.geekbang.org/column/126
self
.
_user
=
str
(
username
)
.
strip
(
)
self
.
_passwd
=
str
(
passwd
)
.
strip
(
)
self
.
article_list_url
=
article_list_url
.
strip
(
)
self
.
driver
=
self
.
_get_webdriver
(
)
self
.
session
=
self
.
_get_session
(
)
self
.
download
(
)
def
_get_session
(
self
)
:
利用浏览器的cookies生成requests session,用于后续接口请求,或者文章列表(不登录也可),文章详情,如音频下载
:return:
header
=
{
'Referer'
:
'https://time.geekbang.org'
,
'Content-Type'
:
'application/json'
,
'user-agent'
:
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36'
s
=
requests
.
session
(
)
s
.
headers
=
header
cookies_dict
=
dict
(
[
(
i
[
'name'
]
,
i
[
'value'
]
)
for
i
in
self
.
driver
.
get_cookies
(
)
]
)
requests
.
utils
.
add_dict_to_cookiejar
(
s
.
cookies
,
cookies_dict
)
return
s
def
_get_webdriver
(
self
)
:
driver
=
webdriver
.
Chrome
(
)
login_url
=
'https://account.geekbang.org/signin'
driver
.
get
(
login_url
)
for
i
in
range
(
3
)
:
driver
.
find_element_by_class_name
(
"nw-input"
)
.
send_keys
(
self
.
_user
)
driver
.
find_element_by_class_name
(
"input"
)
.
send_keys
(
self
.
_passwd
)
driver
.
find_element_by_class_name
(
"mybtn"
)
.
click
(
)
driver
.
implicitly_wait
(
5
)
check_url
=
'https://account.geekbang.org/dashboard/info'
time
.
sleep
(
2
)
if
driver
.
current_url
!=
check_url
:
print
(
driver
.
current_url
)
print
(
"登录失败, 重新登录"
)
else
:
return
driver
else
:
print
(
"登录失败次数3次,程序退出"
)
time
.
sleep
(
2
)
sys
.
exit
(
1
)
def
_get_articles_id_list
(
self
)
:
data
=
{
'cid'
:
str
(
self
.
article_list_url
)
.
rsplit
(
"/"
,
1
)
[
-
1
]
,
'size'
:
20
,
'prev'
:
0
,
'order'
:
'newest'
,
'sample'
:
True
}
url
=
'https://time.geekbang.org/serv/v1/column/articles'
result
=
[
]
def
get_data
(
data
)
:
response
=
self
.
session
.
post
(
url
=
url
,
json
=
data
)
if
response
.
status_code
!=
200
:
print
(
"未登录成功或其他原因,访问文章列表失败"
)
return
res
=
response
.
json
(
)
if
res
[
'error'
]
:
print
(
res
[
'error'
]
)
return
for
cell
in
res
[
'data'
]
[
'list'
]
:
result
.
append
(
cell
[
'id'
]
)
if
res
[
'data'
]
[
'page'
]
[
'more'
]
:
prev
=
res
[
'data'
]
[
'list'
]
[
-
1
]
[
'score'
]
inner_data
=
data
inner_data
[
'prev'
]
=
prev
get_data
(
inner_data
)
get_data
(
data
)
return
result
def
download
(
self
,
prefix
=
''
)
:
prefix
=
str
(
self
.
article_list_url
)
.
rsplit
(
"/"
,
1
)
[
-
1
]
if
not
prefix
else
prefix
if
os
.
path
.
isfile
(
prefix
)
:
prefix
=
''
print
(
"指定路径前缀为文件,自动跳过"
)
else
:
os
.
path
.
isdir
(
prefix
)
or
os
.
mkdir
(
prefix
)
driver
=
self
.
driver
url
=
'https://time.geekbang.org/column/article/{}'
audio_url
=
'https://time.geekbang.org/serv/v1/article'
for
index
,
id_
in
enumerate
(
self
.
_get_articles_id_list
(
)
,
1
)
:
art_url
=
url
.
format
(
id_
)
for
i
in
range
(
3
)
:
try
:
driver
.
get
(
art_url
)
title
=
driver
.
find_element_by_tag_name
(
'body'
)
.
find_element_by_tag_name
(
'h1'
)
.
text
except
Exception
as
e
:
print
(
e
,
"{}获取失败次数{}"
.
format
(
art_url
,
i
)
)
else
:
print
(
"开始下载第{}篇文章,文章名字:{}"
.
format
(
index
,
title
)
)
因为要在windows下保存为PDF文件
所以文件名不能为特殊字符
此处将可能出现的特殊替换为空字符串
raw_title
=
'{}{}{}'
.
format
(
prefix
,
"/"
,
re
.
sub
(
'[\/::*?"<>|]'
,
''
,
title
)
)
options
=
{
'page-size'
:
'Letter'
,
'encoding'
:
"UTF-8"
,
'custom-header'
:
[
(
'Accept-Encoding'
,
'gzip'
)
pdfkit
.
from_string
(
driver
.
page_source
,
raw_title
+
'.pdf'
,
options
=
options
)
data
=
{
"id"
:
str
(
id_
)
,
"include_neighbors"
:
True
}
response
=
self
.
session
.
post
(
audio_url
,
json
=
data
)
try
:
res
=
response
.
json
(
)
audio_downurl
=
res
[
'data'
]
[
'audio_download_url'
]
except
Exception
as
e
:
print
(
e
)
else
:
if
audio_downurl
:
with
open
(
raw_title
+
'.mp3'
,
'wb'
)
as
f
:
f
.
write
(
self
.
session
.
get
(
audio_downurl
)
.
content
)
break
else
:
print
(
"{}获取失败次数达到上限,跳过"
.
format
(
art_url
)
)
if
__name__
==
'__main__'
:
down
=
JikeDownloadPDF
(
'###'
,
'###'
,
'https://time.geekbang.org/column/126'
)
可以看到都有个article的数据,数据里有一个data,data中有个audio_download_url,是个MP3
这里可以直接拷贝到浏览器,确定就是这个课程这一节的
音频
,我们的目标就找到了,就是这个东西
这个可以看到是请求的路径,并非上面的网址
参数在下面
因为需要登录,所以封装自己的请求头
抄浏览器的
一长串,里面的cookie
最近支付宝的 "中国锦鲤"活动 ,让信小呆一夜爆红 ,此后很多商家开始纷纷效仿发起寻找同城 "锦鲤" 。各种以“锦鲤”为名的转发抽奖活动正式引爆朋友圈 。这次在
极客时间
一...
写在前面:这两周花了点时间读了《Python网络数据采集》,内容不多,不到200页,但是非常丰富,有入门,有提高,有注意事项,有经验之谈,有原理,有分析,读完受益匪浅。书中讲了很多反爬虫、图片验证码之类的东西,不过感谢csdn的开放性,这些都没有。所以第一个练习,就是爬取csdn的
极客
头条的更新
文章
。
1 思路
思路比较简单,首先是登录,然后爬取页面的更新
文章
名称和链接。要注意的一点是,
极客
支持多设备之间图书同步 (⭐⭐⭐⭐⭐) 多设备支持优先级 PC(web or software) > ipad > mobile phone支持做笔记、标注,笔记最好可多设备之间同步 (⭐⭐⭐⭐) 记录阅读时长 (⭐⭐⭐) 支持用户上传
订阅了几个
极客时间
的专栏,一直没有时间去看。
最近,想着如果把内容制作成电子书,利用上下班时间学习一下,岂不是很方便?
在网上搜到一个很好用的开源软件,几分钟就可以把
极客时间
的专栏做成电子书,简直太棒了,由衷地感谢软件的作者。
制作电子书的开源软件地址是 https://github.com/jachinlin/geektime_dl。