十、豆瓣读书爬虫

用了一上午的时间做了个这个,还是比较简单的。多练练,总会进步。遇到了很多问题,庆幸自己都解决了。

我的过程是:(python3)

1、先将豆瓣读书的所有标签以每行七个打印到页面上。

2、输入要爬取标签的名字,可以输入多个。

3、输入你想要爬取多少页。

4、爬取每本书的书名、作者、出版社、评分、评价人数、图书的url,封面图片的url

5、以标签名作为文件名存到本地文件中。(本来想保存到Excel中的,但是我下载的Python是最新版本,自己知道的库中,没有合适的)

6、把这些用到我练习的网站(用的Django)中,在Django下写一个脚本,将数据导入数据库

import time
import random
import requests
from bs4 import BeautifulSoup


def printTag():
    '''
    以每行七个、打印标签名,
    :return:
    '''
    response = requests.get('https://book.douban.com/tag/?view=cloud')

    soup = BeautifulSoup(response.text, 'lxml')

    tags = soup.select('.tagCol td a')
    tag_list = []
    start = 0
    end = 7
    for tag in tags:
        tag_list.append(tag.get_text())
    tr, td = divmod(len(tag_list), 7)
    # print(tr, td)
    if td != 0:
        tr = tr + 1
    for i in range(tr):
        print(tag_list[start:end])
        start, end = end, end + 7


def devideTag(book_tag_list):
    # 操作全局变量
    global START_PAGE
    for book_tag in book_tag_list:
        # 每个标签下的书籍
        bookSpider(book_tag)
        # 每爬完一个标签,将起始页归为1
        START_PAGE = 1


def bookSpider(book_tag):
    global START_PAGE

    # 设置请求头
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}

    # 设置循环终止条件,小于你要爬取的页数,或遇到错误终止
    while START_PAGE <= int(end):
        # 分析一下url ,找规律
        param = 'start=' + str((START_PAGE - 1) * 20) + '&type=T'
        url = url = 'https://book.douban.com/tag/%s/' % book_tag
        # 休息一下,哈哈
        time.sleep(random.random() * 5)

        # 如果网址有错误,报错、退出
        try:
            # 拼接url
            response = requests.get(url, params=param, headers=headers)

        except Exception as e:
            print(e)
            break
        # 用Beautifulsoup解析这个页面
        soup = BeautifulSoup(response.text, 'lxml')
        # 这个页面是否有内容,如果没有退出
        try:
            content = soup.find_all('li', class_='subject-item')
        except:
            print('此页无内容')
            break

        # 获取你想要的数据
        loadData(content, book_tag)


def loadData(content, book_tag):
    global START_PAGE

    for book_info in content:
        # 书名需要处理一下,split以空格分隔,移除空字符串,返回一个列表
        f_title = book_info.select('.info h2')[0].get_text().split()
        # 连接字符串
        b_title = ''.join(f_title)
        pub_info= book_info.select('.info .pub')[0].get_text().strip()
        desc_list = pub_info.split('/')
        book_url = '图书链接地址' + book_info.select('.info h2 a')[0].get('href')
        pic_url = '图片链接地址' + book_info.select('.pic img')[0].get('src')
        try:
            author_info = '作者/译者: ' + '/'.join(desc_list[0:-3])
        except:
            author_info = '作者/译者: 暂无'
        try:
            pub_info = '出版信息: ' + '/'.join(desc_list[-3:])
        except:
            pub_info = '出版信息: 暂无'
        try:
            rating = book_info.select('.info .rating_nums')[0].get_text().strip()
        except:
            rating = '0.0'
        try:
            # people_num = book_info.findAll('span')[2].string.strip()
            people_num = book_info.select('.info .pl')[0].get_text().strip()

        except:
            people_num = '0'

        # 以标签为文件名,保存起来
        with open('%s.txt' % book_tag,'a', encoding='utf8') as f:
            f.write('%s  %s  %s  %s  %s  %s  %s' % (b_title, rating, people_num, author_info, pub_info,book_url,pic_url))
            f.write('\n')
    # 打印出下载的页面
    print('Downloading Information From Page %d' % START_PAGE)
    # 页数加1
    START_PAGE += 1


if __name__ == '__main__':
    START_PAGE = 1
    book_tag_list = []
    # 打印的标签名
    printTag()
    while True:
        inp = input('请输入要抓取的标签名(q退出):')
        if inp.lower() == 'q':
            break
        book_tag_list.append(inp)
    # 页数:
    end = input('想抓取的页数:')
    # 抓取每个标签底下的书籍
    devideTag(book_tag_list)

结果:

['小说', '日本', '历史', '外国文学', '文学', '中国', '心理学']
['漫画', '随笔', '哲学', '中国文学', '推理', '绘本', '美国']
['经典', '爱情', '日本文学', '传记', '文化', '散文', '社会学']
['青春', '英国', '旅行', '科普', '东野圭吾', '科幻', '生活']
.........................................
['散文随笔', '国学', '时间管理', '当代文学', '日系推理', '心灵', '科幻小说']
['法国文学', '温暖', '政治哲学', '科学', '英文原版', '灵修', '毛姆']
['BL']
请输入要抓取的标签名(q退出):国学
请输入要抓取的标签名(q退出):轻小说
请输入要抓取的标签名(q退出):q
想抓取的页数:40
Downloading Information From Page 1
Downloading Information From Page 2
..............
Downloading Information From Page 39
Downloading Information From Page 40

Downloading Information From Page 1
Downloading Information From Page 2
..........................
Downloading Information From Page 39
Downloading Information From Page 40 

