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);
上一篇: 记录pyquery选取不到原生标签问题
下一篇: PyQuery 用法和实例