前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >爬虫练习-豆瓣读书

爬虫练习-豆瓣读书

作者头像
zx钟
发布2019-07-17 16:24:59
4990
发布2019-07-17 16:24:59
举报
文章被收录于专栏:测试游记测试游记

昨晚使用不熟悉的xpath语法解析百度新闻页面碰到了好多坑,今天继续通过简单的豆瓣图书进行练习

1.分析页面

进入豆瓣首页https://www.douban.com/在第一行导航栏找到读书:https://book.douban.com/

进入页面之后发现有很多内容,由于豆瓣没有反爬措施,所以多抓取些数据

大致浏览后发现应该能通过标签查找到全部图书,找到所有热门标签点击所有热门标签https://book.douban.com/tag/?view=cloud

浏览页面后大致可以确定这个入口是合适的一个入口

2.分析入口页面

打开浏览器自带的开发者模式找到其中一个标签:小说

代码语言:javascript
复制
1<td><a href="/tag/小说">小说</a>

点击小说:https://book.douban.com/tag/小说发现它的url就是域名https://book.douban.com//tag/小说的组合

3.分析tag页面

进入小说页面之后发现一本书大概分为8个关键部分:封面,书名,作者,出版社,日期,售价,评分,简介

代码语言:javascript
复制
 1<img class="" src="https://img3.doubanio.com/mpic/s27264181.jpg" width="90">
 2
 3<ahref="https://book.douban.com/subject/25862578/" 
                                title="解忧杂货店"onclick="...">解忧杂货店</a>
 4
 5<div class="pub">[日] 东野圭吾 / 李盈春 / 南海出版公司 / 2014-5 / 39.50元</div>
 6
 7<span class="rating_nums">8.6</span>
 8
 9<p>现代人内心流失的东西,这家杂货店能帮你找回——僻静的街道旁有一家杂货店,
10只要写下烦恼投进卷帘门的投信口,第二天就会在店后的牛奶箱里得到回答。
11因男友身患绝... </p>

4.开始

首先导入需要的库

代码语言:javascript
复制
1from lxml import etree
2import requests

这次使用类的方式实现

代码语言:javascript
复制
1class DouBanBook():
2    pass

初始化类:

代码语言:javascript
复制
1def __init__(self):
2            self.url_book = 'https://book.douban.com/tag/?view=cloud'
3            self.page = 0

获取tag列表

代码语言:javascript
复制
 1def get_tags(self):
 2            '''
 3            获取tag列表
 4            '''
 5            tags = [] #创建一个空列表存储tag名
 6            result = requests.get(self.url_book).text
 7            #开始xpath解析
 8            html = etree.HTML(result)
 9            tags_list = html.xpath
                        ('//[@id="content"]/div/div[1]/div[2]/div/table/tbody/tr/td/a')
10            for tag in tags_list:
11                tags.append(''.join(tag.xpath('./text()')))
12            return tags

由于数据比较大且有分析价值,对数据进行持久化操作(存入数据库) 使用python操作mysql数据库

首先新建如下库和表

代码语言:javascript
复制
 1def insert_mysql(self,item):
 2    #连接数据库
 3        db = pymysql.connect(host='127.0.0.1', port=3306, user='root', password='123456', db='douban',charset="utf8")
 4        #写sql语句
 5        sql = "INSERT INTO douban_book
 6(tag,pic,titiel,author,press,price,time,score,book_info) 
 7VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s);"
 8        #尝试插入数据
 9        try:
10            with db.cursor() as cursor:#创建游标
11                cursor.execute(sql, (item['tag'],item['book_pic'],item['book_titiel'],item['book_author']
12,item['book_press'],item['book_price'],item['book_time'],
13item['book_score'],item['book_info']))
14                db.commit()#提交数据
15        except Exception as e:#如果出现异常插入11书名111111
16            cursor.execute(sql,('1','1',item['book_titiel'],'1','1','1','1','1','1',))
17            db.commit()

将八项重要内容写入数据库

代码语言:javascript
复制
 1def get_book_message(self,tag):
 2            '''
 3            将八项重要信息存储到mysql数据库
 4            '''
 5            #拼接tag和page成新的url
 6            url = 'https://book.douban.com/tag/'+tag+'?start=%d&type=T' %self.page
 7            result = requests.get(url).text
 8            #开始xpath解析
 9            html = etree.HTML(result)
