爬虫MOOC 第二周 入门

首先下载Beautiful Soup 4,然后解压安装,记得安装代码是


python setup.py install



这里要说明一点!!!很重要,我吃了一个多小时的亏。

我把文件命名为 bs4.py

这时候如果要from bs4 import ... 的话,就是直接读取文件本身,所以千万不要乱写脚本名字。如果把脚本名字改成 test.py 就可以了。

真的烦人。


然后就可以使用了。

进入演示页面 http://python123.io/ws/demo.html


测试 bs4 安装:

from bs4 import BeautifulSoup

到这里如果没问题就搞定了。


使用方法很简单,牢记这两行代码就行了。

from bs4 import BeautifulSoup
soup = BeautifulSoup('<p>data/p', 'html.parser') # 解析代码

=============================================================================

HTML 代码大概是

<html>
    <body>
        <p class="title"> ... </p>
    </body>
</html>

这个样的,所以 bs4 库就是解析、遍历、维护“标签树”的功能库。

其中

<p> ... </p>
是 标签 tag,是成对出现的。

  <p class="title"> ... </p>
p是标签的名称,p后面那个叫属性域,包含0个或者多个属性域。class就是一种属性,属性内容是 title。


============================================================

bs4 的 HTML 解析器是 html.parser ,此外还有 lxml 和 html5lib 的解析器。

这里主要用 HTML 解析器。




这里假设已经获得了网页信息了,以下是一些命令:

# -*- coding:utf-8 -*-
from bs4 import BeautifulSoup
soup = BeautifulSoup(demo, 'html.parser') # 解析代码
print 'title: '
print soup.title # 打印 title 标签
tag = soup.a # 获取 .a 标签,也就是链接标签
print'.a tag: '
print tag  

print soup.a.name #获取 a 标签的名字
print soup.a.parent.name # a 的父标签的名字
print soup.a.parent.parent.name # a 的父标签的父标签的名字
print tag.attrs # attrs 获得标签的属性(全部)
print tag.attrs['class'] # 单独获得某个属性
print tag.attrs['href']
print type(tag.attrs) # 标签属性的类型(这里是字典)
print type(tag) # 标签本身的类型(就是 tag 类型)

print soup.a.string # a 标签的 string
print soup.p # a 标签的 string 信息 'Basic Python'
print soup.p.string # p 标签的 string 信息
print type(soup.p.string) # p 标签的 string 的类型

# tag 的 comment(注释)类型
newsoup = BeautifulSoup("<b><!--This is a comment--></b><p>This is not a comment</p>", "html.parser")
print newsoup.b.string 
print type(newsoup.b.string)
print newsoup.p.string
print type(newsoup.p.string) # 注意 b 和 p 标签字符串的类型是不同的

=======================================================================

基于 bs4 库的 html 提取方法


首先回顾 demo 的写法:

# -*- coding:utf-8 -*-
# demo
import requests
from bs4 import BeautifulSoup
r = requests.get("http://python123.io/ws/demo.html")
demo = r.text
print demo





先说子节点的用法

# 子节点  
soup = BeautifulSoup(demo, 'html.parser') # 解析代码  
print soup.head # head 标签  
print soup.head.contents # head 的子节点是 title 标签,存在了一个列表中  
print soup.body.contents # 同理,这是 body 的子节点标签  
print len(soup.body.contents) # 表示 body 的子节点的数量,这里有五个  
print soup.body.contents[1] # 这里输出的是第一个子节点  
for child in soup.body.children: # 遍历儿子节点  
    print child  
for child in soup.body.descendants # 遍历子孙节点(课上说是 children ,感觉错了)  
    print child 
然后是父节点

# 父节点  
soup = BeautifulSoup(demo, 'html.parser') # 解析代码  
print soup.title.parent # title 标签的父节点  
print soup.html.parent # html 的父亲就是他自己  
print soup.parent # soup 是一个特殊标签,他的父亲是空的  
for parent in soup.a.parents: # 对 a 标签的所有先辈打印  
    if parent is None:  
        print parent # 这里要注意  
                     # 遍历的时候会遍历到 soup 本身,但是他是不存在 .name 信息的  
    else:  
        print parent.name
=============================================================================

然后平行遍历


# 平行遍历  
soup = BeautifulSoup(demo, 'html.parser') # 解析代码  
print soup.a.next_sibling # a 标签的下一个平行节点(不一定还是标签,也有可能是字符串)  
print soup.a.next_sibling.next_sibling # 再下一个平行节点  
print soup.a.prebious_sibling # a 标签之前的一个平行节点  
print soup.a.prebious_sibling.prebious_sibling # 再前一个,也许为空  
print soup.a.parent   
for sibling in soup.a.next_siblings: # 遍历后续节点  
    print sibling  
for sibling in soup.a.prebious_siblings: # 遍历前续节点  
    print sibling

然后是输出


# 输出  
  
 soup = BeautifulSoup(demo, 'html.parser') # 解析代码  
 print soup.prettify() # 带换行符,这个方法就是为文本标签内容添加换行符  
 print soup.a.prettify() # 单独打印 a 标签  


总结:



到此就是BS4基本用法,接下来讲进一步用法。


==========================================================================

HTML 信息标记有三大种类 :XML, JSON, YAML


先有HTML,后有XML,它通过标签形式来构建信息。


JSON:是有类型的键值对——key: value 的组合。比如 :

"name": "北京大学"   

"name": ["北京大学","理学院"]

