一、数据解析常用的三种方式——③BeautifulSoup
1.使用时需要使用BS转类型
response = requests.get(url,headers=self.headers)
#转类型-------------<class 'bs4.BeautifulSoup'>
#默认bs4会调用你系统中的lxml的解析库 警告提示
#如果不想看到警告,可以主动设置 bs4的解析库----features="lxml"
soup = BeautifulSoup(data,'lxml')
2.通用解析方法
①find----返回符合查询条件的第一个标签
result = soup.find(name='p')
result = soup.find(attrs={'class':'title'})
②find_all-----传标签(a)或者传属性(attrs={’’:’’})
result = soup.find_all('a')
result = soup.find_all('a',limit=1)#其实就是.find()的源码,只取第一个
result = soup.find_all(attrs={"class":"sister"})
③select_one-----传css的选择器(前端的内容)—只取第一个
result = soup.select_one('.sister')#类选择器
④select-----传css选择器,取得是集合-----返回list
result = soup.select('.sister')#类选择器
result = soup.select('#link1')#id选择器
result = soup.select('a[id="link2"]')
result = soup.select('title,.title')
result = soup.select('head title')
⑤select-----传css选择器-----取标签包裹得内容
注:.get_text()是获取文字
result = soup.select('b')[0].get_text()#.get_text()是获取文字
⑥select-----传css选择器-----取标签的属性
注:.get(‘href’)是获取属性
result = soup.select('#link1')[0].get('href')#.get('href')是获取属性
3.通用解析方法的完整测试代码
#pip install beautifulsoup
from bs4 import BeautifulSoup
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" id="link2><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
#1.转类型-------------<class 'bs4.BeautifulSoup'>
soup = BeautifulSoup(html_doc,'lxml')
#2.通用解析方法
#①find----返回符合查询条件的第一个标签
result = soup.find(name='p')
result = soup.find(attrs={'class':'title'})
#②find_all-----传标签(a)或者传属性(attrs={'':''})
result = soup.find_all('a')
result = soup.find_all('a',limit=1)#其实就是.find()的源码,只取第一个
result = soup.find_all(attrs={"class":"sister"})
#③select_one-----传css的选择器(前端的内容)
result = soup.select_one('.sister')#类选择器
#④select-----传css选择器,取得是集合-----返回list
result = soup.select('.sister')#类选择器
result = soup.select('#link1')#id选择器
result = soup.select('a[id="link2"]')
result = soup.select('title,.title')
result = soup.select('head title')
#取标签包裹得内容----返回的是list
result = soup.select('b')[0].get_text()#.get_text()是获取文字
#取标签的属性
result = soup.select('#link1')[0].get('href')#.get('href')是获取属性
print(result)
二、代码——使用BS4抓取QZZN帖子的标题和链接,并抓取每个链接下帖子的回复内容
from bs4 import BeautifulSoup
import requests
import json
import time
class QZZNspider(object):
def __init__(self):
self.url = 'https://bbs.qzzn.com/forum-133-{}.html'
self.headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1'
}
#保存数据
self.data_list = []#用来存储帖子的标题及链接
self.data_detail = []#用来存储每一个帖子下面的回复内容
#1. 发请求
def get_response(self,url):
response = requests.get(url,headers=self.headers)
data = response.content#数据为二进制类型
return data
#2. 解析数据 list(对应一个网页中帖子的标题及链接)
def parse_data(self,data):
#1.转类型
soup = BeautifulSoup(data,'lxml')
#2.解析内容
my_object_list = soup.find_all(attrs={'class':'s xst'})#类选择器,class="s xst
for single_object in my_object_list:
final_dic = {}
final_dic['title'] = single_object.get_text()#取出标题
final_dic['url'] = "http://bbs.qzzn.com/"+single_object.get('href')
self.data_list.append(final_dic)#填充至self.data_list[]
#2.解析详情页 detail(对应每一个帖子下面的回复内容)
def parse_detail_data(self,data):
html_data = BeautifulSoup(data,'lxml')
#取出问题测试
question_test = html_data.find_all(attrs={'id': 'thread_subject'})
if question_test != []:#判断问题测试是不是空集:因为有的帖子可能要求权限大于多少(或者登录之后才能访问),因此先加判断能否正常提出标题(即能否正常访问),若能提出标题,再进行后续的回复提取!
question = question_test[0].get_text()
#存入问题
detail_question_dic = {
'Question': question
}
self.data_detail.append(detail_question_dic)#将问题填充至self.data_detail[]
answer_list = html_data.select('.t_f')#取出所有的回复
for index,answer in enumerate(answer_list):
answer_list_final = []
answer_list_final.append(answer.get_text().replace('\n', '').replace('\r', '').replace('\xa0',''))#把回复中无用的'\n','\r','\xao'去掉
detail_dic = {
'Answer'+format(index+1):answer_list_final
}#给Answer添加一个标签,变成Answer1、Answer2......
self.data_detail.append(detail_dic)
else:
print('无法访问的帖子')#无法访问的帖子,在terminal中打印提示
#3. 保存数据
def save_data(self,data,file_path):
data_str = json.dumps(data)#转为字符串类型
with open(file_path,'w')as f:
f.write(data_str)
#4.启动
def start(self):
#发送列表页请求
for i in range(1,10):#仅是用了一个for循环就能实现翻页的功能
url = self.url.format(i)
data = self.get_response(url)
self.parse_data(data)
self.save_data(self.data_list,'qzznspider.json')#因self.data_list是在__init__(self)中定义的,因此不用在for循环里保存
#发送详情页的请求-----相当于把之前取出的每一个title对应的url取出来,依次对每个url进行发送请求,返回的'response'进行数据解析,具体步骤与第一次取title和url相类似
for data in self.data_list:
detail_url = data['url']
print(detail_url)
detail_data = requests.get(detail_url).content
#解析详情页的数据
self.parse_detail_data(detail_data)
self.save_data(self.data_detail,'detail.json')
QZZNspider().start()