python书籍信息爬虫实例


Posted in Python onMarch 19, 2018

python书籍信息爬虫示例,供大家参考,具体内容如下

背景说明

需要收集一些书籍信息,以豆瓣书籍条目作为源,得到一些有效书籍信息,并保存到本地数据库。

获取书籍分类标签

具体可参考这个链接:
https://book.douban.com/tag/?view=type

然后将这些分类标签链接存到本地某个文件,存储内容如下

https://book.douban.com/tag/小说
https://book.douban.com/tag/外国文学
https://book.douban.com/tag/文学
https://book.douban.com/tag/随笔
https://book.douban.com/tag/中国文学
https://book.douban.com/tag/经典
https://book.douban.com/tag/日本文学
https://book.douban.com/tag/散文
https://book.douban.com/tag/村上春树
https://book.douban.com/tag/诗歌
https://book.douban.com/tag/童话
......

获取书籍信息,并保存本地数据库

假设已经建好mysql表,如下:

CREATE TABLE `book_info` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `bookid` varchar(64) NOT NULL COMMENT 'book ID',
 `tag` varchar(32) DEFAULT '' COMMENT '分类目录',
 `bookname` varchar(256) NOT NULL COMMENT '书名',
 `subname` varchar(256) NOT NULL COMMENT '二级书名',
 `author` varchar(256) DEFAULT '' COMMENT '作者',
 `translator` varchar(256) DEFAULT '' COMMENT '译者',
 `press` varchar(128) DEFAULT '' COMMENT '出版社',
 `publishAt` date DEFAULT '0000-00-00' COMMENT '出版日期',
 `stars` float DEFAULT '0' COMMENT '评分',
 `price_str` varchar(32) DEFAULT '' COMMENT '价格string',
 `hotcnt` int(11) DEFAULT '0' COMMENT '评论人数',
 `bookdesc` varchar(8192) DEFAULT NULL COMMENT '简介',
 `updateAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改日期',
 PRIMARY KEY (`id`),
 UNIQUE KEY `idx_bookid` (`bookid`),
 KEY `idx_bookname` (`bookname`),
 KEY `hotcnt` (`hotcnt`),
 KEY `stars` (`stars`),
 KEY `idx_tag` (`tag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='书籍信息';

并已实现相关爬虫逻辑,主要用到了BeautifulSoup包,如下:

#!/usr/bin/python
# coding: utf-8

import re
import logging
import requests
import pymysql
import random
import time
import datetime
from hashlib import md5
from bs4 import BeautifulSoup

logging.basicConfig(level=logging.INFO,
     format='[%(levelname)s][%(name)s][%(asctime)s]%(message)s',
     datefmt='%Y-%m-%d %H:%M:%S')

class DestDB:
 Host = "192.168.1.10"
 DB = "spider"
 Table = "book_info"
 User = "test"
 Pwd = "123456"

def connect_db(host, db, user, pwd):
 conn = pymysql.connect(
  host=host,
  user=user,
  passwd=pwd,
  db=db,
  charset='utf8',
  connect_timeout=3600) #,
#  cursorclass=pymysql.cursors.DictCursor)
 conn.autocommit(True)
 return conn

def disconnect_db(conn, cursor):
 cursor.close()
 conn.close()

#提取评价人数,如果评价人数少于10人,按10人处理
def hotratings(person):
 try:
  ptext = person.get_text().split()[0]
  pc = int(ptext[1:len(ptext)-4])
 except ValueError:
  pc = int(10)
 return pc

# 持久化到数据库
def save_to_db(tag, book_reslist):
 dest_conn = connect_db(DestDB.Host, DestDB.DB, DestDB.User, DestDB.Pwd)
 dest_cursor = dest_conn.cursor()

 isql = "insert ignore into book_info "
 isql += "(`bookid`,`tag`,`author`,`translator`,`bookname`,`subname`,`press`,"
 isql += "`publishAt`,`price_str`,`stars`,`hotcnt`,`bookdesc`) values "
 isql += ",".join(["(%s)" % ",".join(['%s']*12)]*len(book_reslist))

 values = []
 for row in book_reslist:
  # 暂时将md5(bookname+author)作为bookid唯一指
  bookid = md5(("%s_%s"%(row[0],row[2])).encode('utf-8')).hexdigest()
  values.extend([bookid, tag]+row[:10])

 dest_cursor.execute(isql, tuple(values))
 disconnect_db(dest_conn, dest_cursor)

