爬了个豆瓣小说

书友群里经常有人闹书荒,求推荐,于是我想了想,把豆瓣里面的小说们都爬了下来。

还是用的老方法,urllib+正则提取,没有用到scrapy这么高科技的东西(其实是因为windows下太难装了)。不过这一次我用的是python3。其实我只是在网上找了一下http头应该怎么写,那个网页用的是python3的,我就也用了。python2应该类似。其实方法还是相当简单的。

首先看看,豆瓣上面标签为“小说”的书的地址:

https://book.douban.com/tag/%E5%B0%8F%E8%AF%B4

试着前后翻翻页,能看到这个url后面加上了

?start=0&type=T

这两个get的参数,其中start表示从第几本书开始(20本书一页),type表示书的排序方式。其实豆瓣有默认的按照评分排序,但是并不准,所以,就按默认排序吧,下载下来自己手动sort一下就好了!

首先抓下来一个网页:

def get_html(url):
    """
    抓取网页
    """
    cj = http.cookiejar.CookieJar()
    opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
    opener.addheaders = [(‘User-Agent‘,
                          ‘Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36‘),
                         (‘Cookie‘, ‘4564564564564564565646540‘)]

    urllib.request.install_opener(opener)

    try:
        while True:
            page = urllib.request.urlopen(url)
            html = page.read().decode("utf-8")
            page.close()

            anti_spider = re.findall(r‘403 Forbidden‘, html)

            if anti_spider:
                print("反爬虫了,休息10分钟...")
                time.sleep(600)
            else:
                return html
    except Exception as e:
        print(e)
        sys.exit()

对这一个网页中进行正则提取。在提取的过程中,我发现只能看到书籍的链接和书名,其他内容比如作者名和评分什么的,都是通过js动态生成的。噗。那就只好通过链接来获得每一本书的作者和评分了。

def get_books_info(html):
    """
    获得一页上面所有书的信息
    """
    books = []
    one_page_books = re.findall(r‘href="(https://book\.douban\.com/subject/\d+/)" title="(.*?)"‘, html)
    for url, name in one_page_books:
        one_book_html = get_html(url)
        # print one_book_html
        author, score = get_book_info(one_book_html)
        # print author, score
        if not author and not score:
            break

        name = "《" + name + "》"
        print(‘{"name": %s, "author": %s, "score": %s, "url": %s}‘ % (name, author, score, url))
        books.append({"name": name, "author": author, "score": score, "url": url})
        # print("别爬太快,休息一下")
        time.sleep(3)

    return books

有一件很重要的事应该要说一下,做爬虫,一定要记得sleep,不仅仅是伪装人类行为迷惑反爬虫,也是对网站的尊重。互联网上各种网站的访问已经有90%是爬虫了,其中大部分都是搜索引擎,我们就不要再给人家网站添麻烦了——处理你家爬虫是要消耗服务器资源的,连续不停的爬是不文明的行为!我在开始的时候没有sleep,结果在调试的过程中爬了几百个网页,然后被反爬虫了。好吧,应该向豆瓣道个歉。人家已经很客气了,让我放肆的爬了几百本书,才把我封掉,而且豆瓣本身提供了给爬虫使用的API,我还自己费劲的写正则。

下面是从一本书籍的页面中获得作者和评分:

def get_book_info(html):
    """
    获得一本书的评分和作者
    """
    try:
        score = re.findall(r‘property="v:average"> (.*?) </strong>‘, html)[0]
        author = re.findall(r‘<span class="pl"> 作者</span>[\w\W]*?<a class="" href=".*?">(.*?)</a>‘, html)[0]
        return author, score
    except Exception as e:
        print("评分和作者出了点小问题:")
        print(e)
        return "", ""

这段没什么好说的,全是偷懒写法的正则。

把上面的几个函数组合起来:

def main():
    page = 0
    books = []
    while True:
        url = "https://book.douban.com/tag/%%E5%%B0%%8F%%E8%%AF%%B4?start=%s&type=T" % str(page)

        html = get_html(url)
        one_page_books = get_books_info(html)

        books.extend(one_page_books)

        if len(one_page_books) == 0:
            print("好啦只有这些书啦~")
            break

        page += 20

    # 有的书评价人数太少,没有分数,怕信息不全,补全一下
    for b in books:
        b["author"] = b["author"] or "(佚名)"
        b["score"] = b["score"] or "0.0"

    # 排序
    books.sort(key=lambda x: float(x["score"]), reverse=True)

    # 保存书籍信息
    with open("douban.csv", "w", encoding="gbk", errors="ignore") as f:
        line_template = "%(name)s,%(author)s,%(score)s,%(url)s\n"
        f.write(line_template % ({"name": "书名", "author": "作者", "score": "豆瓣评分", "url": "豆瓣链接"}))
        for book in books:
            f.write(line_template % book)

