python爬虫爬取豆瓣读书

python的课程设计,我爬取的是豆瓣的图书

设计题目:  豆瓣读书的Python爬虫

一、需求分析

由于豆瓣上的图书良莠不齐,很难一下选择适合我们的图书,所以我想通过Python的爬虫程序,实现对豆瓣读书页面信息的抓取,获取图书的信息,并对一部分图书进行分析,同时,为了防止以后如果需要做数据对比而又再费时间和精力去爬取数据,我们应将每次爬取的数据存入到设计好的相关的数据库中,以备不时之需。

二、设计内容

本次爬的书籍分类为小说,散文,自传,具体信息为他们的书名、评分、评价条目(在老师的指导下我又对评价进行细化,分成五个部分:五星好评、四星好评、三星好评、两星好评、一星好评)、作者、出版社信息、出版时间、价格。具体设计如下:

 

1. 数据爬虫结构

首先,创建主方法,通过访问给定的url连接,来获取当前网页的内容,并在内容中筛选出自己需要的信息,由于有些信息包含在图书的嵌套连接中,所以需要创建一个子方法,把抓取出来的嵌套连接进行访问,再提取出需要的信息作为返回值返回,最后将全部的数据存入数据库。

 

2. 数据存储方案

这里我采用的数据库是MySQL数据库,首先在数据库中创建好包含相应的信息的表,然后在python程序中我们连接好数据库,并将爬取到的数据信息存入数据库,最后通过数据库的sql语句进行筛选。

 

3. 数据分析方案

由于条件有限,本次数据分析我主要利用的是网上的在线分析工具:图标秀,他是通过传入excel表信息进行数据分析,于是我将用sql语句筛选出来的信息复制到excel中,再将excel上传到该在线分析工具上从而生成数据分析图。

代码:

# -*- coding: UTF-8 -*-
# encoding: utf-8
import sys
import time
import urllib
import pymysql
import importlib
import requests
import numpy as np
from bs4 import BeautifulSoup
from openpyxl import Workbook, comments

importlib.reload(sys)
import judege

# Some User Agents
hds = [{'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}, \
{'User-Agent':'Mozilla/5.0 (Windows NT 6.2) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.12 Safari/535.11'}, \
{'User-Agent': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)'}]


def book_spider():
    #起始页数
    page_num = 1;
    #连接数据库
    conn = pymysql.connect(host='localhost', user='用户名', password='密码',
                db='数据库名称', port=3306, charset="utf8")
    cur = conn.cursor()
    while(1):
        #爬取的页面
        url = 'https://www.douban.com/tag/%E5%B0%8F%E8%AF%B4/book?start=0' + str(page_num * 15)
        time.sleep(np.random.rand() * 5)
        # Last Version
        #爬虫的基本操作
        try:
            req = urllib.request.urlopen(url)
            source_code = req.read()
            plain_text = str(source_code, 'utf-8')
        except:
            print("error")
            continue
  
        # #Previous Version, IP is easy to be Forbidden
        # source_code = requests.get(url) 
        # plain_text = source_code.text  
        
        soup = BeautifulSoup(plain_text)
        list_soup = soup.find('div', {'class': 'mod book-list'})
        for book_info in list_soup.findAll('dd'):
            title = book_info.find('a', {'class':'title'}).string.strip()
            desc = book_info.find('div', {'class':'desc'}).string.strip()
            desc_list = desc.split('/')
            book_url = book_info.find('a', {'class':'title'}).get('href')
            author = '/'.join(desc_list[0:-3])
            #这里我对字符串进行了清洗,因为网站上的作者前面都有国籍信息,例如:[美]xxxx.xxxx,但是只有中国的前面什么都没有
            #老师让我将字符串改为一致的,方便之后的数据处理,所以我将名字前面没有国籍信息的加上[中]
            if author[0] != '[':
                author = '[中' + author
            price = desc_list[-1]
            price2 = ""
            #这里我对价格进行处理,因为网上爬下来的价格末尾都带‘元’字,在数据库存储中为了方便之后的数据处理我想将数据存储为float型
            #所以需要去掉末尾的‘元’
            for ii in range(len(price)):
                if price[ii] >= '0' and price[ii] <= '9' or price[ii] == '.' :
                    price2 = price2 + price[ii]
            
            try:
                rating = book_info.find('span', {'class':'rating_nums'}).string.strip()
            except:
                rating = '0.0'
            
    
            people_num = get_people_num(book_url)
            
            
            cur.execute('insert into douban(title,grade,comment,fivestars,fourstars,threestars,twostars,onestar,author,info,time,price)values("%s","%s","%s","%s","%s","%s","%s","%s","%s","%s","%s","%s")'
                        % (title, float(rating), people_num[0], people_num[1], people_num[2], people_num[3], people_num[4], people_num[5], author, desc_list[-3], desc_list[-2], float(price2)))
            conn.commit()
                
        page_num += 1
        #最终爬的页数
        if page_num == 10:
            break
    return 1;

#之后老师的要求是统计五星-一星评分,由于这个信息需要在嵌套的url里,就是在图书的界面中需要点击进具体的图书才可以收集到星级数量

def get_people_num(url):
    comments = [0 for x in range(6)]
    try:
        req = urllib.request.urlopen(url)
        source_code = req.read()
        plain_text = str(source_code, 'utf-8') 
    except:
        print ('error')
    soup = BeautifulSoup(plain_text)
    people_num = soup.find('div', {'class':'rating_sum'}).findAll('span')[1].string.strip()
    fivestars = soup.findAll('span', {'class':'rating_per'})[0].string.strip()
    fourstars = soup.findAll('span', {'class':'rating_per'})[1].string.strip()
    threestars = soup.findAll('span', {'class':'rating_per'})[2].string.strip()
    twostars = soup.findAll('span', {'class':'rating_per'})[3].string.strip()
    onestar = soup.findAll('span', {'class':'rating_per'})[4].string.strip()
    #由于这里面的星级爬到的数据是百分比,所以还是需要进行数据处理,将星级百分比变成小数,再与总评论数相乘就可以得到具体的数量
    fivestars = (int)((float)(people_num) * (float)(fivestars.strip('%')) / 100)
    fourstars = (int)((float)(people_num) * (float)(fourstars.strip('%')) / 100)
    threestars = (int)((float)(people_num) * (float)(threestars.strip('%')) / 100)
    twostars = (int)((float)(people_num) * (float)(twostars.strip('%')) / 100)
    onestar = (int)((float)(people_num) * (float)(onestar.strip('%')) / 100)
    comments[0] = people_num
    comments[1] = fivestars
    comments[2] = fourstars
    comments[3] = threestars
    comments[4] = twostars
    comments[5] = onestar
    return comments


if __name__ == '__main__':
    judege_point = book_spider();
    print(judege_point);
    





                
  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值