荐 学了python不知干啥?爬爬虫! (3)爬取豆瓣书籍列表(bs4/lxml简单使用)
爬取豆瓣书籍列表
合理爬取,不随意扩大站点压力
本文章仅作示例,请勿用作非法用途
该系列的其他篇目:
效果
解析豆瓣书籍列表,包括作者/介绍/评分,如下图
开始
和上文一样,我们先去网页端看看我们准备获取的数据
随便点进去一个子分类
右键——查看框架源代码 (Edge,其他浏览器请自行对应 )
哇塞,又是一下子就找到了。
接下来,开始爬取!
试爬取
根据前几节课的,我们写一版简单的代码试试
执行一下!
woc!报错!我们来看看这个418是个什么错误
错误描述:经过网上查询得知,418的意思是被网站的反爬程序返回的,网上解释为,418 I’m a teapot
The HTTP 418 I’m a teapot client error response code indicates that the server refuses to brew coffee because it is a teapot. This error is a reference to Hyper Text Coffee Pot Control Protocol which was an April Fools’ joke in 1998.
翻译为:HTTP 418 I’m a teapot客户端错误响应代码表示服务器拒绝煮咖啡,因为它是一个茶壶。这个错误是对1998年愚人节玩笑的超文本咖啡壶控制协议的引用。
好吧,我们又被bang了,但是没关系,我们有乔装术!
UA伪装
同上节课一样,我们看一下自己的UA
(顺带一提,在这个过程中,我发现了一个豆瓣很有趣的玩意:
挺神奇的)
依葫芦画瓢,简单伪装一下:
真的是非常的amazing啊,搞定了!
解析数据
有了网页,我们开始解析数据。
前几节课我们一直使用的是纯正则表达式,但是既然是学习,我们来整点不一样的
BeautifulSoup4
看到这个题目,你会不会以为我打错了?美丽的汤?这是什么玩意?
事实上我没有打错,bs4是Python爬虫中相当著名的一个包,在解析html时非常易于使用。当然,它也有自己的弊端,例如相较于re,用它解析大量数据速度会慢很多。当然这里并不影响。
如果想学习bs4的话,可以先访问这里,看一下它的基本使用。接下来我们就直接开始。
安装
使用pip安装
pip install beautifulsoup4
使用
from bs4 import BeautifulSoup
将获取到的html文本作为参数传入,实例化一个BeautifulSoup对象,使用默认的html解析器
然后我们使用find_all方法找到href属性中包含subject的所有标签并且打印试一下
amazing啊,一下子就找到了所有!
如法炮制,我们再找一下其他的
然而到这里我发现了一个小问题,我们分别提取了 书名、作者、简介,这是这样合在一起似乎不太方便。所以我决定换一种思路,按照豆瓣一本书一本书的爬取,然后再分别提取。
我们来看看它们的一本书对应的代码是怎么写的
<div class="detail-frame">
<h2>
<a href="https://book.douban.com/subject/35023731/">怪诞故事集</a>
</h2>
<p class="rating">
<span class="allstar00"></span>
<span class="font-small color-lightgray">
</span>
</p>
<p class="color-gray">
[波兰] 奥尔加·托卡尔丘克 / 浙江文艺出版社 / 2020-7
</p>
<p class="detail">
诺奖得主奥尔加·托卡尔丘克小说集,讲述了十个怪诞、疯狂、恐怖和幽默的故事,融合了民间传说、童话、科幻、宗教故事等
元素来观照波兰历史与人的生活。
</p>
</div>
可以看到,每本书都在class="detail-frame"的div里面。按照这个要求,我们重新爬取全部书籍列表。
接下来分别解析
使用lxml
对于这样的单独提取出来的<div></div>来说,直接用html解析方式怕是不ok了,那我们怎么办?难道又回到写正则的苦逼日子?
不要慌,bs4的解析器除了"html.parser",还可以直接使用lxml。
什么是lxml?
lxml是python的一个解析库,支持HTML和XML的解析,支持XPath解析方式,而且解析效率非常高。这个库的主要优点是易于使用,在解析大型文档时速度非常快,归档的也非常好,并且提供了简单的转换方法来将数据转换为Python数据类型,从而使文件操作更容易。
XPath,全称XML Path Language,即XML路径语言,它是一门在XML文档中查找信息的语言,它最初是用来搜寻XML文档的,但是它同样适用于HTML文档的搜索
XPath的选择功能十分强大,它提供了非常简明的路径选择表达式,另外,它还提供了超过100个内建函数,用于字符串、数值、时间的匹配以及节点、序列的处理等,几乎所有我们想要定位的节点,都可以用XPath来选择
XPath于1999年11月16日成为W3C标准,它被设计为供XSLT、XPointer以及其他XML解析软件使用,更多的文档可以访问其官方网站:https://www.w3.org/TR/xpath/
体验一下?
安装
依旧使用pip安装
pip install lxml
结合bs4使用
- 书籍名在 h2标题下
- 作者信息在 class为color-gray的 p标签下
- 简介在 class为detail的 p标签下
但是很尴尬的是,这样做在执行到后半部分的时候会报错
原因是有一部分书籍的 简介 直接放在了 p 标签下,而并没有class属性。这也算是一种特殊情况吧(嘤嘤嘤)
没有办法,处理一下特殊情况。完美
最后闲的蛋疼,我们再把评分补上。大功告成!
完整源码
#FunnySaltyFish 2020/07/09 完成
#基于Python 3.7.0
import urllib.request as ur
from bs4 import BeautifulSoup
import re
def get_html(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Edg/83.0.478.61'
}
request = ur.Request(url=url, headers=headers)
html = ur.urlopen(request).read()
return html.decode('utf-8')
def parse_html(html):
soup = BeautifulSoup(html, 'html.parser')
# books_list = soup.find_all(href=re.compile(r"https://book.douban.com/subject/"))
# authors_list = soup.find_all(class_=re.compile("color-gray"))
# details_list = soup.find_all(class_=re.compile("detail"))
# print(books_list)
# print(authors_list)
# print(details_list)
detail_frames = soup.find_all(class_=re.compile("detail-frame"))
result_list = []
for each_detail in detail_frames:
result_list.append(parse_one_book(str(each_detail)))
return '\n'.join(result_list)
def parse_one_book(detail):
soup = BeautifulSoup(detail, 'lxml')
name = soup.div.h2.a.string
author = soup.find(
'p', attrs={'class': 'color-gray'}).string.strip() # 去除无效字符
rating = soup.find(
'span', attrs={'class': 'font-small color-lightgray'}).string.strip()
if len(str(rating)) == 0:
rating = '暂无评分'
if soup.find('p', attrs={'class': 'detail'}):
detail = soup.find(
'p', attrs={'class': 'detail'}).string.strip() # 去除无效字符
else:
detail = soup.find(
'p', attrs={'class': 'color-gray'}).find_next().string.strip()
result = f"-->%s (%s) 评分:%s:\n %s" % (name, author, rating, detail)
return result
if __name__ == "__main__":
html = get_html('https://book.douban.com/latest')
result = parse_html(html)
print(result)
其他
- 我的水平不高,所讲之处难免有所漏洞,还望指正
后续
- 联系我:github(是的没错,我是个菜鸡)
- 其他文章:年轻人的第一个开源库
- 一种创新的正六边形定位(全过程详解)
- 正六边形地图完整项目
本文地址:https://blog.csdn.net/qq_43596067/article/details/107242899