使用Python爬取mobi格式电纸书
最近做了个微信推送kindle电子书的公众号:kindle免费书库
不过目前电子书不算非常多,所以需要使用爬虫来获取足够书籍。
于是,写了以下这个爬虫,来爬取kindle114的电子书。
值得注意的地方:
当爬取数过大时,由于对方有开启放抓取,会返回一个javascript而非原始的html,所以我使用
的PyV8来执行这段js从而拿到真正的地址。
目前存在的问题:
正则式写得还不够好,毕竟是第一次正式写爬虫:)
无法下载需要购买的附件
爬虫为单线程,爬完整个网站速度慢。我有试过转成多进程,但是貌似由于不能同时登陆,大多数
爬虫进程都无法正常爬取@@
# -*- coding: utf-8 -*-
import urllib2
import re
import requests
import os
import hashlib def fuckJS(js):
import PyV8
import re
#去掉<script>标签
js=js[31:-9]
for st in ['window','location',"'assign'","'href'","'replace'"]:
equal=re.findall('[_A-Za-z0-9 =]+%s;'%st,js)#找到变量赋值等式
if equal==[]:#有可能没有
continue
else:
equal=equal[0]
var=equal.split('=')[0].strip()#找出变量名
#把等式干掉
js=js.replace(equal,'')
#把变量替换成它真正的意思
js=js.replace(var,st)
#把['xx'] 替换成 .xx
js=js.replace("['%s']"%st.strip("'"),'.%s'%st.strip("'"))
#将 window.href= 后的内容踢掉,因为当PyV8只输出最后一个等式的值
if re.findall('window\.href=.+',js)!=[]:
js=js.replace(re.findall('window\.href=.+',js)[0],'')
#删掉location.xxx=
js=js.replace('location.href=','').replace('location.replace','').replace('location.assign','')
#交给你了-v-
ctxt2 = PyV8.JSContext()
ctxt2.enter()
#print ctxt2.eval(js)
trueAddr = ctxt2.eval(js)
print trueAddr
return trueAddr def downloadMobi(name, url):
#去掉windows下不合法的文件名
unlawName = '<>/\\|:""*?'
for i in unlawName:
name = name.replace(i, '')
#正则表达式写的不够好导致的问题@@
if name.count(' img src=templateyeei_dream1cssyeeidigest_1.gif class=vm alt= title= ') > 0:
name = name.split('  ')[0]+'.mobi'
#避免重复下载
if os.path.exists('D:\Kindle114SpiderDownload\\' + name):
print 'already have', name
return
url = url.split(' ')[0]
s = requests.session()
username = '你的用户名'
password = '你的密码'
passwordMd5 = hashlib.md5(password).hexdigest()
data = {'formhash': '23cd6c29', 'referer': '','username': username, 'password': passwordMd5, 'questionid':'', 'answer':''}
res=s.post('http://www.kindle114.com/member.php?mod=logging&action=login&loginsubmit=yes&loginhash=LYn7n&inajax=1',data) #res = s.get('http://www.kindle114.com/forum.php?mod=attachment&aid=MTQ2NTB8ZjhkNjY3NmF8MTQxNjg5OTYxOXw0NDIxfDczNjI%3D')
try:
res = s.get(url, timeout = 200)
except:
print 'time out for ', name
#print 'content[:50]'
#print res.content[:50]
if res.content.count('<!DOCTYPE html') > 0:
print '!!!!!!!!!!!!!!!!!not a mobi, this file need gold coin!!!!!!!!!!!!!!!'
return
try:
with open('D:\\Kindle114SpiderDownload\\' + name, "wb") as code:
code.write(res.content)
except:
print '!!!!!!!!!!!!!!!!!!!!!遇到不合法文件名!!!!!!!!!!!!!!!!!!', name def spiderThread(url, threadName):
req = urllib2.urlopen(url, timeout = 10)
text = req.read()
if text.count('<!DOCTYPE html') == 0:
js = text
trueURL = 'http://www.kindle114.com/' + fuckJS(js)
print 'trueURL', trueURL
req = urllib2.urlopen(trueURL)
text = req.read() #href = '<a href="(.*?)" onmouseover="showMenu({\'ctrlid\':this.id,\'pos\':\'12\'})" id=.*?target="_blank">(.*?)</a>'
href = '<a href="(.*?)".*?target="_blank">(.*?)</a>'
href_re = re.compile(href)
href_info = href_re.findall(text) bookSum = 0
for i in href_info:
if i[1].count('.mobi') > 0:
bookSum+=1
if bookSum == 0:
print '!!!bookSum = 0!!!!', text[:100]
if bookSum == 1:
print 'only one book in this thread'
bookFileName = threadName + '.mobi'
for i in href_info:
if i[1].count('.mobi') > 0:
link = i[0].replace('amp;','')
break
print link, bookFileName
downloadMobi(bookFileName, link)
else:
print str(bookSum), 'in this thread'
for i in href_info:
if i[1].count('.mobi') > 0:
link = i[0].replace('amp;','')
bookFileName = i[1]
print link, bookFileName
downloadMobi(bookFileName, link) for pageNum in range(1, 125):
url = 'http://www.kindle114.com/forum.php?mod=forumdisplay&fid=2&filter=sortid&sortid=1&searchsort=1&geshi=1&page=' + str(pageNum)
print '=============url', url,'==============='
try:
req = urllib2.urlopen(url, timeout = 10)
except:
print 'page time out', url
text = req.read()
href = '<h4><a href="(.*?)" target="_blank" class="xst">(.*?)<span class="xi1">'
href_re = re.compile(href)
href_info = href_re.findall(text)
for i in href_info:
print i[0], i[1]
url = 'http://www.kindle114.com/'+i[0]
threadName = i[1]
try:
spiderThread(url, threadName)
except Exception , e:
print '!!!!!!!!!!!!! Error with ',threadName, url,'!!!!!!!!!!!!!!!!'
print e
raw_input('finish all!!!')
使用Python爬取mobi格式电纸书的更多相关文章
- python爬取网站数据
开学前接了一个任务,内容是从网上爬取特定属性的数据.正好之前学了python,练练手. 编码问题 因为涉及到中文,所以必然地涉及到了编码的问题,这一次借这个机会算是彻底搞清楚了. 问题要从文字的编码讲 ...
- Python:爬取乌云厂商列表,使用BeautifulSoup解析
在SSS论坛看到有人写的Python爬取乌云厂商,想练一下手,就照着重新写了一遍 原帖:http://bbs.sssie.com/thread-965-1-1.html #coding:utf- im ...
- 利用Python爬取豆瓣电影
目标:使用Python爬取豆瓣电影并保存MongoDB数据库中 我们先来看一下通过浏览器的方式来筛选某些特定的电影: 我们把URL来复制出来分析分析: https://movie.douban.com ...
- python爬取人民币汇率中间价
python爬取人民币汇率中间价,从最权威的网站中国外汇交易中心. 首先找到相关网页,解析链接,这中间需要经验和耐心,在此不多说. 以人民币兑美元的汇率为例(CNY/USD),脚本详情如下: wind ...
- python爬取网站数据保存使用的方法
这篇文章主要介绍了使用Python从网上爬取特定属性数据保存的方法,其中解决了编码问题和如何使用正则匹配数据的方法,详情看下文 编码问题因为涉及到中文,所以必然地涉及到了编码的问题,这一次借这 ...
- Python爬取豆瓣电影top
Python爬取豆瓣电影top250 下面以四种方法去解析数据,前面三种以插件库来解析,第四种以正则表达式去解析. xpath pyquery beaufifulsoup re 爬取信息:名称 评分 ...
- Python 爬取淘宝商品数据挖掘分析实战
Python 爬取淘宝商品数据挖掘分析实战 项目内容 本案例选择>> 商品类目:沙发: 数量:共100页 4400个商品: 筛选条件:天猫.销量从高到低.价格500元以上. 爬取淘宝商品 ...
- steam夏日促销悄然开始,用Python爬取排行榜上的游戏打折信息
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 不知不觉,一年一度如火如荼的steam夏日促销悄然开始了.每年通过大大小小 ...
- 用Python爬取B站、腾讯视频、爱奇艺和芒果TV视频弹幕!
众所周知,弹幕,即在网络上观看视频时弹出的评论性字幕.不知道大家看视频的时候会不会点开弹幕,于我而言,弹幕是视频内容的良好补充,是一个组织良好的评论序列.通过分析弹幕,我们可以快速洞察广大观众对于视频 ...
随机推荐
- 第一篇.markdown
目录 Day 01 1.markdown的使用感受 2.markdown的基本语法 2.1 标题 2.2 加粗 2.3 斜体 2.4 高亮 2.5 上标 2.6 下标 2.7 代码引用(>式) ...
- TCP的keepalive和应用层的heart
从长链接说起 TCP是长链接的,也就是说连接建立后,及时数年没有通信连接仍然存在.这样做的好处是:免去了DNS解析的时间,连接建立等时间,大大加快了请求的速度,同时也有利于接受服务器的实时消息.但前提 ...
- VTORRAAYY ws+tls+nginx config
# nginx conf partal location /haha { proxy_redirect off; # the prot should same with config v2*** pr ...
- 2.06_Python网络爬虫_正则表达式
一:爬虫的四个主要步骤 明确目标 (要知道你准备在哪个范围或者网站去搜索) 爬 (将所有的网站的内容全部爬下来) 取 (过滤和匹配我们需要的数据,去掉没用的数据) 处理数据(按照我们想要的方式存储和使 ...
- Ubuntu下PHP+MySQL+Apache+PHPStorm的安装和配置
粘贴自:https://www.jianshu.com/p/a6a0d2a29591 1.Apache的安装: $ sudo apt-get update $ sudo apt-get install ...
- Codeforces 1148 E - Earth Wind and Fire
E - Earth Wind and Fire 思路: 栈模拟 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC opti ...
- Linux下批量修改文件编码
假设需要将所有afish目录下的php文件,编码从gb2312转到utf8 cd afish find ./ -type f -name “*.php”|while read line;do echo ...
- HashSet怎样保证元素不重复
文章同步更新在个人博客:HashSet怎样保证元素不重复 都知道HashSet中不能存放重复元素,有时候可以用来做去重操作等.但是其内部是怎么保证元素不重复的呢?下面从源码去看看. 打开HashSet ...
- Base64编码与解码的作用
1.便于网络传输. 2.不可见性. 3.适合在http,mime协议下快速传输数据. 4 区别于加密,Base64是可以解码的,编码是 公开的,Base 64编码,任何人都可以解码
- solr不是自启动,添加code失败
原文:https://blog.csdn.net/qq_30242987/article/details/100044964 我主要的问题是 conf要复制 configests/sample_t ...