官方文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.html
官方文档中文版:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/
下载源码包(tar.gz)安装
安装解析器:BeautifulSoup4 本身只包含解析器接口规则,支持 python 内置的 HTML 解析器,同时支持第三方的一些解析器[如 lxml] 如果使用过程中没有指定使用解析器,BeautifulSoup4 会自动从当前的 python 环境中检索最优的解析器加载使用
pip install lxml or pip install html5lib
解析器 | 使用 | 优缺点 |
标准库 | BeautifulSoup(html, ‘html.parser’) | 优点: 内置标准库、执行速度适中、容错能力强 缺点: 对中文解析的容错能力有限 |
lxml | BeautifulSoup(html, ‘lxml’) | 优点: 速度快,容错能力强 缺点: 需要安装 c 语言库 |
lxml | BeautifulSoup(html, [‘lxml’, ‘xml’]) | 唯一支持 XML 的解析器 |
html5lib | BeautifulSoup(html, ‘html5lib’) | 优点: 容错能力最好 浏览器方式解析文档 生成 H5 格式的文档 缺点: 速度慢 不依赖外部扩展 |
综上所述:优先推荐使用 lxml 解析器
BeautifulSoup4(BS4)可以将一个 html 文档数据流或者 html 文档对象或者 html 字符串,直接加载到 BS4 对象中,得到一个 BS4 的文档对象
from bs4 import BeautifulSoup
soup = BeautifulSoup(open(‘index.html’)) #本地要有这个网页如果没有就从网站直接获取
soup = BeautifulSoup(‘……’)
BeautifulSoup4 将 HTML结构化文档,解析为树形结构化数据,树形文档对象中主要包含四种对象
案例操作:
# 目标数据
html_doc = """
The Dormouse's story
Once upon a time there were three little sisters; and their names were
Elsie, Lacie and Tillie; and they lived at the bottom of a well.
...
“””
from bs4 import BeautifulSoup # 构建 bs4 文档对象
soup = BeautifulSoup(html_doc, 'lxml')
print(type(soup)) #
# 节点名称查询
print(soup.title) #
print(soup.p) #
The Dormouse's story
print(soup.a) # Elsie
# 子节点查询
chs = soup.contents print(type(chs), len(chs)) #
chs2 = soup.children print(type(chs2), len(list(chs2))) #
# 包含节点查询
chs3 = soup.descendants print(type(chs3), len(list(chs3))) #
# 子节点内容获取
# 获取节点内部文本数据
print(soup.title.string) # The Dormouse's story
# 获取文本节点的文本数据
print(soup.title.contents[0].string) # The Dormouse's story
# 如果包含子节点并且不是文本节点,返回 None print(soup.body.string) # None
# 获取包含的所有文本数据,包括空白字符 print(soup.body.strings) #
# 获取包含的所有文本数据,剔除空白字符
print(soup.body.stripped_strings) #
⚫ find(name, attrs, recursive, text, **kwargs) ◼
查询得到一个节点对象数据,如果结果不存在返回 None ◼
⚫ find_all(name, attrs, recursive, text, limit, **kwargs) ◼
⚫ 查询过滤操作 ◼
⚫ 其他查询 ◼
⚫ beautifulsoup.select(css syntax) #css查询
https://www.autohome.com.cn 获取所拥有车的名称及新手指导价
http://www.6pifa.net/ 爬取商品图片、名称及价格,信息按类别分别放入不同的文本文件
https://b.faloo.com/将小说章节及内容按名称存储到不同的文件中
http://www.williamlong.info/ 爬取所有新闻内容及发布日期
http://sports.sina.com.cn/global/ 获得所有 西甲联赛 相关新闻标题和文字内容
http://www.zhcw.com/ssq/ 所有双色球新闻标题、内容
https://www.cnblogs.com/cate/python/ 获取 python 相关标题及内容
案例代码参考:
"""
Version 1.1.0
Author lkk
Email [email protected]
date 2018-12-01 14:36
DESC NEWS新闻爬取
http://www.williamlong.info/
"""
from urllib import request
from bs4 import BeautifulSoup
import chardet
import re
from fake_useragent import UserAgent
import pymysql
class DownMysql:
def __init__(self, date, title, author_1, content, classify, target, scan):
self.date = date
self.title = title
self.author_1 = author_1
self.content = content
self.classify = classify
self.target = target
self.scan = scan
self.connect = pymysql.connect(
host='localhost',
db='data',
port=3306,
user='root',
passwd='123456',
charset='utf8',
use_unicode=False
)
self.cursor = self.connect.cursor()
# 保存数据到MySQL中
def save_mysql(self):
sql = "insert into blog(date, title, author_1, content, classify, target, scan) VALUES (%s,%s,%s,%s,%s,%s,%s)"
try:
self.cursor.execute(sql, (self.date, self.title, self.author_1, self.content, self.classify, self.target, self.scan))
self.connect.commit()
print('数据插入成功')
except Exception as e:
print(e, '数据插入错误')
# 新建对象,然后将数据传入类中
def mysql(date, title, author_1, content, classify, target, scan):
down = DownMysql(date, title, author_1, content, classify, target, scan)
down.save_mysql()
def target_data(url):
ua = UserAgent()
headers = {
'User-agent': ua.random
}
start_url = request.Request(url, headers=headers)
response = request.urlopen(start_url)
data = response.read()
encoding = chardet.detect(data).get('encoding')
data_info = data.decode(encoding, 'ignore')
soup = BeautifulSoup(data_info, 'lxml')
return soup
def core(url):
soup = target_data(url)
date = soup.select('h4[class="post-date"]')
title = soup.select('h2[class="post-title"]')
content = soup.select('div[class=post-body]')
author = soup.select('h6[class="post-footer"]')
classify = soup.select('h6[class="post-footer"] > a:nth-of-type(1)')
target = soup.select('h6[class="post-footer"] > a:nth-of-type(2)')
for i in range(len(date)):
authors = author[i].text.strip()
scan = re.findall(r'.*?浏览:(.*?)\s+|', authors)[0]
author_1 = re.findall(r'作者:(.*?)\s+|', authors)[0]
mysql(date[i].text.strip(), title[i].text.strip(), author_1, content[i].text.strip(), classify[i].text.strip(), target[i].text.strip(), scan)
url = 'https://www.williamlong.info/cat/?page='
if __name__ == '__main__':
for j in range(1, 185):
next_url = url + str(j)
print(next_url)
core(next_url)