最后在open的时候其实遇到了点小麻烦:网页是utf-8编码的,我爬下来网页之后就直接decode("utf-8")了。但是在windows下,open("douban.csv", "w")函数默认使用的中文编码方式是gbk,于是write时候就直接抛了个中文编码的异常。查到这个原因之后,我就加上了encoding="utf-8"这个参数。这回倒是成功保存了,但是csv默认用excel打开时还是乱码呀!因为excel使用gbk来打开的。倒是可以手动先用记事本打开,另存为选择ANSI来解决,但是我表示不屑于用这种方式,在群里问了问,有同学告诉我用ignore,燃鹅,在python3里面还encode/decode写一串,不是丑死!于是再百度,终于查到在python3中,open函数里面就可以直接加errors="ignore"这个参数。

搞定~最后的效果:

就酱。代码已上传github(https://github.com/anpengapple/doubanbooks)。有需要的同学拿去玩~其实还是不完美:第一,没有小说的详细类型;第二,只有小说而没有别的书;第三,没有直接保存excel,还得自己排版。将来有闲心可以再改改。(话说一直没学写excel也是因为懒,感觉全是体力劳动,完全没有技巧可言,不好玩)。

时间: 2024-10-19 12:39:09

爬了个豆瓣小说的相关文章

如何用python爬虫从爬取一章小说到爬取全站小说

前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取http://t.cn/A6Zvjdun 很多好看的小说只能看不能下载,教你怎么爬取一个网站的所有小说 知识点: requests xpath 全站小说爬取思路 开发环境: 版 本:anaconda5.2.0(python3.6.5) 编辑器:pycharm 第三方库: requests parsel 进行

Python爬虫之利用BeautifulSoup爬取豆瓣小说(三)——将小说信息写入文件

1 #-*-coding:utf-8-*- 2 import urllib2 3 from bs4 import BeautifulSoup 4 5 class dbxs: 6 7 def __init__(self): 8 self.pageIndex = 0 9 self.enable = True 10 self.file = None 11 self.content = [] 12 13 14 #获取html页面的内容 15 def getPage(self, pageIndex): 1

用crawl spider爬取起点网小说信息

起点作为主流的小说网站,在防止数据采集反面还是做了准备的,其对主要的数字采用了自定义的编码映射取值,想直接通过页面来实现数据的获取,是无法实现的. 单独获取数字还是可以实现的,通过requests发送请求,用正则去匹配字符元素,并再次匹配其映射关系的url,获取到的数据通过font包工具解析成字典格式,再做编码匹配,起点返回的编码匹配英文数字,英文数字匹配阿拉伯数字,最后拼接,得到实际的数字字符串,但这样多次发送请求,爬取效率会大大降低.本次集中爬取舍弃了爬取数字,选择了较容易获取的评分数字.评

爬虫到百度贴吧,爬取自己的小说

最近在微信里看了一个小说叫<阴阳代理人>的,看到一半,发现断了,作者说把后面的部分放到了百度贴吧,去了贴吧发现,文章看起来比较费劲,乱糟糟的,所以为了我的小说,弄个了爬虫,去给我弄下来. #!/user/bin/env python # -*- coding:utf-8 -*- import urllib2 import urllib import re #小说章节类 class ZHANGJIE:     #初始化传入地址     def __init__(self,zjUrl,Num):

爬虫到百度贴吧,爬去自己的小说

最近在微信里看了一个小说叫<阴阳代理人>的,看到一半,发现断了,作者说把后面的部分放到了百度贴吧,去了贴吧发现,文章看起来比较费劲,乱糟糟的,所以为了我的小说,弄个了爬虫,去给我弄下来. #!/user/bin/env python # -*- coding:utf-8 -*- import urllib2 import urllib import re #小说章节类 class ZHANGJIE:     #初始化传入地址     def __init__(self,zjUrl,Num):

Python爬取全书网小说,免费看小说

什么是网络爬虫 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用的名字还有蚂蚁.自动索引.模拟程序或者蠕虫. 环境:Python3.6+Windows 开发工具:你喜欢用哪个就用哪个,你开心就好! 模块: 1 import urllib.request 2 3 import re 主要思路: 1 获取主页源代码 2 获取章节超链接 3 获取章节超链接源码 4 获取小说内容 5 下载,文

Python urllib2爬虫豆瓣小说名称和评分

#-*- coding:utf-8 -*- import urllib2 import re url = 'https://book.douban.com/tag/%E5%B0%8F%E8%AF%B4' request = urllib2.Request(url) urlopen = urllib2.urlopen(request) content = urlopen.read() reg_0 = re.findall(r'title.+"\s*on', content) reg_1 = re.

爬虫实践-爬取起点中文网小说信息

qidian.py: import xlwtimport requestsfrom lxml import etreeimport time all_info_list = [] def get_info(url): html = requests.get(url) selector = etree.HTML(html.text) infos = selector.xpath('//ul[@class="all-img-list cf"]/li') for info in infos:

连续爬20多本小说(第二代)

用css选择器的时候有点生疏 1 import requests 2 from bs4 import BeautifulSoup 3 def get_url_list(url): 4 content = requests.get(url).content 5 soup = BeautifulSoup(content,'lxml') 6 list = [] 7 for i in soup.select('#list dl dd a'): 8 temp = url+i.get('href') 9 l