Python利用lxml模块爬取豆瓣读书排行榜的方法与分析


Posted in Python onApril 15, 2019

前言

上次使用了BeautifulSoup库爬取电影排行榜,爬取相对来说有点麻烦,爬取的速度也较慢。本次使用的lxml库,我个人是最喜欢的,爬取的语法很简单,爬取速度也快。

本次爬取的豆瓣书籍排行榜的首页地址是:

https://www.douban.com/doulist/1264675/?start=0&sort=time&playable=0&sub_type=

该排行榜一共有22页,且发现更改网址的 start=0 的 0 为25、50就可以跳到排行榜的第二、第三页,所以后面只需更改这个数字然后通过遍历就可以爬取整个排行榜的书籍信息。

本次爬取的内容有书名、评分、评价数、出版社、出版年份以及书籍封面图,封面图保存为图片,其他数据存为csv文件,方面后面读取分析。

本次的项目步骤:一、分析网页,确定爬取数据

二、使用lxml库爬取内容并保存

三、读取数据并选择部分内容进行分析

步骤一:

Python利用lxml模块爬取豆瓣读书排行榜的方法与分析

分析网页源代码可以看到,书籍信息在属性为的div标签中,打开发现,我们需要爬取的信息都在标签内部,通过xpath语法我们可以很简便的爬取所需内容。

Python利用lxml模块爬取豆瓣读书排行榜的方法与分析

(书籍各类信息所在标签)

所需爬取的内容在 class为post、title、rating、abstract的div标签中。

步骤二:

先定义爬取函数,爬取所需内容执行函数,并存入csv文件

具体代码如下:

import requests
from lxml import etree
import time
import csv

#信息头
headers = {
 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
}

#定义爬取函数
def douban_booksrank(url):
 res = requests.get(url, headers=headers)
 selector = etree.HTML(res.text)
 contents = selector.xpath('//div[@class="article"]/div[contains(@class,"doulist-item")]') #循环点
 for content in contents:
 try:
 title = content.xpath('div/div[2]/div[3]/a/text()')[0] #书名
 scores = content.xpath('div/div[2]/div[4]/span[2]/text()') #评分
 scores.append('9.0') #因为有一些书没有评分,导致列表为空,此处添加一个默认评分,若无评分则默认为9.0
 score = scores[0]
 comments = content.xpath('div/div[2]/div[4]/span[3]/text()')[0] #评论数量
 author = content.xpath('div/div[2]/div[5]/text()[1]')[0] #作者
 publishment = content.xpath('div/div[2]/div[5]/text()[2]')[0] #出版社
 pub_year = content.xpath('div/div[2]/div[5]/text()[3]')[0] #出版时间
 img_url = content.xpath('div/div[2]/div[2]/a/img/@src')[0] #书本图片的网址
 img = requests.get(img_url) #解析图片网址,为下面下载图片
 img_name_file = 'C:/Users/lenovo/Desktop/douban_books/{}.png'.format((title.strip())[:3]) #图片存储位置,图片名只取前3
 #写入csv
 with open('C:\\Users\lenovo\Desktop\\douban_books.csv', 'a+', newline='', encoding='utf-8')as fp: #newline 使不隔行
 writer = csv.writer(fp)
 writer.writerow((title, score, comments, author, publishment, pub_year, img_url))
 #下载图片,为防止图片名导致格式错误,加入try...except
 try:
 with open(img_name_file, 'wb')as imgf:
  imgf.write(img.content)
 except FileNotFoundError or OSError:
 pass
 time.sleep(0.5) #睡眠0.5s
 except IndexError:
 pass
#执行程序
if __name__=='__main__':
 #爬取所有书本,共22页的内容
 urls = ['https://www.douban.com/doulist/1264675/?start={}&sort=time&playable=0&sub_type='.format(str(i))for i in range(0,550,25)]
 #写csv首行
 with open('C:\\Users\lenovo\Desktop\\douban_books.csv', 'a+', newline='', encoding='utf-8')as f:
 writer = csv.writer(f)
 writer.writerow(('title', 'score', 'comment', 'author', 'publishment', 'pub_year', 'img_url'))
 #遍历所有网页,执行爬取程序
 for url in urls:
 douban_booksrank(url)

爬取结果截图如下:

Python利用lxml模块爬取豆瓣读书排行榜的方法与分析

Python利用lxml模块爬取豆瓣读书排行榜的方法与分析

步骤三:

本次使用Python常用的数据分析库pandas来提取所需内容。pandas的read_csv()函数可以读取csv文件并根据文件格式转换为Series、DataFrame或面板对象。

此处我们提取的数据转变为DataFrame(数据帧)对象,然后通过Matplotlib绘图库来进行绘图。

具体代码如下:

from matplotlib import pyplot as plt
import pandas as pd
import re

plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
plt.subplots_adjust(wsapce=0.5, hspace=0.5) #调整subplot子图间的距离

pd.set_option('display.max_rows', None) #设置使dataframe 所有行都显示

df = pd.read_csv('C:\\Users\lenovo\Desktop\\douban_books.csv') #读取csv文件,并赋为dataframe对象

comment = re.findall('\((.*?)人评价', str(df.comment), re.S) #使用正则表达式获取评论人数
#将comment的元素化为整型
new_comment = []
for i in comment:
 new_comment.append(int(i))

pub_year = re.findall(r'\d{4}', str(df.pub_year),re.S) #获取书籍出版年份
#同上
new_pubyear = []
for n in pub_year:
 new_pubyear.append(int(n))

#绘图
#1、绘制书籍评分范围的直方图
plt.subplot(2,2,1)
plt.hist(df.score, bins=16, edgecolor='black')
plt.title('豆瓣书籍排行榜评分分布', fontweight=700)
plt.xlabel('scores')
plt.ylabel('numbers')

