、安装
Beautiful Soup 是一个HTML/XML的解析器,主要的功能也是如何解析和提取 HTML/XML 数据。
lxml 只会局部遍历,而Beautiful Soup 是基于HTML DOM的,会载入整个文档,解析整个DOM树,因此时间和内存开销都会大很多,所以性能要低于lxml。
BeautifulSoup 用来解析 HTML 比较简单,API非常人性化,支持CSS选择器、Python标准库中的HTML解析器,也支持 lxml 的 XML解析器。
pip install beautifulsoup4
二、使用案例
from bs4 import BeautifulSoup
import requests
import asyncio
import functools
import re
house_info=[]
'''异步请求获取链家每页数据'''
async def get_page(page_index):
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36'
}
request=functools.partial(requests.get, f'https://sh.lianjia.com/ershoufang/pudong/pg{page_index}/',
headers=headers)
loop=asyncio.get_running_loop()
response=await loop.run_in_executor(None, request)
return response
'''使用xpath获取房屋信息'''
def get_house_info(soup):
house_info_list=soup.select('.info') # 房屋title
reg=re.compile(r'\n|\s')
for html in house_info_list:
house_info.append({
'title': re.sub(reg,'',html.select('.title a')[0].getText()),
'house_pattern': re.sub(reg,'',html.select('.houseInfo')[0].getText()),
'price': re.sub(reg,'',html.select('.unitPrice')[0].getText()),
'location': re.sub(reg,'',html.select('.positionInfo')[0].getText()),
'total': re.sub(reg,'',html.select('.totalPrice')[0].getText())
})
'''异步获取第一页数据,拿到第一页房屋信息,并返回分页总数和当前页'''
async def get_first_page():
response=await get_page(1)
soup=BeautifulSoup(response.text, 'lxml')
get_house_info(soup)
print(house_info)
if __name__=='__main__':
asyncio.run(get_first_page())
三、创建soup对象
soup=BeautifulSoup(markup="", features=None, builder=None,parse_only=None, from_encoding=None, exclude_encodings=None,element_classes=None)
解析器 | 使用方法 | 优势 | 劣势 |
Python标准库 | BeautifulSoup(markup,"html.parser") | Python 的内置标准库、执行速度适中 、文档容错能力强 | Python 2.7.3 or3.2.2) 前的版本中文容错能力差 |
LXML HTML 解析器 | BeautifulSoup(markup,"lxml") | 速度快、文档容错能力强 | 需要安装 C 语言库 |
LXML XML解析器 | BeautifulSoup(markup,"xml") | 速度快、唯一支持 XML 的解析器 | 需要安装 C 语言库 |
html5lib | BeautifulSoup(markup,"html5lib") | 最好的容错性、以浏览器的方式解析文档、生成 HTML5 格式的文档 | 速度慢、不依赖外部扩展 |
四、soup对象
析动态内容
根据权威机构发布的全球互联网可访问性审计报告,全球约有四分之三的网站其内容或部分内容是通过JavaScript动态生成的,这就意味着在浏览器窗口中“查看网页源代码”时无法在HTML代码中找到这些内容,也就是说我们之前用的抓取数据的方式无法正常运转了。解决这样的问题基本上有两种方案,一是JavaScript逆向工程;另一种是渲染JavaScript获得渲染后的内容。
JavaScript逆向工程
下面我们以“360图片”网站为例,说明什么是JavaScript逆向工程。其实所谓的JavaScript逆向工程就是找到通过Ajax技术动态获取数据的接口。
但是当我们在浏览器中通过右键菜单“显示网页源代码”的时候,居然惊奇的发现页面的HTML代码中连一个<img>标签都没有,那么我们看到的图片是怎么显示出来的呢?原来所有的图片都是通过JavaScript动态加载的,而在浏览器的“开发人员工具”的“网络”中可以找到获取这些图片数据的网络API接口,
那么结论就很简单了,只要我们找到了这些网络API接口,那么就能通过这些接口获取到数据,当然实际开发的时候可能还要对这些接口的参数以及接口返回的数据进行分析,了解每个参数的意义以及返回的JSON数据的格式,这样才能在我们的爬虫中使用这些数据。
关于如何从网络API中获取JSON格式的数据并提取出我们需要的内容,在之前的《文件和异常》一文中已经讲解过了,这里不再进行赘述。
使用Selenium
尽管很多网站对自己的网络API接口进行了保护,增加了获取数据的难度,但是只要经过足够的努力,绝大多数还是可以被逆向工程的,但是在实际开发中,我们可以通过浏览器渲染引擎来避免这些繁琐的工作,WebKit就是一个利用的渲染引擎。
WebKit的代码始于1998年的KHTML项目,当时它是Konqueror浏览器的渲染引擎。2001年,苹果公司从这个项目的代码中衍生出了WebKit并应用于Safari浏览器,早期的Chrome浏览器也使用了该内核。在Python中,我们可以通过Qt框架获得WebKit引擎并使用它来渲染页面获得动态内容,关于这个内容请大家自行阅读《爬虫技术:动态页面抓取超级指南》一文。
如果没有打算用上面所说的方式来渲染页面并获得动态内容,其实还有一种替代方案就是使用自动化测试工具Selenium,它提供了浏览器自动化的API接口,这样就可以通过操控浏览器来获取动态内容。首先可以使用pip来安装Selenium。
pip3 install selenium
下面以“阿里V任务”的“直播服务”为例,来演示如何使用Selenium获取到动态内容并抓取主播图片。
import requests from bs4 import BeautifulSoup def main(): resp=requests.get('https://v.taobao.com/v/content/live?catetype=704&from=taonvlang') soup=BeautifulSoup(resp.text, 'lxml') for img_tag in soup.select('img[src]'): print(img_tag.attrs['src']) if __name__=='__main__': main()
运行上面的程序会发现没有任何的输出,因为页面的HTML代码上根本找不到<img>标签。接下来我们使用Selenium来获取到页面上的动态内容,再提取主播图片。
from bs4 import BeautifulSoup from selenium import webdriver from selenium.webdriver.common.keys import Keys def main(): driver=webdriver.Chrome() driver.get('https://v.taobao.com/v/content/live?catetype=704&from=taonvlang') soup=BeautifulSoup(driver.page_source, 'lxml') for img_tag in soup.body.select('img[src]'): print(img_tag.attrs['src']) if __name__=='__main__': main()
在上面的程序中,我们通过Selenium实现对Chrome浏览器的操控,如果要操控其他的浏览器,可以创对应的浏览器对象,例如Firefox、IE等。运行上面的程序,如果看到如下所示的错误提示,那是说明我们还没有将Chrome浏览器的驱动添加到PATH环境变量中,也没有在程序中指定Chrome浏览器驱动所在的位置。
selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in PATH. Please see https://sites.google.com/a/chromium.org/chromedriver/home
为了解决上面的问题,可以到Selenium的官方网站找到浏览器驱动的下载链接并下载需要的驱动,在Linux或macOS系统下可以通过下面的命令来设置PATH环境变量,Windows下配置环境变量也非常简单,不清楚的可以自行了解。
export PATH=$PATH:/Users/Hao/Downloads/Tools/chromedriver/
其中/Users/Hao/Downloads/Tools/chromedriver/就是chromedriver所在的路径。
eautiful Soup 包:
Beautiful Soup: Python 的第三方插件用来提取 xml 和 HTML 中的数据。官网地址 https://www.crummy.com/software/BeautifulSoup/
1、安装 Beautiful Soup
打开 cmd(命令提示符),进入到 Python(Python2.7版本)安装目录中的 scripts 下,输入 dir 查看是否有 pip.exe, 如果用就可以使用 Python 自带的 pip 命令进行安装,输入以下命令进行安装即可:
pip install beautifulsoup4
2、测试是否安装成功
编写一个 Python 文件,输入:
import bs4
print bs4
运行该文件,如果能够正常输出则安装成功。
五、使用 Beautiful Soup 解析 html 文件
# -*- coding: UTF-8 -*-
import bs4
import re
from bs4 import BeautifulSoup
html_doc="""
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><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>
"""
# 创建一个BeautifulSoup解析对象
soup=BeautifulSoup(html_doc, "html.parser", from_encoding="utf-8")
# 获取所有的链接
links=soup.find_all('a')
print("所有的链接")
for link in links:
print(link.name, link['href'], link.get_text())
print("获取特定的URL地址")
link_node=soup.find('a', href="http://example.com/elsie")
print(link_node.name, link_node['href'], link_node['class'], link_node.get_text())
print("正则表达式匹配")
link_node=soup.find('a', href=re.compile(r"ti"))
print(link_node.name, link_node['href'], link_node['class'], link_node.get_text())
print("获取P段落的文字")
p_node=soup.find('p', class_='story')
print(p_node.name, p_node['class'], p_node.get_text())
===========
输出:
*请认真填写需求信息,我们会在24小时内与您取得联系。