Python爬取豆瓣指定书籍的短评
Python爬取豆瓣指定书籍的短评
#!/usr/bin/python
# coding=utf-8
import re
import sys
import time
import random
import urllib
import urllib2
import MySQLdb
# 爬取豆瓣评论
class Douban:
# 构造函数
def __init__(self, url, name):
# 采集的地址
#self.url = 'https://book.douban.com/subject/26356948/comments/hot'
self.url = url
# 存储的文件名
self.filename = str(name) + '.txt'
# 数据库配置
self.database = {
'host': '127.0.0.1',
'username': 'root',
'password': 'root',
'database': 'douban',
'charset': 'utf8',
'table': str(name),
}
# HTTP请求超时
self.http_timeout = 10
# 请求计数器
self.request_counter = 0
# 错误代码计数器
self.error_counter = 0
# 数据库第一次错误
self.db_error_first = True
# 替换换行符
def replaceSpace(self, string):
string = string.replace('\r\n', ' ')
string = string.replace('\n', ' ')
string = string.replace('\r', ' ')
return string
# 清洗单页评论,返回为单条评论的列表
def getCommentsPage(self, url):
user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36'
headers = {'User-Agent': user_agent}
request = urllib2.Request(url, headers=headers)
try:
response = urllib2.urlopen(request, timeout=self.http_timeout)
comments_page_raw = response.read()
reg = r'.*?<li.*?class="comment-item".*?>(.*?)</li>.*?'
comments_page = re.findall(reg, comments_page_raw, re.I | re.M | re.S)
return comments_page
except urllib2.HTTPError, e:
errmsg = 'HTTP Error: ' + e.code + ',' + e.reason
print unicode(errmsg, 'utf-8')
if e.code == 403 or e.code == '403':
# 服务器拒绝服务,等等...等等... 等120秒
print unicode('服务器拒绝服务,等等...等等... 等120秒', 'utf-8')
time.sleep(120)
response = urllib2.urlopen(request, timeout=self.http_timeout)
comments_page_raw = response.read()
reg = r'.*?<li.*?class="comment-item".*?>(.*?)</li>.*?'
comments_page = re.findall(reg, comments_page_raw, re.I | re.M | re.S)
return comments_page
elif e.code == 404 or e.code == '404':
# not found... 已爬取完毕,结束程序
print unicode('not found... 已爬取完毕,结束程序', 'utf-8')
# 结束程序
sys.exit(0)
else:
print unicode('HTTP 未知错误', 'utf-8')
# 错误次数累加
self.error_counter += 1
# 判断是否进行中断
if self.error_counter == 20:
info = '错误次数已达%d次,结束程序' % self.error_counter
print unicode(info, 'utf-8')
sys.exit(1)
# 清洗单条评论,返回单条评论的昵称、头像、内容...的列表
def getCommentsItem(self, comment_raw):
# 昵称, 豆瓣主页,头像, 点赞, 星级评价, 日期, 评价内容
reg = r'<div.*?<a.*?title="(.*?)" href="(.*?)".*?<img src="(.*?)".*?class="vote-count">(.*?)</span>.*?<span.*?title="(.*?)"></span>.*?<span>(.*?)</span>.*?<p class="comment-content">(.*?)</p>.*?</div>'
# 匹配
comment = re.findall(reg, comment_raw, re.I | re.M | re.S)
# 返回数据
return comment
# 操作单页内容
def getPageContent(self, url):
# 获取单页评论的列表
comments = self.getCommentsPage(url)
# 迭代出单条评论
for comment in comments:
# 清洗单条评论
contents = self.getCommentsItem(comment)
for content in contents:
# 存到文件
self.saveFile(content)
# 存到数据库
self.saveDatabase(content)
# 测试输出
self.testPrint(content)
# 测试输出
def testPrint(self, content):
print content[0]
print content[1]
print content[2]
print content[3]
print content[4]
print content[5]
print self.replaceSpace(content[6])
print '\n'
# 保存到数据库
def saveDatabase(self, content):
# 打开数据库连接
db = MySQLdb.connect(
self.database['host'],
self.database['username'],
self.database['password'],
self.database['database'],
charset=self.database['charset'],
)
# 获取游标
cursor = db.cursor()
# SQL语句
sql = "INSERT INTO %s (username, homepage, header_img, like_num, star_rating, publish_date, comment_content) VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s');" % (
self.database['table'], content[0], content[1], content[2], content[3], content[4], content[5],
self.replaceSpace(content[6]))
# print sql
# 添加数据
try:
# 执行SQL语句
cursor.execute(sql)
# 提交到数据库执行
db.commit()
except:
# 回滚
db.rollback()
# 判断数据库是否是第一次错误
if self.db_error_first:
print 'Failed to find database table, Trying to create database [%s].\n\n' % self.database['table']
time.sleep(2)
# 创建数据表的SQL语句
create_table = '''CREATE TABLE IF NOT EXISTS %s (
id INT(6) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '评论id',
username VARCHAR(50) NOT NULL DEFAULT '' COMMENT '用户名',
homepage VARCHAR(200) NOT NULL DEFAULT '' COMMENT '豆瓣主页',
header_img VARCHAR(200) NOT NULL DEFAULT '' COMMENT '头像',
like_num INT(6) NOT NULL DEFAULT '0' COMMENT '点赞量',
star_rating VARCHAR(10) NOT NULL DEFAULT '' COMMENT '星级评价',
publish_date VARCHAR(12) NOT NULL DEFAULT '' COMMENT '发表日期',
comment_content VARCHAR(2000) NOT NULL DEFAULT '' COMMENT '评价内容'
)DEFAULT CHARSET=utf8;''' % self.database['table']
# 执行SQL语句
cursor.execute(create_table)
db.commit()
# 设定数据库错误的标志
self.db_error_first = False
# 执行异常前的SQL语句
cursor.execute(sql)
db.commit()
else:
# 数据库非第一次放生错误
print 'Database Error'
# 关闭数据库连接
db.close()
# 保存到文件
def saveFile(self, content):
# 一行数据(即一条评论)
# item = content[5] + '\t' + content[4] + '\t' + content[3] + '\t' + content[0] + '\t\t' + content[1] + '\t\t' + content[2] + '\t\t' + content[6] + '\r\n'
item = self.replaceSpace(content[6]) + '\r\n'
# 尝试去将文件存储到文件
try:
# 打开文件
file = open(self.filename, 'ab+')
# 写入
file.write(item)
# 关闭文件
file.close()
except:
# 发生错误
print 'File Error'
# 入口函数
def start(self, first=1, last=10):
# 按设定页码,采集数据
for page in range(first, last + 1):
# 时间戳
timestrap = str(int(time.time())) + '000'
# get参数
getdata = {'p': page, '_': timestrap}
# URL编码的url
url = self.url + '?' + urllib.urlencode(getdata)
# 开始采集的提示信息
info_start = "----- ----- ----- [INFO] 正在获取第%d页 ----- ----- ----- \n%s\n" % (page, url)
print unicode(info_start, 'utf-8')
# 休眠2秒
time.sleep(2)
# 获取第page页的内容
self.getPageContent(url)
# 结束采集的提示信息
info_end = "----- ----- ----- [INFO] 第%d页已加载完毕 ----- ----- ----- \n" % page
print unicode(info_end, 'utf-8')
# 采集次数自增
self.request_counter += 1
# 判断采集次数,并根据条件休眠
if self.request_counter % 50 == 0:
# 特定情况下,休息60秒
print unicode('\n每采集50页,休息60秒...\n', 'utf-8')
# 休眠
time.sleep(60)
else:
# 普通情况下,休息随机的时间
_time = 5 + int(random.uniform(0, 6))
print unicode('sleep %ds\n\n\n' % _time, 'utf-8')
# 休眠
time.sleep(_time)
# 摆渡人
#url = 'https://book.douban.com/subject/26356948/comments/hot' # 短评地址
#name = 'baiduren' # 名称
# 芳华
url = 'https://book.douban.com/subject/27010212/comments/hot' # 短评地址
name = 'fanghua' # 名称
# 实例化爬虫对象
bookSpyder = Douban(url, name)
# 设定爬取的页码范围,并开始爬取
bookSpyder.start(1, 333)
Python爬取豆瓣指定书籍的短评的更多相关文章
- 利用Python爬取豆瓣电影
目标:使用Python爬取豆瓣电影并保存MongoDB数据库中 我们先来看一下通过浏览器的方式来筛选某些特定的电影: 我们把URL来复制出来分析分析: https://movie.douban.com ...
- Python爬取豆瓣电影top
Python爬取豆瓣电影top250 下面以四种方法去解析数据,前面三种以插件库来解析,第四种以正则表达式去解析. xpath pyquery beaufifulsoup re 爬取信息:名称 评分 ...
- Python爬取豆瓣《复仇者联盟3》评论并生成乖萌的格鲁特
代码地址如下:http://www.demodashi.com/demo/13257.html 1. 需求说明 本项目基于Python爬虫,爬取豆瓣电影上关于复仇者联盟3的所有影评,并保存至本地文件. ...
- python 爬取豆瓣书籍信息
继爬取 猫眼电影TOP100榜单 之后,再来爬一下豆瓣的书籍信息(主要是书的信息,评分及占比,评论并未爬取).原创,转载请联系我. 需求:爬取豆瓣某类型标签下的所有书籍的详细信息及评分 语言:pyth ...
- python 爬取豆瓣电影短评并wordcloud生成词云图
最近学到数据可视化到了词云图,正好学到爬虫,各种爬网站 [实验名称] 爬取豆瓣电影<千与千寻>的评论并生成词云 1. 利用爬虫获得电影评论的文本数据 2. 处理文本数据生成词云图 第一步, ...
- python 爬取豆瓣电影评论,并进行词云展示及出现的问题解决办法
本文旨在提供爬取豆瓣电影<我不是药神>评论和词云展示的代码样例 1.分析URL 2.爬取前10页评论 3.进行词云展示 1.分析URL 我不是药神 短评 第一页url https://mo ...
- python爬取豆瓣视频信息代码
目录 一:代码 二:结果如下(部分例子) 这里是爬取豆瓣视频信息,用pyquery库(jquery的python库). 一:代码 from urllib.request import quote ...
- Python爬取豆瓣音乐存储MongoDB数据库(Python爬虫实战1)
1. 爬虫设计的技术 1)数据获取,通过http获取网站的数据,如urllib,urllib2,requests等模块: 2)数据提取,将web站点所获取的数据进行处理,获取所需要的数据,常使用的技 ...
- 零基础爬虫----python爬取豆瓣电影top250的信息(转)
今天利用xpath写了一个小爬虫,比较适合一些爬虫新手来学习.话不多说,开始今天的正题,我会利用一个案例来介绍下xpath如何对网页进行解析的,以及如何对信息进行提取的. python环境:pytho ...
随机推荐
- OneAPM 获得“2018中国 IT 服务创新奖”,彰显技术创新实力
6月30日,主题为“智能服务 数字中国”的中国 IT 服务创新大会在京召开.作为第22届中国国际软件博览会的重头戏,本次大会由工业和信息化部.北京市人民政府共同主办,中国电子工业标准化技术协会信息技术 ...
- 口碑点餐相关问题FAQ
1.菜品上传中:出现重复错误或者违禁词 检查并修改商家中心本次上传中的重复菜品,或者删除口碑掌柜以及第三方平台已添加的重复菜品(重复菜品临时快捷办法:修改菜品名称) 2.手持pos 打开自动接单,无响 ...
- java----字符串的大写字母右移
import java.util.Scanner; /** * Created by Admin on 2017/3/27. */ public class test02 { public stati ...
- unix2dos和dos2unix处理换行问题
今天同事QQ给发来一个文件内容如下: 希望把文件内容转换为update table_name set col_name=第一列 where col_name=第二列;这种SQL格式,使用UE列模式秒秒 ...
- linux系统/var/log目录下的信息详解
一./var目录 /var 所有服务的登录的文件或错误信息文件(LOG FILES)都在/var/log下,此外,一些数据库如MySQL则在/var/lib下,还有,用户未读的邮件的默认存放地点为/v ...
- Win 10 和 Linux 双系统,从硬盘删除Linux分区,Win 10引导修复
由于安装双系统后,Linux 用的比较少.因此,从Win 10 磁盘管理中删除了linux 占用的磁盘空间,重启后无法进入win 10 ,出现如下情况: 有人提出,此时需要重装系统,并不用如此麻烦,通 ...
- 简述KVM架构和Xen架构
暑假最后一篇更新,因为,,,明天我就回学校了. 以下均为个人理解,如果有不对的地方还望各位dalao不吝赐教. 虚拟化 虚拟化是通过Hypervisor程序实现的,Hypervisor的作用是将硬件虚 ...
- LeetCode算法题-Nth Digit(Java实现)
这是悦乐书的第215次更新,第228篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第83题(顺位题号是400).找到无限整数序列的第n个数字1,2,3,4,5,6,7,8 ...
- Python爬虫-04:贴吧爬虫以及GET和POST的区别
目录 1. URL的组成 2. 贴吧爬虫 2.1. 只爬贴吧第一页 2.2. 爬取所有贴吧的页面 3. GET和POST的区别 3.1. GET请求 3.2. POST请求 3.3. 有道翻译模拟发送 ...
- 【汤鸿鑫 3D太极】5年目标规划(基本功、套路、实战搏击)
[5年目标]在基本功的基础上,每年完成一个套路或实战搏击的学习研究. [中小学2年]三段九节 + 2套路. [高中的3年]太极十三势 + 1套路 + 推手 + 搏击. 1.中小学阶段-可自学 (1)基 ...