爬虫学习日记2-提取丁香园论坛的回复内容
任务:
-
学习beautifulsoup,并使用beautifulsoup提取内容。
-
使用beautifulsoup提取丁香园论坛的回复内容。
一、使用BeautifulSoup
方法1:find_all方法+使用属性
首先导入相关bs4和requests库,略。
制定headers参数,以伪装成浏览器,略。
res = requests.get(r'http://www.dxy.cn/bbs/thread/626626#626626',headers=headers).text
soup = BeautifulSoup(res,'lxml')
#返回一个对象<class 'bs4.BeautifulSoup'>
起初只打算拿到回复文本
reply = soup.find_all('td',attrs={'class':"auth",'class':"postbody",})
reply为<class ‘bs4.element.ResultSet’>,且具备__iter__方法,每次迭代拿到bs4.element.Tag。于是自然而然的拿到想要的结果。
for i,res in enumerate(reply):
print("***第{}条回复内容***".format(i+1), res.text.strip())
结果大概如下所示:
这时看了下参考资料,里面将每天评论的作者信息也输出了。于是顺着先前的思路:既然拿到了评论文本,那根据评论拿到评论人员吧。发现find_previous可以实现需求 ,拿到向上节点中第一个符合条件的结果。于是最终完整代码如下:
from bs4 import BeautifulSoup
import requests
res = requests.get(r'http://www.dxy.cn/bbs/thread/626626#626626',headers=headers).text
soup = BeautifulSoup(res,'lxml')
reply = soup.find_all('td',class_='postbody')
for r in reply:
auth = r.find_previous(name='div',class_='auth').get_text()
reply_text = r.get_text(strip=True)
print("-"*10+auth+"-"*10,reply_text,sep="\n")
结果如下:
这里要附上任务资料里提供的参考资料:[https://blog.csdn.net/wwq114/article/details/88085875]里的方法。
先通过find_all(‘tbody’)拿到包含auth和postbody的两个需要提取的tag对象。然后每次迭代时,再用find方法拿到auth和postbody两个类的文本结果。
方法2:使用CSS选择器
先复习下选择器的知识
-
- 基本选择器
1. 标签选择器
2. ID选择器 #ID名
3. 类选择器(class=“c1 c2 …”) .类名
- 基本选择器
-
- 通用选择器(*)
-
- 组合选择器
1. 后代选择器(空格)
2. 儿子选择器(>)
3. 毗邻选择器(div+p)
4. 弟弟选择器(~)
- 组合选择器
-
- 属性选择器
1. [s9]
2. [s9=“hao”]
3. 其他不常用的(有印象即可)
- 属性选择器
-
- 分组和嵌套
1. 分组(用逗号分隔的多个选择器条件)
2. 嵌套(选择器都可以组合起来使用)
- 分组和嵌套
-
- 选择器的优先级
1. 越靠近标签的优先级越高(就近原则)
2. 权重的计算
1. 内联样式1000
2. ID选择器100
3. 类选择器10
4. 元素选择器1
- 选择器的优先级
代码如下,使用的Class选择器,结果与上面的一致。
auths = soup.select('.auth') #auths是一个列表,里面的为tag对象
replys = soup.select('.postbody')
for i in range(len(auths)):
auth = auths[i].text
reply= replys[i].get_text(strip=True)
print("-"*20+'auth:'+auth+"-"*20)
print(reply)
方法3:find_all方法结合CSS选择器
现用find_all拿到一个同时包含auth和postbody的对象。
tag_list = soup.find_all('tr')
for tobj in tag_list:
auth = tobj.select('.auth')#
if auth:
reply= tobj.select('.postbody')[0].get_text(strip=True)
print("-"*20+'auth:'+auth[0].text+"-"*20)
print(reply)
二、使用xPath
用起来不是很习惯,可能是前端知识不丰富的原因。
from lxml import etree
import requests
headers = {
'User-Agent':"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50"
}
res = requests.get(r'http://www.dxy.cn/bbs/thread/626626#626626',headers=headers)
html = etree.HTML(res.text)
html.xpath('//td[@class="postbody"]//text()')