写一个脚本,导入Django的数据库中:

#!/usr/bin/env python
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
 
def main():
    from blog.models import Book
    f = open('轻小说.txt')
    BookList = []
    for line in f:
        title,author............ = line.split( )
        book = Book(title=title,author=author..........)
        BookList.append(book)
    f.close()
     
    Blog.objects.bulk_create(BlogList)
 
if __name__ == "__main__":
    main()
    print('Done!')

遇到的问题:

1、最大的问题就是将数据写入本地文件中,出错:

'gbk' codec can't encode character解决方法 使用Python写文件的时候,或者将网络数据流写入到本地文件的时候,大部分情况下会遇到:UnicodeEncodeError: 'gbk' codec can't encode character '\xa0' in position ... 这个问题。 网络上有很多类似的文件讲述如何解决这个问题,但是无非就是encode,decode相关的,这是导致该问题出现的真正原因吗?不是的。 很多时候,我们使用了decode和encode,试遍了各种编码,utf8,utf-8,gbk,gb2312等等,该有的编码都试遍了,可是编译的时候仍然出现: UnicodeEncodeError: 'gbk' codec can't encode character '\xa0' in position XXX。 崩溃了。     在windows下面编写python脚本,编码问题很严重。     将网络数据流写入文件时时,我们会遇到几个编码:     1: #encoding='XXX' 这里(也就是python文件第一行的内容)的编码是指该python脚本文件本身的编码,无关紧要。只要XXX和文件本身的编码相同就行了。 比如notepad++ "格式"菜单里面里可以设置各种编码,这时需要保证该菜单里设置的编码和encoding XXX相同就行了,不同的话会报错     2:网络数据流的编码 比如获取网页,那么网络数据流的编码就是网页的编码。需要使用decode解码成unicode编码。     3:目标文件的编码 要将网络数据流的编码写入到新文件,那么我么需要指定新文件的编码。写文件代码如: 复制代码代码如下: f.write(txt)   ,那么txt是一个字符串,它是通过decode解码过的字符串。关键点就要来了:目标文件的编码是导致标题所指问题的罪魁祸首。如果我们打开一个文件: 复制代码代码如下: f = open("out.html","w")   ,在windows下面,新文件的默认编码是gbk,这样的话,python解释器会用gbk编码去解析我们的网络数据流txt,然而txt此时已经是decode过的unicode编码,这样的话就会导致解析不了,出现上述问题。 解决的办法就是,改变目标文件的编码: 复制代码代码如下: f = open("out.html","w",encoding='utf-8')   。这样,问题将不复存在。

2、获取的标签列表很多,不能每个标签打印一次,独占一行。也不能一次都打出,这么多标签占一行:

有点像网页分页的问题,自己也是按照这种思路解决的,用切片的方式从列表中取出

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏ascii0x03的安全笔记

PySide——Python图形化界面入门教程(六)

PySide——Python图形化界面入门教程(六)             ——QListView和QStandardItemModel 翻译自:http:/...

3946
来自专栏菜鸟致敬

【菜鸟致敬】爬取豆瓣的短评(⊙o⊙)…

因为需要一点数据,所以就去爬取一点豆瓣短评的数据。因为短评页面是生成的静态html,还是很容易爬虫数据的,其中发现了问题每部电影短评在同一条件下最多只能查阅50...

1161
来自专栏DeveWork

【译】WordPress 中的50个过滤器(1):何为过滤器?

这篇文章是来自tutsplus 上系列文章《50 Filters of WordPress》的开篇文,系列文章还在陆续发表中。Jeff 打算借助Github 进...

1899
来自专栏高性能分布式系统设计

Pandas 简介

Pandas 是Python的数据处理包,全名:Python Data Analysis Library 是连接 SciPy 和 NumPy 的一种工具。特色...

3465
来自专栏更流畅、简洁的软件开发方式

【自然框架】之数据访问 —— 再小的类库也需要设计。

  以前也写过几篇关于数据访问的,这里是最新的总结。麻雀虽小五脏俱全,数据访问也许不起眼,但是也要好好的设计一翻。从2004年开始用自己的数据访问,一直到现在,...

2529
来自专栏北京马哥教育

一致性hash原理与实现

一、背景介绍 memcached的分布式 memcached虽然称为“分布式”缓存服务器,但服务器端并没有“分布式”功能。服务器端内存存储功能,其实现非常简单。...

3867
来自专栏有趣的django

Django+xadmin打造在线教育平台(九)

代码 github下载 十二、首页和全局404,500配置 12.1.首页功能 Course添加一个字段 is_banner = models.Boolean...

6006
来自专栏Crossin的编程教室

Python 爬虫爬取美剧网站

一直有爱看美剧的习惯,一方面锻炼一下英语听力,一方面打发一下时间。之前是能在视频网站上面在线看的,可是自从广电总局的限制令之后,进口的美剧英剧等貌似就不在像以前...

4087
来自专栏Flutter入门

偶遇FFMpeg(四)-FFmpeg PC端推流

之前在Android集成FFmpeg。主要还是基于命令行的方式进行操作。刚刚好最近又在研究推流相关的东西。看了一些博文。和做了一些实践。 就希望通过本文记录袭...

4563
来自专栏信安之路

奇淫异巧之 PHP 后门

早上看了一位小伙伴在公众号发的文章《php 后门隐藏技巧》,写的挺好,其中有一些姿势是我之前没见到过了,学到很很多。同时,这篇文章也引发了自己的一点点思考:“ ...

1810

扫码关注云+社区

领取腾讯云代金券