Python爬虫实例
紧接着上一讲的内容。
我们初步了解了bs4这个解析库。
但是bs4难道只有find,find_all了吗?
如果层次比较深,相似的元素比较多,和可能会写的比较长。
最主要的是很难搞清逻辑。
所以这一章是bs4的中级部分。
任务:解析修真聊天群的章节标题。
网页数据见上一讲。
本期耗时15min。练习耗时15min。
前言
最开始的工具介绍里提到过BeautifulSoup,lxml包。
在速度上正则表达式和lxml是比较突出的。lxml是基于C语言的,而BeautifulSoup使用Python编写,因此BeautifulSoup在性能上略逊一筹也不奇怪。但BeautifulSoup使用起来更方便一些,且支持CSS选择器,这也能够弥补其性能上的不足。另外最新版的bs4也已经支持lxml作为解析器。使用lxml时程序主要根据XPath来解析,如果熟悉XPath的语法,那么lxml和BeautifulSoup都是很好的选择。
一、select选择器
通过上一节,我们看到find的用法。我相信各位因该有感触。
- 笼统。find是对所有的子孙查找。目标太大,及时加了限定也很飘。
- 局限。返回的要么是一个,要么可能太多。
- 步长短。为了精确可能需要一步步逼近。然后写的老长。可能还要分类讨论。。。
select函数简介
select代表的就是选择器。返回值是一个列表。
status = soup.select('#contentcolumn > div > span:nth-child(4)')
我们提到过一次选择器,就是CSS那一篇文章。
css选择器
select支持CSS语法,其实本来就是受到了CSS的启发。
CSS语法选择器
基本和CSS选择器语法一致。
content = soup.find("div",attrs={"id":"book"}).find("div",attrs={"id":"info"}).find('p').string
content1 = soup.select('div#book div#info p:nth-child(2)')[0].string
print(content)
print(content1)
作 者:圣骑士的传说
作 者:圣骑士的传说
我们可以看到效果一致,并且更加的精简了。
注意:
- 空格代表递进关系
- [0],select返回值是一个列表所以不能直接string。不是解析字符串。
- nth-child(2)代表第二个节点。:nth-child() 选择器,该选择器选取父元素的第 N 个子元素,与类型无关。
所以这里即使是第一个p,但是却是2。
当然也可以选中全部的p出来用列表索引,如下:
content2 = soup.select('div#book div#info p')[0].string
效果是一样的。
二、实操
目标的确认
观察内容,返现基本是一个列表,但是有一些妨碍的序言部分,需要去除。
<dd><a href ="/1_1852/526426166.html">第3167章 哥哥,我们家果然不是普通人对吧?</a></dd>
<dd><a href ="/1_1852/529533214.html">第3166章 我的妹妹,当你出生的那一天……</a></dd>
<dd><a href ="/1_1852/530029322.html">第3165章 霸妹变成了面瘫</a></dd>
<dd><a href ="/1_1852/530224932.html">第3164章 此女类我</a></dd>
<dd><a href ="/1_1852/530584964.html">完本感言</a></dd>
<dd><a href ="/1_1852/530590713.html">第3163章 霸宋邀请你加入群‘九洲一号群’【大结局】</a></dd>
<dd><a href ="/1_1852/530693596.html">今天先一章……明天大结局</a></dd>
<dt>《修真聊天群》正文卷</dt>
<dd><a href ="/1_1852/835564.html">第一章 黄山真君和九洲一号群</a></dd>
<dd><a href ="/1_1852/835565.html">第二章 且待本尊算上一卦</a></dd>
<dd><a href ="/1_1852/835566.html">第三章 一张丹方</a></dd>
<dd><a href ="/1_1852/835567.html">第四章 H市三品后天雷劫</a><
方案选择
直接定位dd标签行不行?
不行,列表一个页面可能有很多,干扰元素太多。
定位
<div class="listmain">
行不行,可以,而且距离目标关系不是很远。
干扰信息的排除
我们发现dt标签没有a标签是分割信息。
在两次dt之后才是我们要的dd内容。
raw_titles = soup.select('div.listmain dl dd,dt')
# print(raw_titles)
dt_nu = 0 # flag
filter_list = []
for title in raw_titles:
if not title.find('a') :
print("dt")
dt_nu +=1
if dt_nu >=2 and title.find('a') :
title_str = title.find('a').string
filter_list.append(title_str)
print(dt_nu)
print(filter_list)
with open("sector.txt","w",encoding='utf-8') as SEC:
for title in filter_list:
if title:# 过滤空值
SEC.write(title+"\n")
结果自然是很完美啦!!!
select返回的基础的类型是和find,find_all一致的。所以两种方法可以相互嵌套。
总结
这一章,我们讲解了更为简单的定位工具。
CSS选择器select。更多的参数需要具体查看使用说明。
并且在不同的实例下联系。
在实战中很少用到find,所以忘记也无所谓。。。可能也就如上的if里面用的到。
下一讲我们介绍另一个规则工具,xpath。
虽然形式上相差比较多,但是定位用的锚点无非就那么几个。
标签,id,属性,类。
需要的是,灵活的运用。
一键三连吧,朋友们。。。