手写python爬虫下载电子书一键发送到kindle

1.概述

由于平时喜欢看书,但是发现一些推送的服务号没有自己想要的电子书,最近再学习爬虫,就想小试牛刀,主要用到的技术:

使用pythonrequests模块进行网站信息的爬取

解析我使用了两个方式,正则表达式和pyquery库进行html的解析

由于kindle推送,主要使用的是邮箱发送的方式,所以使用python已经封装好的email模块和smtplib模块,发送附件至你的kindle邮箱
主要的功能模块实现:

检索书籍然后推送至kindle
排行榜推送至kindle


2.各模块实现

2.1 排行榜采集模块

采集网页信息
主要使用的是requests模块。

def spider_qishu(url,headers):
    response=requests.get(url,headers=headers)
    if response.status_code==200:
        return response.text
    return None

函数功能:get请求将网页的内容读取

解析html中的关键信息,并将其返回

def tuijian(html):
    result=re.findall('<font>(.*?)</font>.*?<u style=.*?<em>(.*?)</em><a href="(.*?)">(.*?)</a></u>',html,re.S)
    paihangbang=re.findall('<h2>(.*?)</h2>',html,re.S)
    print(paihangbang[0])
    results=[]
    for item in result:
        t={}
        t['index']=item[0]
        t['author']=item[1]
        t['href']=item[2]
        t['book_name']=item[3]
        results.append(t)
    for i in results:
        print('序号:'+i['index']+'  作者:'+i['author']+' 书名:'+i['book_name']+' 链接:'+i['href'])
    return results

这里将解析的结果存放再resultsresults是一个列表,然后它的每个元素是一个字典,分别存储序号,作者,书名,以及书的链接,这个链接的网页存在着下载地址,下面我们还要将其爬取,解析其下载地址。

下载模块:

def download(number,results,base_url,headers):
    number=int(number)-1
    extend_url=results[number]['href']
    url=base_url+extend_url
    headers['Referer']=url
    response=requests.get(url)
    content=response.content.decode('utf-8')
    out=re.findall('get_down_url.*?,\'(.*?)\',',content,re.S)
    download_url=out[0]
    print(download_url)
    print('正在下载请耐心等候。。。。。。。\n')
    filename=results[number]['book_name']+'.txt'
    try:
        r=requests.get(download_url,headers=headers)
        if r.status_code==200:
            with open(filename,'wb') as f:
                f.write(r.content)
        else:
            print(r.status_code)
    except RequestException as e:
        print(e)
    return filename 

首先我们从链接地址中得到网页,然后用正则表达式解析网页获得下载地址,然后将其写入文件,最后使用我们封装的send_email函数将其发送至kindle

总结:解析网页这边使用的是正则表达式,发现正则表达式很不方便,很容易写错,十分麻烦。所以推荐再解析库的使用上使用lxml模块,或者使用pyquery模块,两个的解析速度都很快,beautiful soup很慢,而且它的css选择器没有pyquery模块的强大,如果你对jquery熟悉的话,推荐使用pyquery模块。

2.2 检索下载电子书

思路还是和上面的一样,不过再解析html网页我使用的是pyquery模块,它主要是根据css选择节点,进行网页的解析,速度很快,而且很方便。

分页模块

当你搜索一本书的时候,可能相似的书有很多,网页会将其分页,我们使用fiddler分析网页的请求过程,首先网页会将20个书分为一页,然后再get请求的时候会添加一个page字段,所以我们首先得得到一共检索有number本书,然后用math模块的ceil方法,对number/20取上,最后得到网页的页数,我们再迭代对每一页发出请求解析到每本书所在的链接。在做这个模块的时候,我不幸踩到了坑,网页的请求url地址中的word字段编码是gb2312,所以这边需要进行编码。

def page_parse():
    href={}
    name_href={}
    base_url='http://www.qishu.cc/search.asp'
    keyword=input("请输入你要搜索的书籍:\n")
    data={}
    data['word']=keyword.encode('gb2312')
    response=requests.get(base_url,data=data)
    doc=pq(response.text)
    spans=doc('#searchmain .searchResult span:first-child')
    print("一共拥有"+spans.text()+"本书:\n")
    numbers=int(spans.text())
    pages=math.ceil(numbers/20) 
    for i in range(pages):
        i=i+1
        data['page']=str(i)
        new_response=requests.get(base_url,data=data)
        links,names=search(new_response,href,name_href)
    return links,names

检索所有书籍模块
使用循环迭代,将书籍打印出来,并存储所在的页面信息,书所在的链接,名字

def search(response,href,name_href):
    response.encoding='gb2312'
    doc=pq(response.text)
    results=doc('#searchmain .searchTopic').items()
    for result in results:
        a=result.find('a').remove('font')
        result.find('a').remove()
        print('序号   '+result.text().rstrip('、'))
        print('书名   '+a.text())
        print('链接   '+a.attr('href'))
        href[result.text().rstrip('、')]=a.attr('href')
        name_href[result.text().rstrip('、')]=a.text()
    return href,name_href

下载模块

使用上面得到的链接,然后找到书所在的页面,解析下载地址,然后写入文件,返回文件名

def download_search(links,number,filename):
    base_url='http://www.qishu.cc'
    for key,value in links.items():
        if key==number:
            url=base_url+value
    response=requests.get(url)
    response.encoding='gb2312'
    content=pq(response.text)
    temp=content('#downAddress a:gt(0)').remove('b')
    download_url=temp.attr('href')
    try:
        r=requests.get(download_url)
        if r.status_code==200:
            with open(filename,'wb') as f:
                f.write(r.content)
        else:
            print(r.status_code)
    except RequestException as e:
        print(e)
    print('下载完成')
    return filename 

2.3 邮箱推送模块

下面只要将qq邮箱和16位授权码、kindle邮箱地址替换成你的就可以使用了,send_mail我将除了filename之外的所有形参设置成默认参数,这样不用调用的使用给他传值。

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import smtplib
import email.mime.multipart
import email.mime.text
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication

def send_email(filename,smtpHost='smtp.qq.com', sendAddr='qq邮箱', password='16位授权码', recipientAddrs='kindle邮箱地址', subject='kindle推送', content='推送小说'):
    msg = email.mime.multipart.MIMEMultipart()
    msg['from'] = sendAddr
    msg['to'] = recipientAddrs
    msg['subject'] = subject
    content = content
    txt = email.mime.text.MIMEText(content, 'plain', 'utf-8')
    msg.attach(txt)


    part = MIMEApplication(open(filename,'rb').read())
    part.add_header('Content-Disposition', 'attachment', filename=filename)
    msg.attach(part)

    smtp = smtplib.SMTP()
    smtp.connect(smtpHost, '25')
    smtp.login(sendAddr, password)
    smtp.sendmail(sendAddr, recipientAddrs, str(msg))
    print("发送成功!")
    smtp.quit()

总结:还可以在爬取分页数据的时候,采用多线程,这样就会速度很快,然后下载的时候可以做个进度条。


 上一篇
sqlmap工具总结 sqlmap工具总结
1. 三种注入方式检测get方式注入 python2 sqlmap.py -u http://127.0.0.1/sqli-labs/Less-1/?id=2 post方式注入 python2 sqlmap.py -u http://127
2019-04-12 starjian
下一篇 
使用python爬虫爬取猫眼电影 使用python爬虫爬取猫眼电影
1. 环境以及工具使用我们使用的是python3的requests库,requests比urllib更加的方便,同时使用正则表达式作为解析的工具。 在工具方便这次我们使用一个新的抓包工具用来对http协议的包进行分析 1.1 工具介绍Fid
2019-04-12 starjian
  目录