# 处理每一次访问的页面
def do_parse(tag, url):
 page_data = requests.get(url)
 soup = BeautifulSoup(page_data.text.encode("utf-8"), "lxml")
 # 提取标签信息
 tag = url.split("?")[0].split("/")[-1]
 # 抓取作者,出版社信息
 details = soup.select("#subject_list > ul > li > div.info > div.pub")
 # 抓取评分
 scores = soup.select("#subject_list > ul > li > div.info > div.star.clearfix > span.rating_nums")
 # 抓取评价人数
 persons = soup.select("#subject_list > ul > li > div.info > div.star.clearfix > span.pl")
 # 抓取书名
 booknames = soup.select("#subject_list > ul > li > div.info > h2 > a")
 # 抓取简介 
 descs = soup.select("#subject_list > ul > li > div.info > p")
 # 从标签信息中分离内容
 book_reslist = []
 for detail, score, personCnt, bookname, desc in zip(details, scores, persons, booknames, descs):
  try:
   subtitle = ""
   title_strs = [s.replace('\n', '').strip() for s in bookname.strings]
   title_strs = [s for s in title_strs if s]
   # 部分书籍有二级书名
   if not title_strs:
    continue
   elif len(title_strs) >= 2:
    bookname, subtitle = title_strs[:2]
   else:
    bookname = title_strs[0]

   # 评分人数
   hotcnt = hotratings(personCnt)
   desc = desc.get_text()
   stars = float('%.1f' % float(score.get_text() if score.get_text() else "-1"))

   author, translator, press, publishAt, price = [""]*5
   detail_texts = detail.get_text().replace('\n', '').split("/")
   detail_texts = [s.strip() for s in detail_texts]

   # 部分书籍无译者信息
   if len(detail_texts) == 4:
    author, press, publishAt, price = detail_texts[:4]
   elif len(detail_texts) >= 5:
    author, translator, press, publishAt, price = detail_texts[:5]
   else:
    continue

   # 转换出版日期为date类型
   if re.match('^[\d]{4}-[\d]{1,2}', publishAt):
    dts = publishAt.split('-')
    publishAt = datetime.date(int(dts[0]), int(dts[1]), 1)
   else:
    publishAt = datetime.date(1000, 1, 1)

   book_reslist.append([author, translator, bookname, subtitle, press, 
         publishAt, price, stars, hotcnt, desc])
  except Exception as e:
   logging.error(e)

 logging.info("insert count: %d" % len(book_reslist))
 if len(book_reslist) > 0:
  save_to_db(tag, book_reslist)
  book_reslist = []
 return len(details)

def main():
 with open("book_tags.txt") as fd:
  tags = fd.readlines()
  for tag in tags:
   tag = tag.strip()
   logging.info("current tag url: %s" % tag)
   for idx in range(0, 1000000, 20):
    try:
     url = "%s?start=%d&type=T" % (tag.strip(), idx)
     cnt = do_parse(tag.split('/')[-1], url)
     if cnt < 10:
      break
     # 睡眠若干秒,降低访问频率
     time.sleep(random.randint(10, 15))
    except Exception as e:
     logging.warn("outer_err: %s" % e)
   time.sleep(300)

if __name__ == "__main__":
 main()

小结

