夏令营小结:网络爬虫--沙窝李之王

爬虫:获取网页并提取和保存信息的自动化程序。
经过:获取网页->提取信息->保存数据。
能抓取怎样的数据:网页源码、json数据、二进制数据等浏览器能够访问到的数据

Robots协议:也称作爬虫协议、机器人协议,它的全名叫作网络爬虫排除标准(Robots Exclusion Protocol),用来告诉爬虫和搜索引擎哪些页面可以抓取,哪些不可以抓取。它通常是一个叫作robots.txt的文本文件,一般放在网站的根目录下。
1.正则匹配:
正则表达式:是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配,
定义了一种规则,匹配出所有符合这个规则的字符。
常见的正则匹配字符:
^:匹配一行字符串的开头
. : 匹配任意字符,除了换行符
[…]:匹配括号中的任一个,[amk] 匹配 ‘a’,‘m’或’k’
[^…]: 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符
:匹配0个或多个的表达式
+:匹配1个或多个的表达式
?:匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
|:a| b,匹配a或b
{n}:精确匹配 n 个前面表达式。例如, o{2} 不能匹配 “Bob” 中的 “o”,但是能匹配 “food” 中的两个 o。
{n,}:匹配 n 个前面表达式。例如, o{2,} 不能匹配"Bob"中的"o",但能匹配 "foooood"中的所有 o。“o{1,}” 等价于 “o+”。“o{0,}” 则等价于 "o
"。
{ n, m}:匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
\w:匹配字母数字下划线
\W:匹配非字母数字下划线
\s:匹配任意空白字符
\S:匹配任意非空白字符
\d: 匹配任意数字,等价于 [0-9]
\D:匹配任意非数字
re 模块使 Python 语言拥有全部的正则表达式功能
常用方法:
re.match :尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match() 就返回none。第一个参数传入了正则表达式,第二个参数传入了要匹配的字符串。
re.search:扫描整个字符串并返回第一个成功的匹配。
span():获取开始和结束位置;string:获取匹配的内容
group():获取子表达式匹配的内容
re.findall:在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。
re.sub(‘表达式’, ‘新字符’, ‘字符串’):用于替换字符串中的匹配项。
re.split:方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:
re.compile:函数用于编译正则表达式,生成一个正则表达式对象。
例:
夏令营小结:网络爬虫--沙窝李之王_第1张图片
结果:
在这里插入图片描述夏令营小结:网络爬虫--沙窝李之王_第2张图片结果:
夏令营小结:网络爬虫--沙窝李之王_第3张图片BeautifulSoup:
1 创建 BeautifulSoup 对象:
首先导入库 bs4 lxml requests:

    #encoding:UTF-8
    from bs4 import BeautifulSoup
    import lxml
    import requests

创建 beautifulsoup 对象:

soup = BeautifulSoup(html,'lxml')  #创建 beautifulsoup 对象

还可以用本地 HTML 文件来创建对象:

soup1 = BeautifulSoup(open('index.html'))  #用本地 HTML 文件来创建对象

打印一下 soup 对象的内容,格式化输出:

print soup.prettify()  #打印 soup 对象的内容,格式化输出

输出结果,格式化打印出了它的内容,这个函数经常用到。
2. 四种对象

Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:

Tag
NavigableString
BeautifulSoup
Comment

(1)Tag

Tag就是 HTML 中的一个个标签,例如

The Dormouse's story

用 BeautifulSoup 可以很方便地获取 Tags:

print soup.title
print soup.head
print soup.a
print soup.p
print type(soup.a)

这种方式查找的是在所有内容中的第一个符合要求的标签。

对于 Tag,它有两个重要的属性,name 和 attrs :

print soup.name
print soup.a.name
print soup.attrs
print soup.p.attrs #在这里,我们把 p 标签的所有属性打印输出了出来,得到的类型是一个字典。
print soup.p['class'] #单独获取某个属性
print soup.p.get('class') ##单独获取某个属性 跟上面一样的

可以对这些属性和内容等等进行修改:

soup.p['class']="newClass"

可以对这个属性进行删除:

del soup.p['class']

(2)NavigableString

得到了标签的内容用 .string 即可获取标签内部的文字,例如:

