python书籍信息爬虫实例
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表,如下:
CREATETABLE`book_info`( `id`int(11)NOTNULLAUTO_INCREMENT, `bookid`varchar(64)NOTNULLCOMMENT'bookID', `tag`varchar(32)DEFAULT''COMMENT'分类目录', `bookname`varchar(256)NOTNULLCOMMENT'书名', `subname`varchar(256)NOTNULLCOMMENT'二级书名', `author`varchar(256)DEFAULT''COMMENT'作者', `translator`varchar(256)DEFAULT''COMMENT'译者', `press`varchar(128)DEFAULT''COMMENT'出版社', `publishAt`dateDEFAULT'0000-00-00'COMMENT'出版日期', `stars`floatDEFAULT'0'COMMENT'评分', `price_str`varchar(32)DEFAULT''COMMENT'价格string', `hotcnt`int(11)DEFAULT'0'COMMENT'评论人数', `bookdesc`varchar(8192)DEFAULTNULLCOMMENT'简介', `updateAt`timestampNOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMPCOMMENT'修改日期', PRIMARYKEY(`id`), UNIQUEKEY`idx_bookid`(`bookid`), KEY`idx_bookname`(`bookname`), KEY`hotcnt`(`hotcnt`), KEY`stars`(`stars`), KEY`idx_tag`(`tag`) )ENGINE=InnoDBDEFAULTCHARSET=utf8COMMENT='书籍信息';
并已实现相关爬虫逻辑,主要用到了BeautifulSoup包,如下:
#!/usr/bin/python
#coding:utf-8
importre
importlogging
importrequests
importpymysql
importrandom
importtime
importdatetime
fromhashlibimportmd5
frombs4importBeautifulSoup
logging.basicConfig(level=logging.INFO,
format='[%(levelname)s][%(name)s][%(asctime)s]%(message)s',
datefmt='%Y-%m-%d%H:%M:%S')
classDestDB:
Host="192.168.1.10"
DB="spider"
Table="book_info"
User="test"
Pwd="123456"
defconnect_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)
returnconn
defdisconnect_db(conn,cursor):
cursor.close()
conn.close()
#提取评价人数,如果评价人数少于10人,按10人处理
defhotratings(person):
try:
ptext=person.get_text().split()[0]
pc=int(ptext[1:len(ptext)-4])
exceptValueError:
pc=int(10)
returnpc
#持久化到数据库
defsave_to_db(tag,book_reslist):
dest_conn=connect_db(DestDB.Host,DestDB.DB,DestDB.User,DestDB.Pwd)
dest_cursor=dest_conn.cursor()
isql="insertignoreintobook_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=[]
forrowinbook_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)
#处理每一次访问的页面
defdo_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=[]
fordetail,score,personCnt,bookname,descinzip(details,scores,persons,booknames,descs):
try:
subtitle=""
title_strs=[s.replace('\n','').strip()forsinbookname.strings]
title_strs=[sforsintitle_strsifs]
#部分书籍有二级书名
ifnottitle_strs:
continue
eliflen(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()ifscore.get_text()else"-1"))
author,translator,press,publishAt,price=[""]*5
detail_texts=detail.get_text().replace('\n','').split("/")
detail_texts=[s.strip()forsindetail_texts]
#部分书籍无译者信息
iflen(detail_texts)==4:
author,press,publishAt,price=detail_texts[:4]
eliflen(detail_texts)>=5:
author,translator,press,publishAt,price=detail_texts[:5]
else:
continue
#转换出版日期为date类型
ifre.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])
exceptExceptionase:
logging.error(e)
logging.info("insertcount:%d"%len(book_reslist))
iflen(book_reslist)>0:
save_to_db(tag,book_reslist)
book_reslist=[]
returnlen(details)
defmain():
withopen("book_tags.txt")asfd:
tags=fd.readlines()
fortagintags:
tag=tag.strip()
logging.info("currenttagurl:%s"%tag)
foridxinrange(0,1000000,20):
try:
url="%s?start=%d&type=T"%(tag.strip(),idx)
cnt=do_parse(tag.split('/')[-1],url)
ifcnt<10:
break
#睡眠若干秒,降低访问频率
time.sleep(random.randint(10,15))
exceptExceptionase:
logging.warn("outer_err:%s"%e)
time.sleep(300)
if__name__=="__main__":
main()
小结
以上代码基于python3环境来运行;
需要首先安装BeautifulSoup:pipinstallbs4
爬取过程中需要控制好访问频率;
需要对一些信息进行异常处理,比如译者信息、评论人数等。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。