Python网络数据采集——复杂HTML解析

 

附注:关于基础知识:

  • 标签:HTML语言中最常见的基本单位,通常是成对出现的,比如 <div> 和 </div>等,网页的内容需在<html>标签中,标题、字符格式、语言、兼容性、关键字、描述等信息显示在<head>标签中,而网页需展示的内容需嵌套在<body>标签中。还有<title>等,他们分类了网页的内容。非常之多。

1.1最牛逼的库之一:BeautifulSoup4

  我们此处使用一个网页作为例子:http://www.pythonscraping.com/pages/warandpeace.html。这是战争与和平的纯文本小说,其中所有的人名都使用绿色标记,对话内容使用红色标记。我们截取一种一段HTML代码,其中——

  <span class="green">(此处为人名)</span>
  网络爬虫可以通过 class 属性的值,轻松地区分出两种不同的标签。例如,它们可以用BeautifulSoup 抓取网页上所有的红色文字,而绿色文字一个都不抓。以下给出代码。

from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen("http://www.pythonscraping.com/pages/warandpeace.html")
bsObj = BeautifulSoup(html)
##建立了一个bs4对象

nameList = bsObj.findAll("span", {"class":"green"})
## namelist代表一个list 其中bs0bj的语法是findall(tagName, tagAttributes)前者是表情名,后者是类名
## 非常灵活,以后会继续使用findall
for name in nameList:
  print(name.get_text())

##get_text会返回其中的文本值 如果直接读取name的话你会发现里面塞满了各种标签

1.2.1 BeautifulSoup的find()和findAll()

   findAll(tag, attributes, recursive, text, limit, keywords)是其最基本的用法,但是后面几个基本没卵用。

  • tag:代表标签,可以传一个标签的名称做函数,当然也可以使用多个比如{"h1","h2","h3","h4","h5","h6"}这样的。
  • attributes:实际上是一个字典,比如{"class":"{"greed","red"}}
  • 递归参数 recursive 是一个布尔变量,代表你想抓多少层的信息,因为有一些标签套标签,但如果是True就查到底、如果是False就查一层,默认是True。
  • 文本参数 text 有点不同,它是用标签的文本内容去匹配,而不是用标签的属性。这一点通常用来查找。
  • 范围限制参数 limit,显然只用于 findAll 方法。 find 其实等价于 findAll 的 limit 等于1 时的情形。就是查多少,但是注意你以为你以为的真的不一定是你以为的。

1.2.2 beautifulsoup的对象们

  • BeautifulSoup 对象,比如前面代码示例中的 bsObj
  • 标签 Tag 对象。BeautifulSoup 对象通过 find 和 findAll,或者直接调用子标签获取的一列对象或单个对象。
  • NavigableString 对象用来表示标签里的文字, 不是标签(有些函数可以操作和生成 NavigableString 对象,而不是标签对象)

 

1.2.3 导航树

  findAll 函数通过标签的名称和属性来查找标签 。但是如果你需要通过标签在文档中的位置来查找标签, 这就是导航树(Navigating Trees)的作用。现在我们用虚拟的在线购物网站 http://www.pythonscraping.com/pages/page3.html 作为要抓取的示例网页。我随便看了看,发现复杂的一逼,其中有一百万(?)个标签,互相嵌套。每一个部分都是一个高级标签的孩子。一般情况下, BeautifulSoup 函数总是处理当前标签的后代标签。例如, bsObj.body.h1 选择了 body 标签后代里的第一个 h1 标签,不会去找 body 外面的标签。

  在本次实例中,我们只需要爬取一部分子标签,这就是搜集类比表格的数据。这里不太懂。

from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = BeautifulSoup(html)
for child in bsObj.find("table",{"id":"giftList"}).children:
print(child)

1.3 正则表达式

  任意可以用一系列线性规则构成的字符串。正则表达式就是表达这组规则的缩写。这组规则的正则表达式如下所示

  例如:[A-Za-z0-9\._+]+@[A-Za-z]+\.(com|org|edu|net)

  A-Za-z0-9符号任选一个。+代表着匹配前面的字符 第一个是指必须有个字符 第二个是指字符可以乱七八糟混在一起但是必须有一个中括号里的东西。之后是转义字符代表一个.,再之后是com什么的。

1.4 正则表达式与bs4

在抓取网页的时候, BeautifulSoup 和正则表达式总是配合使用的。其实,大多数支持字符串参数的函数(比如, find(id="aTagIdHere"))都可以用正则表达式实现。比如想要抓取所有的图片文件,可以使用。这段代码会打印出图片的相对路径,都是以 ../img/gifts/img 开头,以 .jpg 结尾。

from urllib.request import urlopen
from bs4 import BeautifulSoup
import re
html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = BeautifulSoup(html)
images = bsObj.findAll("img",{"src":re.compile("\.\.\/img\/gifts/img.*\.jpg")})
## 这里的正则表达式很有趣 src代表地址 之后re代表正则表达式的模块 通常写正则表达式都得这么写
## \.\.\/img\/gifts/img.*\.jpg"
for image in images:
  print(image["src"])

 

1.5 Lambda表达式

Lambda 表达式本质上就是一个函数, 可以作为其他函数的变量使用;也就是说,一个函数不是定义成 f(x, y),而是定义成 f(g(x), y),或 f(g(x), h(x)) 的形式。

BeautifulSoup 允许我们把特定函数类型当作 findAll 函数的参数。唯一的限制条件是这些函数必须把一个标签作为参数且返回结果是布尔类型。 BeautifulSoup 用这个函数来评估它遇到的每个标签对象,最后把评估结果为“真”的标签保留,把其他标签剔除

soup.findAll(lambda tag: len(tag.attrs) == 2)这样会产生两个属性的标签。

 

 

Guess you like

Origin blog.csdn.net/qq_37772958/article/details/87217305