print soup.p.string

来检查一下它的类型:

print type(soup.p.string)
#

可以看到它的类型是一个 NavigableString,翻译过来叫 可以遍历的字符串。

(3)BeautifulSoup

BeautifulSoup 对象表示的是一个文档的全部内容.大部分时候,可以把它当作 Tag 对象,是一个特殊的 Tag,我们可以分别获取它的类型,名称:

print type(soup.name)
#
print soup.name 
# [document]
print soup.attrs 
#{} 空字典

(4)Comment

Comment 对象是一个特殊类型的 NavigableString 对象,其实输出的内容仍然不包括注释符号。我们找一个带注释的标签:

print soup.a
print soup.a.string
print type(soup.a.string)

运行结果如下:


 Elsie 

a 标签里的内容实际上是注释,但是如果我们利用 .string 来输出它的内容,我们发现它已经把注释符号去掉了,所以这可能会给我们带来不必要的麻烦。

我们打印输出下它的类型,发现它是一个 Comment 类型,所以,我们在使用前最好做一下判断,判断代码如下:

if type(soup.a.string)==bs4.element.Comment:
    print soup.a.string

上面的代码中,我们判断了它的类型,是否为 Comment 类型。

  1. 遍历文档树

(1)直接子节点

tag 的 .content 属性可以将tag的子节点以列表的方式输出:

print soup.head.contents

运行结果:

[The Dormouse’s story]

输出方式为列表,我们可以用列表索引来获取它的某一个元素:

print soup.head.contents[0]
.children

它返回的不是一个 list,不过我们可以通过遍历获取所有子节点。我们打印输出 .children 看一下,可以发现它是一个 list 生成器对象:

print soup.head.children

运行结果:

遍历一下获得里面的内容:

for item in  soup.body.children:
    print item

(2)所有子孙节点

.contents 和 .children 属性仅包含tag的直接子节点,.descendants 属性可以对所有tag的子孙节点进行递归循环,和 children类似,要获取其中的内容,我们需要对其进行遍历
for item in soup.descendants:
print item

查看运行结果,可以发现,所有的节点都被打印出来了:

The Dormouse's story

The Dormouse's story

Once upon a time there were three little sisters; and their names were

(5)父节点

p = soup.p
print p.parent.name

运行结果:

body

content = soup.head.title.string
print content.parent.name

运行结果:

title

(6)全部父节点

通过元素的 .parents 属性可以递归得到元素的所有父辈节点:

content = soup.head.title.string
for parent in  content.parents:
    print parent.name

传 True

True 可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点:

for tag in soup.find_all(True):
    print(tag.name)
# html
# head
# title
# body
# p
# b
# p
# a
# a

   E.传方法

如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数 ,如果这个方法返回 True 表示当前元素匹配并且被找到,如果不是则反回 False。下面方法校验了当前元素,如果包含 class 属性却不包含 id 属性,那么将返回 True:

def has_class_but_no_id(tag):
    return tag.has_attr('class') and not tag.has_attr('id')

text 参数

通过 text 参数可以搜搜文档中的字符串内容.与 name 参数的可选值一样, text 参数接受 字符串 , 正则表达式 , 列表, True:

soup.find_all(text="Elsie")
# [u'Elsie']
 
soup.find_all(text=["Tillie", "Elsie", "Lacie"])
# [u'Elsie', u'Lacie', u'Tillie']
 
soup.find_all(text=re.compile("Dormouse"))
[u"The Dormouse's story", u"The Dormouse's story"]

limit 参数

find_all() 方法返回全部的搜索结构,如果文档树很大那么搜索会很慢.如果我们不需要全部结果,可以使用 limit 参数限制返回结果的数量.效果与SQL中的limit关键字类似,当搜索到的结果数量达到 limit 的限制时,就停止搜索返回结果.

文档树中有3个tag符合搜索条件,但结果只返回了2个,因为我们限制了返回数量:

soup.find_all("a", limit=2)
# [Elsie,
#  Lacie]

recursive 参数

调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False:

soup.html.find_all("title")
# [The Dormouse's story]
 
soup.html.find_all("title", recursive=False)

你可能感兴趣的:(夏令营小结:网络爬虫--沙窝李之王)