除了数字,需要双引号。


YAML:采用无类型键值对——

name:北京大学  

注意没有双引号,需要的时候可以利用缩进表达从属,用 - 号表达并列。


XML:扩展性好,但是繁琐



JSON:适合 JavaScript,和XML比更简洁




YAML:文本信息比例最高,可读性好。


================================================================



===========================================================

信息提取方法:

一、完整解析信息的标记形式,然后提取关键信息,比如bs4库的标签树遍历。

二、无视标记形式,直接搜索关键信息。

三、融合方法:结合形式解析和搜索方法,提取关键信息。

from bs4 import BeautifulSoup
soup = BeautifulSoup(demo, "html.parser")
for link in soup.find_all('a'): # 查找 a 标签
    print(link.get('href')) # 得到了内容,href 是属性。

记得之前的demo,再写一遍:

# -*- coding:utf-8 -*-
# demo
import requests
r = requests.get("http:/python123.io/ws/demo.html")
demo = r.text
print demo

=====================================================

现在介绍 find_all :

# <>.find_all(name, attrs, recursive, string, **kwargs)
# name: 对标签名称的检索字符串
# attrs: 对标签属性值的检索字符串,可标注属性检索
# recursive: 对标签的子孙搜索,默认为 True
# string: <>...</> 中字符串区域的检索字符串

print soup.find_all('a'): # 查找 a 标签
print soup.find_all(['a','b']) # 找 a b 标签 
for tag in soup.find_all(True): # True 会显示所有标签信息
    print(tag.name)

import re 
for tag in soup.find_all(re.compile('b')) # 返回的所有以 b 开头的信息
    print tag.name

print soup.find_all('p','course') # 查找了带有 course 属性的 p 标签 
print soup.find_all(id = 'link1') # 属性中 id 域为 link1 的标签
print soup.find_all(id = 'link') # 属性中 id 域为 link 的标签
print soup.find_all(id = re.compile('link')) # 输出以 link 开头但是不全是 link 的信息  

print soup.find_all('a', recursive = False) # 返回这里是一个空列表,说明儿子节点上面没有 a 标签 

print soup.find_all(string = 'Basic Python') # 精确检索 Basic Python
print soup.find_all(string = re.compile("Python")) # 使用正则,把带有 python 的字符串域全部检索


以后会介绍正则库

find_all() 函数 和 正则结合很好用。

缩写:

<tag>(..) 等价于 <tag>.find_all(..)

soup(..) 等价于  soup.find_all(..)




=========================================================================

实战 http://www.zuihaodaxue.cn/zuihaodaxuepaiming2016.html

最好大学网的2016中国最好大学排名,这里我们要试着使用爬虫爬取。

功能:

输入:大学排URL

输出:大学排名信息的屏幕输出(排名,大学,总分)

路线:requests / BS4

这个称为:定向爬虫


先打开看看源代码。我们要看看这个页面的大学排名信息是动态的还是写在源代码中的,如果是源代码中就有的,那么可以爬取。

实际上打开发现是写好了的,那么我们可以用爬虫爬取信息了。

<tr class="alt"><td>1</td>
				<td><div align="left">清华大学</div></td>
				<td>北京市</td><td>95.9</td>

然后看一看网站的robots协议。




404说明随便爬取。





# -*- coding:utf-8 -*-
# 爬取中国最好大学数据
import requests
from bs4 import BeautifulSoup
import bs4

def getHTMLText(url): # 从网络上获取大学排名网页内容
    try:
        r = requests.get(url, timeout = 30) # 限定时间 30 秒
        r.raise_for_status() # 有问题就产生异常
        r.encoding = r.apparent_encoding # 编码
        return r.text
    except:
        return "" # 否则返回空字符串

def fillUnivList(ulist, html ): # 提取网页内容中信息到合适的数据结构
# 注意这里的 "tbody"/"td"/"tr" 都是根据网页源代码来的
    soup = BeautifulSoup(html, "html.parser")
    for tr in soup.find('tbody').children: # 遍历、查找在 tbody 中子标签中的 tr 标签,tr 包含大学信息
        if isinstance(tr, bs4.element.Tag): # 检测 tr 标签类型,如果不是 bs4 库定义的 tag 类型,则过滤掉
            tds = tr('td') # 把所有的 td 标签存为列表 tds
            ulist.append([tds[0].string, tds[1].string, tds[2].string]) # 把需要的 td 标签加入到 ulist

def printUnivList(ulist, num ): # 利用数据结构展示并输出结果
    tplt = "{0:^10}\t{1:{3}^10}\t{2:^10}"
    # 注意 ":" 是引导符号,"3"是填充的字符,"^" 是居中对齐符号,"10"是宽度,最前面"0"、"1"、"2"是顺序
    # chr 12288是中文空格变量
    print (tplt.format("排名", "学校名称", "总分",chr(12288))) # format 方法格式化输出
    for i in range(num):
        u = ulist[i] # 所有信息保存在 ulist 中
        print (tplt.format(u[0], u[1], u[2],chr(12288))) # 格式化输出

def main(): # 主函数
    uinfo = [] # 大学信息放在 uinfo 列表
    url = 'http://www.zuihaodaxue.cn/zuihaodaxuepaiming2016.html'
    html = getHTMLText(url)
    fillUnivList(uinfo, html)
    printUnivList(uinfo, 20) # 打印 20 所大学信息
    
main()

最后输出效果:



个中的表格对齐很重要,请看图片和注释。






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值