10            books_list = html.xpath('//*[@id="subject_list"]/ul/li')
11            #由于翻页操作是通过回调函数实现,所以需要做跳出循环的判断
12            if books_list == []:
13                return
14            item = {}#新建一个空字典存储获取到的信息
15            item['tag'] = tag
16            for book in books_list:
17                #封面
18                item['book_pic'] = ''.join(book.xpath('./div[1]/a/img/@src'))
19                #书名
20                item['book_titiel'] = ''.join(book.xpath('./div[2]/h2/a/@title'))
21
22                _book_press = book.xpath('./div[2]/div[1]/text()')[0].split('\n')
23                #由于作者,出版社,时间,售价是通过/分割的所以写一个列表推倒式存储
24                book_press = ''.join([book_press for book_press in _book_press if '/' in book_press])
25                #作者/出版社/时间/售价
26                #查看多条数据后发现最后一条必为价格,最后第二条为时间,最后第三条为出版社
27                item['book_price'] = book_press.split('/')[-1]
28                item['book_time'] = book_press.split('/')[-2]
29                item['book_press'] = book_press.split('/')[-3]
30                item['book_author'] = ''.join(book_press.split('/')[:-3])
31                #评分
32                item['book_score'] = ''.join(book.xpath('./div[2]/div[2]/span[2]/text()'))
33                #简介
34                item['book_info'] = ''.join(''.join(book.xpath('./div[2]/p/text()')).split('\n'))
35                self.insert_mysql(item)#写入数据库
36                #print(item)
37            self.page += 20
38            self.get_book_message(tag)

整个类:

代码语言:javascript
复制
 1    class DouBanBook():
 2        def __init__(self):
 3            self.url_book = 'https://book.douban.com/tag/?view=cloud'
 4            self.page = 0
 5        def get_tags(self):
 6            '''
 7            获取tag列表
 8            '''
 9            tags = [] #创建一个空列表存储tag名
10            result = requests.get(self.url_book).text
11            #开始xpath解析
12            html = etree.HTML(result)
13            tags_list = html.xpath('//[@id="content"]/div/div[1]/div[2]/div/table/tbody/tr/td/a')
14            for tag in tags_list:
15                tags.append(''.join(tag.xpath('./text()')))
16            return tags
17
18        def get_book_message(self,tag):
19            '''
20            将八项重要信息存储到mysql数据库
21            '''
22            #拼接tag和page成新的url
23            url = 'https://book.douban.com/tag/'+tag+'?start=%d&type=T' %self.page
24            result = requests.get(url).text
25            #开始xpath解析
26            html = etree.HTML(result)
27            books_list = html.xpath('//*[@id="subject_list"]/ul/li')
28            #由于翻页操作是通过回调函数实现,所以需要做跳出循环的判断
29            if books_list == []:
30                return
31            item = {}#新建一个空字典存储获取到的信息
32            item['tag'] = tag
33            for book in books_list:
34                #封面
35                item['book_pic'] = ''.join(book.xpath('./div[1]/a/img/@src'))
36                #书名
37                item['book_titiel'] = ''.join(book.xpath('./div[2]/h2/a/@title'))
38
39                _book_press = book.xpath('./div[2]/div[1]/text()')[0].split('\n')
40                #由于作者,出版社,时间,售价是通过/分割的所以写一个列表推倒式存储
41                book_press = ''.join([book_press for book_press in _book_press if '/' in book_press])
42                #作者/出版社/时间/售价
43                #查看多条数据后发现最后一条必为价格,最后第二条为时间,最后第三条为出版社
44                item['book_price'] = book_press.split('/')[-1]
45                item['book_time'] = book_press.split('/')[-2]
46                item['book_press'] = book_press.split('/')[-3]
47                item['book_author'] = ''.join(book_press.split('/')[:-3])
48                #评分
49                item['book_score'] = ''.join(book.xpath('./div[2]/div[2]/span[2]/text()'))
50                #简介
51                item['book_info'] = ''.join(''.join(book.xpath('./div[2]/p/text()')).split('\n'))
52                self.insert_mysql(item)#写入数据库
53                #print(item)
54            self.page += 20
55            self.get_book_message(tag)
56
57         def insert_mysql(self,item):
58    #连接数据库
59        db = pymysql.connect(host='127.0.0.1', port=3306, user='root', password='123456', db='douban',charset="utf8")
60        #写sql语句
61        sql = "INSERT INTO douban_book
62(tag,pic,titiel,author,press,price,time,score,book_info) 
63VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s);"
64        #尝试插入数据
65        try:
66            with db.cursor() as cursor:#创建游标
67                cursor.execute(sql, (item['tag'],item['book_pic'],item['book_titiel'],item['book_author']
68,item['book_press'],item['book_price'],item['book_time'],
69item['book_score'],item['book_info']))
70                db.commit()#提交数据
71        except Exception as e:#如果出现异常插入11书名111111
72            cursor.execute(sql,('1','1',item['book_titiel'],'1','1','1','1','1','1',))
73            db.commit()

开始调用:

由于全部图书有点多,使用线程池加快点速度并记录下耗时

耗时1021s,相当于17分钟速度还有待提升

代码语言:javascript
复制
 1if __name__ == '__main__':
 2    starttime = time.time()
 3    book = DouBanBook()
 4    p = Pool()
 5    for tag in book.get_tags():
 6        p.apply_async(book.get_book_message,args=(tag,))
 7
 8    p.close()
 9    p.join()
10    usetime = time.time()-starttime
11    print('总耗时%s'%usetime)

综上总共导入的模块如下:

代码语言:javascript
复制
1from multiprocessing import Pool #进程池
2from lxml import etree #lxml解析页面
3import pymysql #连接mysql数据库了
4import requests #模拟http/https访问
5import time #时间模块
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-03-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 测试游记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档