#绘制书籍评论数量的直方分布图
plt.subplot(222)
plt.hist(new_comment, bins=16, color='green', edgecolor='yellow')
plt.title('豆瓣书籍排行榜评价分布', fontweight=700)
plt.xlabel('评价数')
plt.ylabel('书籍数量(单位/本)')

#绘制书籍出版年份分布图
plt.subplot(2,2,3)
plt.hist(new_pubyear, bins=30, color='indigo',edgecolor='blue')
plt.title('书籍出版年份分布', fontweight=700)
plt.xlabel('出版年份/year')
plt.ylabel('书籍数量/本')

#寻找关系
plt.subplot(224)
plt.bar(new_pubyear,new_comment, color='red', edgecolor='white')
plt.title('书籍出版年份与评论数量的关系', fontweight=700)
plt.xlabel('出版年份/year')
plt.ylabel('评论数')

plt.savefig('C:\\Users\lenovo\Desktop\\douban_books_analysis.png') #保存图片
plt.show()

这里需要注意的是,使用了正则表达式来提取评论数和出版年份,将其中的符号和文字等剔除。

分析结果如下:

Python利用lxml模块爬取豆瓣读书排行榜的方法与分析

本次分析的内容也较为简单,从上面的几个图形中我们也能得出一些结论。

这些高分书籍中绝大多数的评论数量都在50000以下;多数排行榜上的高分书籍都出版在2000年以后;出版年份在2000年后的书籍有更多的评论数量。

以上数据也见解的说明了在进入二十世纪后我国的图书需求量更大了,网络更发达,更多人愿意发表自己的看法。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
Python发送form-data请求及拼接form-data内容的方法
Mar 05 Python
浅谈python中的变量默认是什么类型
Sep 11 Python
请不要重复犯我在学习Python和Linux系统上的错误
Dec 12 Python
tensorflow实现简单的卷积神经网络
May 24 Python
Python3单行定义多个变量或赋值方法
Jul 12 Python
python自动化生成IOS的图标
Nov 13 Python
python实现学员管理系统
Feb 26 Python
scrapy-redis源码分析之发送POST请求详解
May 15 Python
Python 实现平台类游戏添加跳跃功能
Mar 27 Python
Python制作数据预测集成工具(值得收藏)
Aug 21 Python
如何使用scrapy中的ItemLoader提取数据
Sep 30 Python
Biblibili视频投稿接口分析并以Python实现自动投稿功能
Feb 05 Python
Python常见读写文件操作实例总结【文本、json、csv、pdf等】
Apr 15 #Python
10招!看骨灰级Pythoner玩转Python的方法
Apr 15 #Python
Python后台开发Django会话控制的实现
Apr 15 #Python
浅析Python 实现一个自动化翻译和替换的工具
Apr 14 #Python
提升Python程序性能的7个习惯
Apr 14 #Python
Python根据当前日期取去年同星期日期
Apr 14 #Python
Python实现的微信支付方式总结【三种方式】
Apr 13 #Python
You might like
php mysql Errcode: 28 终极解决方法
2009/07/01 PHP
回帖脱衣服的图片实现代码
2014/02/15 PHP
解决PhpMyAdmin中导入2M以上大文件限制的方法分享
2014/06/06 PHP
PHP单例模式与工厂模式详解
2017/08/29 PHP
PHP数组式访问接口ArrayAccess用法分析
2017/12/28 PHP
PHP的JSON封装、转变及输出操作示例
2019/09/27 PHP
JavaScript中的new的使用方法与注意事项
2007/05/16 Javascript
JavaScript sub方法入门实例(把字符串显示为下标)
2014/10/17 Javascript
js中hash和ico的关联分析
2015/02/05 Javascript
JS实现网页每隔3秒弹出一次对话框的方法
2015/11/09 Javascript
深入理解关于javascript中apply()和call()方法的区别
2016/04/12 Javascript
webpack中引用jquery的简单实现
2016/06/08 Javascript
div实现自适应高度的textarea实现angular双向绑定
2017/01/08 Javascript
JavaScript实现删除数组重复元素的5种常用高效算法总结
2018/01/18 Javascript
JS跨域请求的问题解析
2018/12/03 Javascript
angular 表单验证器验证的同时限制输入的实现
2019/04/11 Javascript
Vuex新手的理解与使用详解
2019/05/31 Javascript
基于vue-draggable 实现三级拖动排序效果
2020/01/10 Javascript
Webpack的Loader和Plugin的区别
2020/11/09 Javascript
[02:16]完美世界DOTA2联赛PWL S3 集锦第三期
2020/12/21 DOTA
把大数据数字口语化(python与js)两种实现
2013/02/21 Python
Python随机生成彩票号码的方法
2015/03/05 Python
python编写朴素贝叶斯用于文本分类
2017/12/21 Python
对django的User模型和四种扩展/重写方法小结
2019/08/17 Python
Python list与NumPy array 区分详解
2019/11/06 Python
AUC计算方法与Python实现代码
2020/02/28 Python
阿拉伯世界最大的电子商务网站:Souq沙特阿拉伯
2016/10/28 全球购物
塔吉特百货公司官网:Target
2017/04/27 全球购物
意大利简约的休闲品牌:Aspesi
2018/02/08 全球购物
比利时家具购买网站:Home24
2019/01/03 全球购物
50道外企软件测试面试题
2014/08/18 面试题
法学专业自我鉴定
2014/02/05 职场文书
综合实践活动总结
2014/05/05 职场文书
环保建议书400字
2014/05/14 职场文书
爱护草坪标语
2014/06/24 职场文书
使用Docker容器部署rocketmq单机的全过程
2022/04/03 Servers