页面解析和数据提取
一般来讲对我们而言,需要抓取的是某个网站或者某个应用的内容,提取有用的价值。内容一般分为两部分,非结构化的数据 和 结构化的数据。
-
非结构化数据:先有数据,再有结构,(http://www.baidu.com)
-
结构化数据:先有结构、再有数据(https://www.qiushibaike.com/imgrank/page/3/)
-
不同类型的数据,我们需要采用不同的方式来处理。
常用的数据解析有正则(re)、bs4、xpath等。
bs4
bs4解析原理
- 实例化一个BeautifulSoup的对象,需要将即将被解析的页面源码数据加载到对象中
- 调用BeautifulSoup对象中的相关方法和属性进行标签定位和数据提取
bs4解析流程
✏️ 环境安装
pip install bs4
✏️ 导入模块
from bs4 import BeautifulSoup
✏️ 实例化一个BeautifulSoup对象
# 转化本地文件(将本地存储的一个html文档中的数据加载到实例化好的BeautifulSoup对象中)
soup = BeautifulSoup(open(\'本地文件\'), \'lxml\')
# 转化网络文件(将从互联网上获取的页面源码数据加载到实例化好的BeautifulSoup对象中)
soup = BeautifulSoup(\'字符串类型或者字节类型\', \'lxml\')
✏️ 调用BeautifulSoup对象中的相关属性和方法进行标签的定位
bs4基本语法
1.根据标签名查找
soup.tagName
- soup.a 只能找到第一个符合要求的标签
2.获取属性
soup.tagName[\'attrName\']
- soup.a.attrs 获取a所有的属性和属性值,返回一个字典
- soup.a.attrs[\'href\'] 获取href属性
- soup.a[\'href\'] 也可简写为这种形式
3.获取内容
.string:获取直系的文本内容
.text:获取所有的文本内容
- soup.a.string 获取a标签的直系文本
- soup.a.text 这是属性,获取a子类的所有文本
- soup.a.get_text() 这是方法,获取a标签子类的所有文本
【注意】如果标签还有标签,那么string获取到的结果为None,而其它两个,可以获取文本内容
4.属性定位find方法
soup.find(\'tagName\', attrName=\'value\')
- soup.find(\'a\') 找到第一个符合要求的a标签
- soup.find(\'a\', title="xxx") 找具有title=xxx属性的第一个a标签
- soup.find(\'li\', alt="xxx") 找到具有alt=xxx属性的第一个li标签
- soup.find(\'ul\', class_="xxx") 找到具有class=xxx属性的第一个ui标签
- soup.find(\'div\', id="xxx") 找到具有id=xxx属性的第一个div标签
5.属性定位find_all方法
soup.find_all(\'tagName\', attrName=\'value\'),返回值为列表
- soup.find_all(\'a\') #找到所有a标签
- soup.find_all(\'a\', title=\'xxx\') 找到具有title=xxx属性的所有a标签
- soup.find_all(\'div\', class_=\'xxx\', limit=3) 找到具有class=xxx属性的前三个标签
6.选择器定位select方法
soup.select(\'选择器\')
- soup.select(\'.song\') 找到类属性为song的标签
- soup.select(\'#song\') 找到id属性为song的标签
- 常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器
- 层级选择器:
div .haha #wan 空格表示多个层级
div > p > a > img >表示一个层级
bs4爬虫示例
✏️ 爬取三国整篇内容
#爬取三国整篇内容(章节名称和章节内容) http://www.shicimingju.com/book/sanguoyanyi.html
import requests
from bs4 import BeautifulSoup
fp = open(\'sanguo.txt\',\'w\',encoding=\'utf-8\')
headers = {
\'User-Agent\': \'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36\'
}
main_url = \'http://www.shicimingju.com/book/sanguoyanyi.html\'
page_text = requests.get(url=main_url, headers=headers).text
#解析出章节名称和章节详情的url
soup = BeautifulSoup(page_text, \'lxml\')
a_list = soup.select(\'.book-mulu > ul >li > a\') #返回的列表中存储的是一个个a标签
for a in a_list:
title = a.string
detail_url = \'http://www.shicimingju.com\'+a[\'href\']
detail_page_text = requests.get(detail_url, headers=headers).text
#解析详情页中的章节内容
soup = BeautifulSoup(detail_page_text, \'lxml\')
content = soup.find(\'div\', class_=\'chapter_content\').text
fp.write(title+\':\'+content+\'\\n\')
print(title,\'下载成功!\')
fp.close
xpath
xpath解析原理
- 实例化一个etree的对象,然后将即将被解析的页面源码加载到该对象中
- 使用etree对象中xpath方法结合着不同形式的xpath表达式实现标签定位和数据提取
xpath解析流程
✏️ 环境安装
pip install lxml
✏️ 导入模块
from lxml import etree
✏️ 实例化一个etree对象
# 转化本地文件(将本地存储的一个html文档中的数据加载到实例化好的tree对象中)
tree = etree.parse(\'test.html\')
# 转化网络文件(将从互联网上获取的页面源码数据加载到实例化好的tree对象中)
tree = etree.HTML(page_text)
xpath基本语法
xpath表达式:xpath方法的返回值一定是一个列表
最左侧的/表示:xpath表达式一定要从根标签逐层进行标签查询和定位
最左侧的//表示:xpath表达式可以从任意位置定位标签
非最左侧的/:表示一个层级
非最左侧的//:表示夸多个层级
属性定位://tagName[@attrName=\'value\']
索引定位://tagName[index] 索引从1开始
1.取文本:
- /text():直系文本内容
- //text():所有文本内容
2.取属性:
/@attrName
示例
准备html内容
<html><body>
<div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>
</ul>
</div>
</body></html>
1.获取所有的
from lxml import etree
html = etree.parse(\'hello.html\')
result = html.xpath(\'//li\')
print(result) # 打印<li>标签的元素集合
result_text = html.xpath(\'//li/text()\')
2.获取
from lxml import etree
html = etree.parse(\'hello.html\')
result = html.xpath(\'//li/@class\')
print result
结果是
[\'item-0\', \'item-1\', \'item-inactive\', \'item-1\', \'item-0\']
3.继续获取<li>
标签下href
为 link1.html
的 <a>
标签
from lxml import etree
html = etree.parse(\'hello.html\')
result = html.xpath(\'//li/a[@href="link1.html"]\')
print result
运行结果
[<Element a at 0x10ffaae18>]
4.获取最后一个 <li>
的 <a>
的 href
from lxml import etree
html = etree.parse(\'hello.html\')
result = html.xpath(\'//li[last()]/a/@href\')
# 谓语 [last()] 可以找到最后一个元素
print result
运行结果
[\'link5.html\']
xpath 爬虫示例
以上是关于Python--爬虫数据解析的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向使用 Python 解析 ELF 文件 ( Capstone 反汇编 ELF 文件中的机器码数据 | 创建反汇编解析器实例对象 | 设置汇编解析器显示细节 )(代码片段