最近做了个微信推送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(' &nbsp;img src=templateyeei_dream1cssyeeidigest_1.gif class=vm alt= title= ') > 0:
name = name.split(' &nbsp')[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格式电纸书的更多相关文章

  1. python爬取网站数据

    开学前接了一个任务,内容是从网上爬取特定属性的数据.正好之前学了python,练练手. 编码问题 因为涉及到中文,所以必然地涉及到了编码的问题,这一次借这个机会算是彻底搞清楚了. 问题要从文字的编码讲 ...

  2. Python:爬取乌云厂商列表,使用BeautifulSoup解析

    在SSS论坛看到有人写的Python爬取乌云厂商,想练一下手,就照着重新写了一遍 原帖:http://bbs.sssie.com/thread-965-1-1.html #coding:utf- im ...

  3. 利用Python爬取豆瓣电影

    目标:使用Python爬取豆瓣电影并保存MongoDB数据库中 我们先来看一下通过浏览器的方式来筛选某些特定的电影: 我们把URL来复制出来分析分析: https://movie.douban.com ...

  4. python爬取人民币汇率中间价

    python爬取人民币汇率中间价,从最权威的网站中国外汇交易中心. 首先找到相关网页,解析链接,这中间需要经验和耐心,在此不多说. 以人民币兑美元的汇率为例(CNY/USD),脚本详情如下: wind ...

  5. python爬取网站数据保存使用的方法

    这篇文章主要介绍了使用Python从网上爬取特定属性数据保存的方法,其中解决了编码问题和如何使用正则匹配数据的方法,详情看下文     编码问题因为涉及到中文,所以必然地涉及到了编码的问题,这一次借这 ...

  6. Python爬取豆瓣电影top

    Python爬取豆瓣电影top250 下面以四种方法去解析数据,前面三种以插件库来解析,第四种以正则表达式去解析. xpath pyquery beaufifulsoup re 爬取信息:名称  评分 ...

  7. Python 爬取淘宝商品数据挖掘分析实战

    Python 爬取淘宝商品数据挖掘分析实战 项目内容 本案例选择>> 商品类目:沙发: 数量:共100页  4400个商品: 筛选条件:天猫.销量从高到低.价格500元以上. 爬取淘宝商品 ...

  8. steam夏日促销悄然开始,用Python爬取排行榜上的游戏打折信息

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 不知不觉,一年一度如火如荼的steam夏日促销悄然开始了.每年通过大大小小 ...

  9. 用Python爬取B站、腾讯视频、爱奇艺和芒果TV视频弹幕!

    众所周知,弹幕,即在网络上观看视频时弹出的评论性字幕.不知道大家看视频的时候会不会点开弹幕,于我而言,弹幕是视频内容的良好补充,是一个组织良好的评论序列.通过分析弹幕,我们可以快速洞察广大观众对于视频 ...

随机推荐

  1. late_initcall 替换 module_init

    今天在调试pwm驱动程序的时候,在__init函数中调用pwm_init后,则以太网不可用.pwm_init放在设备文件的open函数中,则系统正常运行. 这当中的区别就是硬件初始化函数pwm_ini ...

  2. 编译原理实战——使用Lex/Flex进行编写一个有一定词汇量的词法分析器

    编译原理实战--使用Lex/Flex进行编写一个有一定词汇量的词法分析器 by steve yu 2019.9.30 参考文档:1.https://blog.csdn.net/mist14/artic ...

  3. 团队第三次作业:Alpha版本第二周小结

    姓名 学号 周前计划安排 每周实际工作记录 自我打分 XXX 061109 1.对原型设计与编码任务进行进一步的规划与任务分配 2.协调与统一已完成的部分原型设计页面风格并针对部分页面提出了改进建议 ...

  4. 如何让Python2与Python3共存

    一.摘要 最近做服务测试的时候,实在被第三方模块折磨的够呛,从安装就存在兼容Py2和Py3的问题,产品提供的服务越来越多,做服务验证也不得不跟进支持测试,这眼前的Hadoop/Hive/Hbase/H ...

  5. axios 用 params/data 发送参数给 springboot controller,如何才能正确获取

    今天有人遇到接口调用不通的情况,粗略看了一下是axios跨域请求引起了.找到问题,处理就简单多了. 但是我看其代码,发现比较有意思 export function agentlist(query) { ...

  6. SQL查询CASE遇上NULL怎么办?

    原SQL: case userName when  null THEN '空' else '有值' end, 这种写法不好使: 换一种:case when userName is null THEN ...

  7. ftp定时下载指定目录或文件脚本

    #! /bin/bash rpm -qa lftp &>/dev/null || yum install -y lftp lftp 160.106.0.34 << EOF c ...

  8. vue今日总结

    ''' 复习 ''' """ 1.vue框架的优势 中文API 单一面应用 - 提升移动端app运行速度 数据的双向绑定 - 变量全局通用 数据驱动 - 只用考虑数据,不 ...

  9. wavefronts

    https://www.g-truc.net/post-0597.html https://michaldrobot.com/2014/04/01/gcn-execution-patterns-in- ...

  10. 数字签名 转载:http://www.youdzone.com/signature.html

    What is a Digital Signature?An introduction to Digital Signatures, by David Youd Bob (Bob's public k ...