以上代码基于python3环境来运行;
需要首先安装BeautifulSoup: pip install bs4
爬取过程中需要控制好访问频率;
需要对一些信息进行异常处理,比如译者信息、评论人数等。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
跟老齐学Python之集合的关系
Sep 24 Python
Python访问MySQL封装的常用类实例
Nov 11 Python
Python3中正则模块re.compile、re.match及re.search函数用法详解
Jun 11 Python
修改默认的pip版本为对应python2.7的方法
Nov 06 Python
学生信息管理系统Python面向对象版
Jan 30 Python
python实现对列表中的元素进行倒序打印
Nov 23 Python
pytorch实现用CNN和LSTM对文本进行分类方式
Jan 08 Python
Python 实现自动完成A4标签排版打印功能
Apr 09 Python
python 模块导入问题汇总
Feb 01 Python
解决Python字典查找报Keyerror的问题
May 26 Python
Pytorch中Softmax与LogSigmoid的对比分析
Jun 05 Python
解决pycharm安装scrapy DLL load failed:找不到指定的程序的问题
Jun 08 Python
python中字符串比较使用is、==和cmp()总结
Mar 18 #Python
Python使用zip合并相邻列表项的方法示例
Mar 17 #Python
Python zip()函数用法实例分析
Mar 17 #Python
Python iter()函数用法实例分析
Mar 17 #Python
Python callable()函数用法实例分析
Mar 17 #Python
Python matplotlib绘图可视化知识点整理(小结)
Mar 16 #Python
python中matplotlib的颜色及线条控制的示例
Mar 16 #Python
You might like
改德生G88 - 加装等响度低音提升电路
2021/03/02 无线电
thinkphp中session和cookie无效的解决方法
2014/12/19 PHP
Thinkphp 框架配置操作之配置加载与读取配置实例分析
2020/05/15 PHP
jquery判断字符输入个数(数字英文长度记为1,中文记为2,超过长度自动截取)
2010/10/15 Javascript
网站404页面3秒后跳到首页的实例代码
2013/08/16 Javascript
jQuery Validate 验证,校验规则写在控件中的具体实例
2014/02/27 Javascript
一个获取第n个元素节点的js函数
2014/09/02 Javascript
jQuery+ajax中getJSON() 用法实例
2014/12/22 Javascript
JavaScript获得当前网页来源页面(即上一页)的方法
2015/04/03 Javascript
jQuery+HTML5实现图片上传前预览效果
2015/08/20 Javascript
JavaScript提高加载和执行效率的方法
2017/02/03 Javascript
javascript+css3开发打气球小游戏完整代码
2017/11/28 Javascript
JS设计模式之观察者模式实现实时改变页面中金额数的方法
2018/02/05 Javascript
apicloud拉起小程序并传递参数的方法示例
2018/11/21 Javascript
LayUI数据接口返回实体封装的例子
2019/09/12 Javascript
jQuery实现可以扩展的日历
2020/12/01 jQuery
[12:29]《一刀刀一天》之DOTA全时刻19:蝙蝠骑士田伯光再度不举
2014/06/10 DOTA
[01:02:34]TFT vs VGJ.T Supermajor 败者组 BO3 第二场 6.5
2018/06/06 DOTA
Python实现判断一个字符串是否包含子串的方法总结
2017/11/21 Python
python实现的生成word文档功能示例
2019/08/23 Python
python爬虫爬取幽默笑话网站
2019/10/24 Python
python enumerate内置函数用法总结
2020/01/07 Python
解决Tensorflow占用GPU显存问题
2020/02/03 Python
CSS3圆角边框和边界图片效果实例
2016/07/01 HTML / CSS
德国古洛迷亚百货官网:GALERIA Kaufhof
2017/06/20 全球购物
VLAN和VPN有什么区别?分别实现在OSI的第几层?
2014/12/23 面试题
说说在weblogic中开发消息Bean时的persistent与non-persisten的差别
2013/04/07 面试题
毕业自我评价范文
2013/11/17 职场文书
学习保证书范文
2014/04/30 职场文书
计算机毕业大学生求职信
2014/06/26 职场文书
小学亲子活动总结
2014/07/01 职场文书
学雷锋广播稿大全
2015/08/19 职场文书
2016新教师岗前培训心得体会
2016/01/08 职场文书
《黄山奇石》教学反思
2016/02/18 职场文书
Python常遇到的错误和异常
2021/11/02 Python
苹果M1芯片安装nginx 并且部署vue项目步骤详解
2021/11/20 Servers