Python爬虫实战一之使用Beautiful Soup抓取‘谣言百科’的分类内容
2017-07-15 14:12
881 查看
Beautiful Soup功能介绍
简介
Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你节省数小时甚至数天的工作时间.
Beautiful Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。Beautiful Soup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful
Soup就不能自动识别编码方式了。
支持的解析器
Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,其中一个是lxml .根据操作系统不同,可以选择下列方法来安装lxml
解析器
使用简单案例
解析的对象种类
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:
,
<1>Tag
(1)tag中最重要的属性: name和attributes
每个tag都有自己的名字,通过
有一个 “class” 的属性,值为 “boldest” . tag的属性的操作方法与字典相同,如下
(2) 可以遍历的字符串
字符串常被包含在tag内.Beautiful Soup用
print tag.string-----------Hello World!
(3)注释及特殊字符串
几乎覆盖了html和xml中的所有内容,但是还有一些特殊对象.容易让人担心的内容是文档的注释部分:
(4)遍历文档树
子节点
一个Tag可能包含多个字符串或其它的Tag,这些都是这个Tag的子节点.Beautiful Soup提供了许多操作和遍历子节点的属性.
注意: Beautiful Soup中字符串节点不支持这些属性,因为字符串没有子节点
循环遍历:
如果想要得到所有的<a>标签,或是通过名字得到比一个tag更多的内容的时候,就需要用到Searching the tree 中描述的方法,比如: find_all()
print soup.find_all('a')
1).contents 和 .children
tag的
通过tag的 .children 生成器,可以对tag的子节点进行循环
2).descendants 属性可以对所有tag的子孙节点进行递归循环 [5]
3).strings 和 stripped_strings
如果tag中包含多个字符串 [2] ,可以使用 .strings 来循环获取:
输出的字符串中可能包含了很多空格或空行,使用 .stripped_strings 可以去除多余空白内容
父节点
1).parent
通过 .parent 属性来获取某个元素的父节点.在例子“爱丽丝”的文档中,<head>标签是<title>标签的父节点
2).parents
通过元素的 .parents 属性可以递归得到元素的所有父辈节点,下面的例子使用了 .parents 方法遍历了<a>标签到根节点的所有节点.
兄弟节点
1).next_sibling 和 .previous_sibling
在文档树中,使用 .next_sibling 和 .previous_sibling 属性来查询兄弟节点
2).next_siblings 和 .previous_siblings
通过 .next_siblings 和 .previous_siblings 属性可以对当前节点的兄弟节点迭代输出
回退或前进
1).next_element 和 .previous_element
.next_element 属性指向解析过程中下一个被解析的对象(字符串或tag),结果可能与 .next_sibling 相同,但通常是不一样的.
2).next_elements 和 .previous_elements
通过 .next_elements 和 .previous_elements 的迭代器就可以向前或向后访问文档的解析内容,就好像文档正在被解析一样:
(5)搜索文档树
过滤器----find_all()
1)字符串
最简单的过滤器是字符串.在搜索方法中传入一个字符串参数,Beautiful Soup会查找与字符串完整匹配的内容,下面的例子用于查找文档中所有的<b>标签:
soup.find_all('b')
2)正则表达式
如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容.下面例子中找出所有以b开头的标签,这表示<body>和<b>标签都应该被找到
import re
for tag in soup.find_all(re.compile("^b")):
print(tag.name)
3)列表
如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.下面代码找到文档中所有<a>标签和<b>标签:
soup.find_all(["a", "b"])
4)True
True 可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点
for tag in soup.find_all(True):
print(tag.name)
5)方法
如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数 [4] ,如果这个方法返回 True 表示当前元素匹配并且被找到,如果不是则反回 False
下面方法校验了当前元素,如果包含 class 属性却不包含 id 属性,那么将返回 True:
def has_class_but_no_id(tag):
return tag.has_attr('class') and not tag.has_attr('id')
将这个方法作为参数传入 find_all() 方法,将得到所有<p>标签:
soup.find_all(has_class_but_no_id)
# [<p class="title"><b>The Dormouse's story</b></p>,
# <p class="story">Once upon a time there were...</p>,
# <p class="story">...</p>]
6)name 参数
name 参数可以查找所有名字为 name 的tag,字符串对象会被自动忽略掉.
简单的用法如下:
soup.find_all("title")
# [<title>The Dormouse's story</title>]
重申: 搜索 name 参数的值可以使任一类型的 过滤器 ,字符窜,正则表达式,列表,方法或是 True .
keyword 参数
如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性.
soup.find_all(id='link2')
# [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
如果传入 href 参数,Beautiful Soup会搜索每个tag的”href”属性:
soup.find_all(href=re.compile("elsie"))
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
搜索指定名字的属性时可以使用的参数值包括 字符串 , 正则表达式 , 列表, True .
其它详见:http://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/
Beautiful Soup抓取‘谣言百科’的分类内容
源代码:
执行结果:
简介
Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你节省数小时甚至数天的工作时间.
Beautiful Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。Beautiful Soup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful
Soup就不能自动识别编码方式了。
支持的解析器
Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,其中一个是lxml .根据操作系统不同,可以选择下列方法来安装lxml
解析器
使用方法 | 优势 | 劣势 | |
---|---|---|---|
Python标准库 | BeautifulSoup(markup,"html.parser") | Python的内置标准库 执行速度适中 文档容错能力强 | Python 2.7.3 or 3.2.2)前的版本中文档容错能力差 |
lxml HTML 解析器 | BeautifulSoup(markup,"lxml") | 速度快 文档容错能力强 | 需要安装C语言库 |
lxml XML 解析器 | BeautifulSoup(markup,["lxml-xml"]) BeautifulSoup(markup,"xml") | 速度快 唯一支持XML的解析器 | 需要安装C语言库 |
html5lib | BeautifulSoup(markup,"html5lib") | 最好的容错性 以浏览器的方式解析文档 生成HTML5格式的文档 | 速度慢 不依赖外部扩 |
from bs4 import BeautifulSoup soup = BeautifulSoup(open("index.html")) soup = BeautifulSoup("<html>data</html>") print BeautifulSoup("Hello World!") 执行结果:<html><body><p>Hello World!</p></body></htm
解析的对象种类
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:
Tag,
NavigableString
,
BeautifulSoup,
Comment
<1>Tag
Tag对象与XML或HTML原生文档中的tag相同,
soup = BeautifulSoup('<b class="boldest">Extremely bold</b>') tag = soup.b type(tag) # <class 'bs4.element.Tag'>
(1)tag中最重要的属性: name和attributes
每个tag都有自己的名字,通过
.name来获取,一个tag可能有很多个属性. tag
<bclass="boldest">
有一个 “class” 的属性,值为 “boldest” . tag的属性的操作方法与字典相同,如下
getsoup=BeautifulSoup("<html><body><p class='test'>Hello World!</p></body></html>") tag=getsoup.p print tag print tag.name print tag['class'] ----结果---- <body><p>Hello World!</p></body> body ['test']
(2) 可以遍历的字符串
字符串常被包含在tag内.Beautiful Soup用
NavigableString类来包装tag中的字符串:
print tag.string-----------Hello World!
(3)注释及特殊字符串
Tag,
NavigableString,
BeautifulSoup
几乎覆盖了html和xml中的所有内容,但是还有一些特殊对象.容易让人担心的内容是文档的注释部分:
markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>" soup = BeautifulSoup(markup) comment = soup.b.string print type(comment) print comment
<class 'bs4.element.NavigableString'> Hey, buddy. Want to buy a used parser?
(4)遍历文档树
子节点
一个Tag可能包含多个字符串或其它的Tag,这些都是这个Tag的子节点.Beautiful Soup提供了许多操作和遍历子节点的属性.
注意: Beautiful Soup中字符串节点不支持这些属性,因为字符串没有子节点
循环遍历:
如果想要得到所有的<a>标签,或是通过名字得到比一个tag更多的内容的时候,就需要用到Searching the tree 中描述的方法,比如: find_all()
print soup.find_all('a')
1).contents 和 .children
tag的
.contents属性可以将tag的子节点以列表的方式输出
通过tag的 .children 生成器,可以对tag的子节点进行循环
2).descendants 属性可以对所有tag的子孙节点进行递归循环 [5]
3).strings 和 stripped_strings
如果tag中包含多个字符串 [2] ,可以使用 .strings 来循环获取:
输出的字符串中可能包含了很多空格或空行,使用 .stripped_strings 可以去除多余空白内容
父节点
1).parent
通过 .parent 属性来获取某个元素的父节点.在例子“爱丽丝”的文档中,<head>标签是<title>标签的父节点
2).parents
通过元素的 .parents 属性可以递归得到元素的所有父辈节点,下面的例子使用了 .parents 方法遍历了<a>标签到根节点的所有节点.
兄弟节点
1).next_sibling 和 .previous_sibling
在文档树中,使用 .next_sibling 和 .previous_sibling 属性来查询兄弟节点
2).next_siblings 和 .previous_siblings
通过 .next_siblings 和 .previous_siblings 属性可以对当前节点的兄弟节点迭代输出
回退或前进
1).next_element 和 .previous_element
.next_element 属性指向解析过程中下一个被解析的对象(字符串或tag),结果可能与 .next_sibling 相同,但通常是不一样的.
2).next_elements 和 .previous_elements
通过 .next_elements 和 .previous_elements 的迭代器就可以向前或向后访问文档的解析内容,就好像文档正在被解析一样:
(5)搜索文档树
过滤器----find_all()
1)字符串
最简单的过滤器是字符串.在搜索方法中传入一个字符串参数,Beautiful Soup会查找与字符串完整匹配的内容,下面的例子用于查找文档中所有的<b>标签:
soup.find_all('b')
2)正则表达式
如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容.下面例子中找出所有以b开头的标签,这表示<body>和<b>标签都应该被找到
import re
for tag in soup.find_all(re.compile("^b")):
print(tag.name)
3)列表
如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.下面代码找到文档中所有<a>标签和<b>标签:
soup.find_all(["a", "b"])
4)True
True 可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点
for tag in soup.find_all(True):
print(tag.name)
5)方法
如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数 [4] ,如果这个方法返回 True 表示当前元素匹配并且被找到,如果不是则反回 False
下面方法校验了当前元素,如果包含 class 属性却不包含 id 属性,那么将返回 True:
def has_class_but_no_id(tag):
return tag.has_attr('class') and not tag.has_attr('id')
将这个方法作为参数传入 find_all() 方法,将得到所有<p>标签:
soup.find_all(has_class_but_no_id)
# [<p class="title"><b>The Dormouse's story</b></p>,
# <p class="story">Once upon a time there were...</p>,
# <p class="story">...</p>]
6)name 参数
name 参数可以查找所有名字为 name 的tag,字符串对象会被自动忽略掉.
简单的用法如下:
soup.find_all("title")
# [<title>The Dormouse's story</title>]
重申: 搜索 name 参数的值可以使任一类型的 过滤器 ,字符窜,正则表达式,列表,方法或是 True .
keyword 参数
如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性.
soup.find_all(id='link2')
# [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
如果传入 href 参数,Beautiful Soup会搜索每个tag的”href”属性:
soup.find_all(href=re.compile("elsie"))
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
搜索指定名字的属性时可以使用的参数值包括 字符串 , 正则表达式 , 列表, True .
其它详见:http://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/
Beautiful Soup抓取‘谣言百科’的分类内容
源代码:
# -*- coding:UTF-8 -*- # 2017年7月15日 # 爬虫目标网站:http://www.yaoyanbaike.com/ # 获取信息BeautifulSoup+request import urllib2 from bs4 import BeautifulSoup import re import codecs if __name__ == "__main__": text_file_number = 0 # 同一类新闻下的索引数 number = 1 # 同类别新闻不同页面下的索引数 while (number <= 2): if number==1: # 第一个新闻下地址是baby不是baby_数字所以要区分判断一下 get_url = 'http://www.yaoyanbaike.com/category/baby.html' else: get_url = 'http://www.yaoyanbaike.com/category/baby_'+str(number)+'.html' #这个是baby_数字,number就是目录索引数 head = {} #设置头 head['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0' # 模拟浏览器模式,定制请求头 download_req_get = urllib2.Request(url = get_url, headers = head) # 设置Request download_response_get = urllib2.urlopen(download_req_get) # 设置urlopen获取页面所有内容 download_html_get = download_response_get.read().decode('UTF-8','ignore') # UTF-8模式读取获取的页面信息标签和内容 soup_texts = BeautifulSoup(download_html_get, 'lxml') # BeautifulSoup读取页面html标签和内容的信息 for link in soup_texts.find_all(["a"]): print(str(text_file_number)+" "+str(number)+" "+str(link.get('title'))) # 打印文件地址用于测试 s=link.get('href') if s.find("/a/") == -1: print("错误网址") # 只有包含"/a/"字符的才是有新闻的有效地址 else: download_url = link.get('href') head = {} head['User-Agent'] = 'Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19' download_req = urllib2.Request(url = "http://www.yaoyanbaike.com"+download_url, headers = head) download_response = urllib2.urlopen(download_req) download_html = download_response.read().decode('UTF-8','ignore') soup_texts = BeautifulSoup(download_html, 'lxml') texts = soup_texts.find_all('article') soup_text = BeautifulSoup(str(texts), 'lxml') p = re.compile("<[^>]+>") text=p.sub("", str(soup_text)) # 去除页面标签 f1 = codecs.open('E:\pic\\'+str(text_file_number)+'--'+str(link.get('title')).decode('utf-8')+'.txt','w','UTF-8') # f1 = codecs.open('E:\pic\\'+str(text_file_number)+'.txt','w','UTF-8') # 排序id+按标题名称将信息存储在本地 f1.write(text) f1.close() text_file_number = text_file_number + 1 number = number + 1
执行结果:
相关文章推荐
- Python爬虫实战一之使用Beautiful Soup抓取百度招聘信息并存储excel文件
- Python爬虫使用Selenium+PhantomJS抓取Ajax和动态HTML内容
- Python使用Srapy框架爬虫模拟登陆并抓取知乎内容
- 零基础写python爬虫之使用urllib2组件抓取网页内容
- python3 [爬虫入门实战] 爬虫之selenium 模拟QQ登陆抓取好友说说内容(暂留)
- python3 [爬虫入门实战] 爬虫之使用selenium 爬取百度招聘内容并存mongodb
- Python爬虫实战(1)——百度贴吧抓取帖子并保存内容和图片
- Python爬虫使用Selenium+PhantomJS抓取Ajax和动态HTML内容
- Python使用Srapy框架爬虫模拟登陆并抓取知乎内容
- 零基础写python爬虫之使用urllib2组件抓取网页内容
- 萌新的Python学习日记 - 爬虫无影 - 使用BeautifulSoup + css selector 抓取自己想要网页内容
- [置顶] [爬虫]使用python抓取京东全站数据(商品,店铺,分类,评论)
- Python爬虫使用Selenium+PhantomJS抓取Ajax和动态HTML内容
- Python爬虫入门实战七:使用Selenium--以抓取QQ空间好友说说为例
- Python爬虫使用Selenium+PhantomJS抓取Ajax和动态HTML内容
- python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息,抓取政府网新闻内容
- 萌新的Python学习日记 - 爬虫无影 - 使用BeautifulSoup + css selector 抓取动态网页内容:Knewone
- python爬虫之使用urllib2组件抓取网页内容
- python爬虫爬取指定用户微博图片及内容,并进行微博分类及使用习惯分析,生成可视化图表
- python 爬虫 实战(一) —— 抓取学校开课数据