python爬取网页
文章目录
html网页
head
link
<link> 标签定义文档与外部资源的关系。
rel 属性规定当前文档与被链接文档之间的关系。
rel=”canonical”属性值 告诉搜索引擎当前网站中的重复或相似的网页中,哪一个页面才是站长想让其抓取与收录的。
meat
<meat> 提供了 HTML 文档的元数据。元数据不会显示在客户端,但是会被浏览器解析。
script及style
head里面基本就是link还有meat,其他就还有js的<script>以及css的<style>了。
body
div
<div> 是一个块级元素。这意味着它的内容自动地开始一个新行。实际上,换行是
main
<main> 元素中的内容对于文档来说应当是唯一的。它不应包含在文档中重复出现的内容,比如侧栏、导航栏、版权信息、站点标志或搜索表单。
注释:在一个文档中,不能出现一个以上的 <main> 元素。<main> 元素不能是以下元素的后代:<article>、<aside>、<footer>、<header> 或 <nav>。
无用的元素
svg
SVG 意为可缩放矢量图形,使用 XML 格式定义图像。
ul
定义无序 HTML 列表。在csdn中,目前发现用于标题和代码块前的序号。
hljs-button属性
按钮样式
class
类名,用于应用css样式
name
name 属性用于指定锚(anchor)的名称。
id
id 属性规定 HTML 元素的唯一的 id。id 在 HTML 文档中必须是唯一的。id 属性可用作链接锚(link anchor),通过 JavaScript(HTML DOM)或通过 CSS 为带有指定 id 的元素改变或添加样式。id 属性看作是 name 属性的升级版本。
onclick
当点击按钮时执行一段 JavaScript。
rel
rel 属性指示被链接的文档是一个样式表。
img
定义 HTML 页面中的图像
hr
在 HTML 页面中创建一条水平线
br
在文档中插入换行符。
beautifulsoap
Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据。
使用
将一段文档传入BeautifulSoup 的构造方法,就能得到一个文档的对象, 可以传入一段字符串或一个文件句柄.
from bs4 import BeautifulSoup
soup = BeautifulSoup(open("index.html"))
soup = BeautifulSoup("<html>data</html>")
Beautiful Soup会选择最合适的解析器来解析这段文档,如果手动指定解析器那么Beautiful Soup会选择指定的解析器来解析文档.
四大对象种类
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:
Tag
tag通俗点讲就是 HTML 中的一个个标签。可以利用 soup加标签名轻松地获取这些标签的内容,它查找的是在所有内容中的第一个符合要求的标签。
print soup.a
#<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>
print type(soup.a)
#<class 'bs4.element.Tag'>
对于 Tag,它有两个重要的属性,是 name 和 attrs,分别为标签名字和属性:
print soup.p.attrs
#{'class': ['title'], 'name': 'dromouse'}
print soup.p['class']
#['title']
NavigableString
NavigableString是标签内部的文字。
获取<p>The Dormouse’s story</p>内的内容
print soup.p.string
#The Dormouse's story
BeautifulSoup
BeautifulSoup 对象表示的是一个文档的全部内容.大部分时候,可以把它当作 Tag 对象,
Comment
Comment 对象是一个特殊类型的 NavigableString 对象,代表注释,其实输出的内容仍然不包括注释符号,但是如果不好好处理它,可能会对我们的文本处理造成意想不到的麻烦。
print soup.a
print soup.a.string
print type(soup.a.string)
输出:
<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>
Elsie
<class 'bs4.element.Comment'>
搜索文档树
find_all( name , attrs , recursive , text , kwargs )
find_all() 方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件
name 参数可以查找所有名字为 name 的tag,字符串对象会被自动忽略掉
如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容.下面例子中找出所有以b开头的标签,这表示和标签都应该被找到**
import re
for tag in soup.find_all(re.compile("^b")):
print(tag.name)
# body
# b
如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数 ,如果这个方法返回 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>]
其他还有很多用法。
css选择器
在 CSS 中,选择器是选取需设置样式的元素的模式。
Beautiful Soup支持大部分的CSS选择器。使用 Tag 或 BeautifulSoup 对象的 .select() 方法, 即可使用CSS选择器的语法找到想要的元素。
select_one是select的变体,它返回查找到的元素的第一个。
部分语法:
选择器 | 例子 | 例子描述 |
---|---|---|
.class | .intro | 选择 class=“intro” 的所有元素。 |
#id | #firstname | 选择 id=“firstname” 的元素。 |
element | p | 选择所有 <p> 元素。 |
element>element | div > p | 选择父元素是 <div> 的所有 <p> 元素。 |
具体见CSS选择器参考手册
输出
如果只想得到结果字符串,不重视格式,那么可以对一个 BeautifulSoup 对象或 Tag 对象使用Python的 unicode() 或 str() 方法:
str(soup)
# '<html><head></head><body>\xe2\x80\x9cDammit!\xe2\x80\x9d he said.</body></html>'
csdn网页内容
- 主体
在csdn博客中,真正的文章区域的div id为mainBox
下的class为div.blog-content-box
的div里面,获取的语句如下: ``` content = soup.select_one(“#mainBox > main > div.blog-content-box”)
1. 标题
<h1 class=”title-article” id=”articleContentId”>windows开发环境记录</h1>
class在主体内唯一
title=soup.select_one(“h1.title-article”)
1. 作者名字
<a class=”follow-nickName “ href=”https://blog.csdn.net/m0_37565736” target=”_blank” rel=”noopener”>香蕉割草机 </a>
class在主体内唯一
auth=soup.select_one(“a.follow-nickName”)
1. 创建时间
<span class=”time”>已于 2022-03-26 16:06:49 修改</span>
在html代码中,使用转义字符&nbsp表示1个空格。<br/> class在主体内唯一
createtime=soup.select_one(“span.time”)
1. 分类和标签
分类的报文:
<a class=”tag-link” href=”https://blog.csdn.net/m0_37565736/category_7276991.html” target=”_blank” rel=”noopener”>其他 </a>
标签的:
<a data-report-click=”{…} class=”tag-link” href=”https://so.csdn.net/so/search/s.do?q=环境&t=blog&o=vip&s=&l=&f=&viparticle=” target=”_blank” rel=”noopener”>环境 </a>
代码入下:
candt=soup.select(“a.tag-link”) for t in candt: if t.has_attr(‘data-report-click’): tag.append(t.string) else: classify.append(t.string)
```
具体处理
post命名
Jekyll 要求一篇文章的文件名遵循下面的格式:
年-月-日-标题.MARKUP
考虑获取到文章后,获取这三个字段,作为文件名存储转换好的markdown文件。
头信息
每篇post的头部都包含 YAML 头信息,除了jekll已有的,也可以自己扩展。目前我使用so-simple-theme作为网站的主题,需要的头信息有:
title
categories
tags
这三个是必须的,代表标题,分类和标签。
防重复
后续考虑用文章id来区分,避免重复