BeautifulSoup命令
这个BrautifulSoup命令请参考博客:BS4官方详细讲解–中文版
BeautifulSoup和Xpath一样也是用来筛选HTML标签的
下面就来讲讲BeautifulSoup的基本用法
BS4命令 | 代码含义 |
---|---|
select_one() | select_one(selector) 选择器的名字查找,如果符合条件的有多个标签:就只返回第1个标签下所有子标签,返回类型为字符串 ex: select_one(’#div1’) |
select() | select(selector)找到选择器下所有标签,返回列表 ex: select(‘ul’) |
find() | find(selector) 找到选择器下所有标签。如果符合条件的有多个标签:就只返回第1个标签下所有子标签,返回类型为字符串 ex: find(‘div’, id=‘div2’), find(‘div’, class_=‘div2’) |
find_all() | find_all(selector)找到选择器下所有标签,返回列表 ex: find_all(“ul”) ,find_all(‘ul’,class_=“show2”) |
通过观察发现:
select_one()和find()相似
select()和find_all()相似
select()的格式基本上是:
标准形式:select(‘标签名’,class_="") 或者 select(‘标签名’,id="")
简单形式:select("#id选择器名") 或者 select(".类名")
我们看到 select()的简单形式并没有写那么多,就只写id选择器的名字和类选择器的名字而已,如果是id选择器 我们用:#加id选择器名字,如果是类选择器我们用:. 加类选择器名字
示例代码–>:
select(‘div’,class_=‘div1’)
select(‘span’,id=“xiaoming”)
select_one(’#comments’)
select(’.comment-item’)
select_one(’.comment h3 .comment-info’)
注:这上面【空格】表示层级,它不能匹配 class='comment h3 comment-info’
如果想匹配class=’.comment h3 .comment-info’*
需要用更强大的find
find()的格式
标准形式:find(‘标签名’,class_="") 或者 find(‘标签名’,class_="")
简单形式:find(class_="") 或者 find(id="")
多类选择器形式:find(‘标签名’, attrs={‘class’: ‘comment h3 comment-info’})
这个形式是专门解决 class=comment h3 comment-info的!!!
示例代码–>
find_all(‘ul’,class_=“show2”)
find(‘ul’,id=“show1”)
find(id=“div1”)
find(‘span’,attrs={‘class’:‘aa bb cc’})
基础语法掌握了,开始练习代码吧
我们首先先给出一段html代码
然后我们用 bs4命令 进行操作
<div id='div1'>
<ul class="show1">
<li>275万购昌平邻铁三居 总价20万买一居</li>
<li>00万内购五环三居 140万安家东三环</li>
<li>北京首现零首付楼盘 53万购东5环50平</li>
<li>京楼盘直降5000 中信府 公园楼王现房</li>
京楼盘直降10000 橡树湾 公园楼王现房
</ul>
<ul class="show2">
<li><a href='#'>275万购昌平邻铁三居 总价20万买一居222</a>xxxxxx</li>
<li>00万内购五环三居 140万安家东三环222</li>
<li>北京首现零首付楼盘 53万购东5环50平222</li>
<li>京楼盘直降5000 中信府 公园楼王现房222</li>
京楼盘直降10000 橡树湾 公园楼王现房
</ul>
</div>
<div id='div2'>
<img src='xxx'/>
</div>
好了我们现在和xpath一样写bf4指令来筛选我们想要的html标签
现在请对照上面的html代码看看bf4命令如何进行筛选:
bs4指令 | 代码含义 |
---|---|
select_one(’#div1’) | 找到id="div"的标签及其内部所有子标签 ,如果有多个匹配结果,只返回第一个,返回类型字符串 |
select(‘ul’) | 找到ul标签下的所有子标签,返回列表 |
find(‘ul’) | 找到ul标签下所有子标签。如果有多个匹配结果,只返回第一个,返回类型字符串 |
find_all(‘ul’,class_=“show2”) | 找到ul标签下所有class="show2"的标签及其内部所有标签,返回类型为列表 |
好了接下来和练习xpath一样,我们要练习代码:
不过你要先安装BeautifulSoup
打开Terminal输入命令行: pip3 install BeautifulSoup4敲回车 进行安装pip install bs4
然后再输入
然后我们就可以写代码了:
from bs4 import BeautifulSoup
data = '''
<div id='div1'>
<ul class="show1">
<li>275万购昌平邻铁三居 总价20万买一居</li>
<li>00万内购五环三居 140万安家东三环</li>
<li>北京首现零首付楼盘 53万购东5环50平</li>
<li>京楼盘直降5000 中信府 公园楼王现房</li>
京楼盘直降10000 橡树湾 公园楼王现房
</ul>
<ul class="show2">
<li><a href='#'>275万购昌平邻铁三居 总价20万买一居222</a>xxxxxx</li>
<li>00万内购五环三居 140万安家东三环222</li>
<li>北京首现零首付楼盘 53万购东5环50平222</li>
<li>京楼盘直降5000 中信府 公园楼王现房222</li>
京楼盘直降10000 橡树湾 公园楼王现房
</ul>
</div>
<div id='div2'>
<img src='xxx'/>
</div>
'''
soup = BeautifulSoup(data, 'lxml')
print(type(soup.ul))
print(soup.ul)
#选择器:select_one(selector) 选择器的名字查找
div= soup.select_one('#div1') # find()
print(div)
ul_list = soup.select('ul') # 类似find_all()
print(ul_list)
for ul in ul_list:
lis = ul.select('li')
print(lis[0].text)
divs = soup.find('ul') # [<div Tag>,<div Tag>]
print(divs)
div = soup.find_all('ul',class_="show2")
print(div)
ul = soup.find(id="div1")
print(ul)
e=soup.select_one('.show2 li a')
print(e.get('href'))
e=soup.select_one('.show1 li')
print(e.string)
print(e.text)
print(e.get_text())
e=soup.select_one('.show2 li')
#string方法没有办法获取到嵌套标签下内容
print(e.string)
print(e.text)
print(e.get_text())
这里给大家的建议是:
一次运行打印一行,剩余的注释掉。这样有利于理解 bf4命令
用BeautifulSoup爬取 指定内容(图片、文字)
1.爬取豆瓣影评
我们爬取的网站是庆余年豆瓣影评
这次我们要爬取多页评论,昨天我们用Xpath解析的是一页内容
怎么爬取多页呢?
我们分析页面切换时候的params(参数)变化,就是?后面那一堆
找到后经过分析我们发现:切换页面时候,params中的start参数每次增加20
# 评论信息爬取
# 豆瓣
import csv
import random
import re
import time
import requests
from bs4 import BeautifulSoup
from lxml import etree
user_agents = [
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'
]
# 1。获取html
def get_resource(url, params=None, flag='html'):
headers = {
'Host': 'movie.douban.com',
'User-Agent': random.choice(user_agents)
}
# 使用requests发出请求
response = requests.get(url=url, params=params, headers=headers)
# 判断response的状态码
if response.status_code == 200:
# 判断flag
if flag == 'html':
return response.text
elif flag == 'media':
return response.content
else:
print('获取资源有误!')
# 2. 解析网页内容
# 采用方式:beautifulSoup4
def parse_html_other(resource):
comment_list = []
soup = BeautifulSoup(resource, 'lxml')
comments = soup.select_one('#comments')
comment_items = comments.select('.comment-item')
for item in comment_items:
comment_info = item.select_one('.comment h3 .comment-info')
# 用户的头像
image = item.select_one('.avatar a img').get('src')
# 评价的用户名
username = comment_info.find('a').text
# 获取星级
star = comment_info.find('span', class_='rating')
# 有个人他没有星级评论,这里
if star:
star = star.get('title')
else:
# 如果这个家伙没有评论,就默认5星吧->力荐
star = '力荐'
# 评论内容
comment_text = item.find('span', attrs={'class': 'short'}).text
# 保存在一个列表中
comment = [username, star, image, comment_text]
# 将其添加到列表中
comment_list.append(comment)
return comment_list
# 3. 封装:持久化保存(保存数据)
def save_data(comment_list):
# 文件操作:csv [[],[],[],[],[]]
# a 是追加模式,不然覆盖的话就剩下最后一页的了
with open('data/douban.csv', mode='a', newline='', encoding='utf-8') as fw:
writer = csv.writer(fw)
# 遍历评论列表
writer.writerows(comment_list)
print('保存完毕!')
# 只在本类下调用运行,其他类导入的话程序不会运行
if __name__ == '__main__':
url = 'https://movie.douban.com/subject/25853071/comments'
params = {'status': 'P', 'limit': 20, 'sort': 'new_score'}
for i in range(10):
n = i * 20
params['start'] = n
# 调用函数获取资源
resource = get_resource(url=url, params=params)
# print(resource)
# 调用解析方法:bs4 获取所有的评论内容,并返回list内容
comment_list = parse_html_other(resource)
# 保存
save_data(comment_list)
# 延时
time.sleep(5)
print('成功下载第{}页评论....'.format(i + 1))
2. 爬取笔趣阁(小说)
我们要爬取的网站是笔趣阁小说网
请浏览后输入图书名然后点击搜索按下F12键分析html标签
点进去书籍看到章节内容再按下F12键分析html标签
下面的代码就是爬取小说,并下载到本地
我们这次是多页面爬取,实现爬虫页面跳转和跨页面抓取。
我们时刻注意着:链接的结构和变化规律
多页面爬取就像 剥大蒜一样,一层一层标签,一个一个页面访问,逐步逼近目标步步为营
这里需要大家熟练Xpath命令或者BeautifulSoup命令来进行解析网页(筛选)
import os
import random
import requests
from bs4 import BeautifulSoup
from lxml import etree
user_agents = [
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'
]
# 获取资源
def get_resource(url, params=None, flag='html'):
headers = {
'Host': 'www.biqukan.cc',
'User-Agent': random.choice(user_agents)
}
# 使用requests发出请求
response = requests.get(url=url, params=params, headers=headers)
print(response.status_code)
# 判断response的状态码
if response.status_code == 200:
# 判断flag
if flag == 'html':
print(response.encoding)
return response.text
elif flag == 'media':
return response.content
else:
print('获取资源有误!')
# 查询图书:
def search_book(url):
print('*' * 40)
print("*" * 12, '笔趣阁看小说下载', '*' * 12)
print('*' * 40)
name = input('输入作品名称:')
name = name.encode('gbk')
params = {'searchkey': name}
html = get_resource(url=url, params=params)
# print(html)
# 直接解析
book_list = []
if html:
search = etree.HTML(html)
divs = search.xpath(
'//div[@class="panel-body"]/div[@class="row"]/div[@class="col-md-4 col-xs-4 book-coverlist"]')
for div in divs:
try:
# link
link = div.xpath('div[@class="row"]/div[@class="col-md-5"]/a/@href')
# name
name = div.xpath('div[@class="row"]/div[@class="col-md-5"]/a/img/@alt')
# author
author = div.xpath(
'div[@class="row"]/div[@class="col-md-7 pl0 mb10"]/div[@class="caption"]/small//text()')
# description
description = div.xpath(
'div[@class="row"]/div[@class="col-md-7 pl0 mb10"]/div[@class="caption"]/p//text()')
book = [link[0], name[0], author[0], description[0]]
except:
continue
else:
book_list.append(book)
return book_list
# 获取每本书的章节内容
def get_chapter(url):
html = get_resource(url=url)
soup = BeautifulSoup(html, 'lxml')
dl_tag = soup.find_all('dl', attrs={'class': 'panel-body panel-chapterlist'})[1]
dd_tags = dl_tag.find_all('dd', attrs={'class': 'col-md-3'})
# 遍历dd标签
chapter_list = []
for dd in dd_tags:
# 从dd中可以取出内容
try:
a_tag = dd.select_one('a')
chapter_link = a_tag.get('href')
chapter_name = a_tag.get('title')
chapter = [chapter_link, chapter_name]
except:
continue
else:
chapter_list.append(chapter)
return chapter_list
# 获取章节详情
def chapter_detail(detail_url, path):
# 获取章节详情页面
html = get_resource(detail_url)
# 解析页面
soup = BeautifulSoup(html, 'lxml')
# 获取详情信息
div_content = soup.select_one('#htmlContent').text
print("detail:", div_content)
# 本地保存
with open(path, mode='w', encoding='utf-8') as fw:
div_content=div_content.replace('</br>','\n').replace(' ',' ')
fw.write(div_content)
if __name__ == '__main__':
url = 'https://www.biqukan.cc/modules/article/search.php'
book_list = search_book(url) # [['链接','书名','作者','简介'],[],[]]
# 此处只是获取book_list中的某一本书
book_url = book_list[0][0]
chapter_list = get_chapter(book_url) # [['6378944.html', '第四章 大山里的古墓'],[],[]]
for chapter in chapter_list:
detail_url = book_url + chapter[0] # https://www.biqukan.cc/book/15330/9085368.html
path = book_list[0][1] + "/" + chapter[1] + '.txt'
# 获取详情
chapter_detail(detail_url, path)
print('成功保存:', chapter[1])
'''
'''
看看pycharm左面的资源管理器,是不是已经下载了!!