《Web Scraping With Python》Chapter 2的学习笔记
You Don't Always Need a Hammer
When Michelangelo was asked how he could sculpt a work of art as masterful as his David, he is famously reported to have said: “It is easy. You just chip away the stone that doesn’t look like David.”
这里将Web Scraping比作雕刻,即“用锤子去掉那些不像‘David’的部分”,在解析难题(Gordian Knot)的时候(即此网站很难去爬),我们不总是需要“锤子”(即我们不要一开始就dive),我们需要做的更聪明点:
- 查看此网页有无
print this page,或者移动端版本的html(通常来说移动端的html格式和架构会更好些) - 查看JavaScript File有无自己想要的信息
- 也许URL就有你想要的信息
- 有无其它比较好爬的网页同样能得到你的信息
Another Serving of BeautifulSoup
几乎每个网站都会有层叠样式表(Cascading Style Sheet, CSS)。CSS 可以让 HTML 元素呈现出差异化,使那些具有完全相同修饰的元素呈现出不同的样式。
比如一些标签看起来是这样:
我们可以通过创建一个这样的网络爬虫来爬取网页中的所有人物名称(此网页中人物名字都是绿色的):
from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/warandpeace.html")
bsObj = BeautifulSoup(html)
nameList = bsObj.findAll("span", {"class":"green"})
for name in nameList:
print(name.get_text())
关于get_text()函数
get_text() 会把你正在处理的 HTML 文档中所有的标签都清除,然后返回一个只包含文字的字符串。 假如你正在处理一个包含许多超链接、段落和标签的大段源代码, 那么 .get_text() 会把这些超链接、段落和标签都清除掉,
只剩下一串不带标签的文字。
例如,上面的代码的结果是(只保留了前五行):
Anna
Pavlovna Scherer
Empress Marya
Fedorovna
Prince Vasili Kuragin
如果print(name.get_text())换成 print(name),运行结果就会变成:
<span class="green">Anna
Pavlovna Scherer</span>
<span class="green">Empress Marya
Fedorovna</span>
<span class="green">Prince Vasili Kuragin</span>
关于BeautifulSoup中的findAll函数和find函数
BeatifulSoup文档中两者的定义是:
findAll(tag, attributes, recursive, text, limit, keywords)
find(tag, attributes, recursive, text, keywords)
find 其实等价于findAll的limit等于1时的情形。如果你只对网页中获取的前 x 项结果感兴趣,就可以设置它。
find和findAll函数中关键词参数的注意事项
虽然bsObj.findAll(id="text")和bsObj.findAll("", {"id":"text"})是完全一样的,但是偶尔会出现问题,比如我们用class属性查找标签,如果这样写代码:bsObj.findAll(class="green"),就会
因为class是python中的保留字而产生一个语法错误。一个比较臃肿的解决方案是在class后增加一个下划线:bsObj.findAll(class_="green"),或者:bsObj.findAll("", {"class":"green"})
Other BeautifulSoup Objects
NavigableString Object
用来表示标签里的文字,不是标签。
Comment Object
Used to find HTML comments in comment tags,
再加上我们之前学习的Tag Object和BeautifulSoup对象,这四个对象就是我们用BeautifulSoup库时能遇到的所有对象了,
Navigating Trees
一个html页面可以被映射成一棵树,以http://www.pythonscraping.com/pages/page3.html 为例,Navigating Tree是:
html
— body
— div.wrapper
— h1
— div.content
— table#giftList
— tr
— th
— th
— th
— th
— tr.gift#gift1
— td
— td
— span.excitingNote
— td
— td
— img
— ……其他表格行省略了……
— div.footer
children和descendants
我们在处理标签时,可以选择处理它的children或是descendants,但这里有一个极其容易混淆的地方,以以下代码为例:
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"}):
print(child)
上面的代码打印了bsObj的后代中所有符合条件的标签。在上面代码的第5行加上.children()和不加上是一样的,即for child in bsObj.find("table",{"id":"giftList"}):和
for child in bsObj.find("table",{"id":"giftList"}).children:等价。
而处理descenents,是处理完后代之后继续遍历一遍它的后代标签并得到标签的text,例如上面(children)代码得到的结果(一部分)是:
<tr><th>
Item Title
</th><th>
Description
</th><th>
Cost
</th><th>
Image
</th></tr>
如果将代码的for child in bsObj.find("table",{"id":"giftList"}):换成for child in bsObj.find("table",{"id":"giftList"}).descendants:,结果(一部分)会变成:
<tr><th>
Item Title
</th><th>
Description
</th><th>
Cost
</th><th>
Image
</th></tr>
<th>
Item Title
</th>
Item Title
<th>
Description
</th>
Description
<th>
Cost
</th>
Cost
<th>
Image
</th>
Image
通过上面结果我们可以得知,descendant在访问后代标签之后,又循环遍历了一遍后代标签,并且输出了text信息。
siblings
from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = BeautifulSoup(html)
for sibling in bsObj.find("table",{"id":"giftList"}).tr.next_siblings:
print(sibling)
这行代码会打印产品列表的所有行的产品,但是不会打印标题,原因是自己不能被视为自己的兄弟。
Make Selections Specifc
切记不要直接使用标签来得到你想要的信息,比如:bsObj.table.tr虽然和bsObj.find("table",{"id":"giftList"}).tr得到的结果一样,但是后者更稳定。
parents
from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = BeautifulSoup(html)
print(bsObj.find("img",{"src":"../img/gifts/img1.jpg"
}).parent.previous_sibling.get_text())
原标签结构为:
—
—
— (3)
— “$15.00” (4)
— s (2)
— <img src=”../img/gifts/img1.jpg">(1)
结果为:$15.00
Regular Expressions
正则表达式,简称为regex,大二《编译原理》课有很详细的学过这方面的知识,就不再赘述了。
Regular Expressions and BeautifulSoup
同时运用两方面的知识来构建一个爬虫,regex可以让我们得到的信息更具体,在一些需要对信息进行限制的情况下我们需要用到regex。
Accessing Attributes
用myTag.attrs这样的格式可以获取标签的所有属性。
Lambda Expressions
Lambda表达式,或许可以用来替代regex,不展开说。
Beyond BeautifulSoup
介绍了除BeautifulSoup之外可以用到的库,但目前我打算专注BeautifulSoup,就不去了解了。
lxml
HTML Parser
《Web Scraping With Python》Chapter 2的学习笔记的更多相关文章
- <Web Scraping with Python>:Chapter 1 & 2
<Web Scraping with Python> Chapter 1 & 2: Your First Web Scraper & Advanced HTML Parsi ...
- Web Scraping with Python读书笔记及思考
Web Scraping with Python读书笔记 标签(空格分隔): web scraping ,python 做数据抓取一定一定要明确:抓取\解析数据不是目的,目的是对数据的利用 一般的数据 ...
- Web scraping with Python (part II) « Jean, aka Sig(gg)
Web scraping with Python (part II) « Jean, aka Sig(gg) Web scraping with Python (part II)
- 阅读OReilly.Web.Scraping.with.Python.2015.6笔记---Crawl
阅读OReilly.Web.Scraping.with.Python.2015.6笔记---Crawl 1.函数调用它自身,这样就形成了一个循环,一环套一环: from urllib.request ...
- 阅读OReilly.Web.Scraping.with.Python.2015.6笔记---找出网页中所有的href
阅读OReilly.Web.Scraping.with.Python.2015.6笔记---找出网页中所有的href 1.查找以<a>开头的所有文本,然后判断href是否在<a> ...
- 阅读OReilly.Web.Scraping.with.Python.2015.6笔记---BeautifulSoup---findAll
阅读OReilly.Web.Scraping.with.Python.2015.6笔记---BeautifulSoup---findAll 1..BeautifulSoup库的使用 Beautiful ...
- 首部讲Python爬虫电子书 Web Scraping with Python
首部python爬虫的电子书2015.6pdf<web scraping with python> http://pan.baidu.com/s/1jGL625g 可直接下载 waterm ...
- $《利用Python进行数据分析》学习笔记系列——IPython
本文主要介绍IPython这样一个交互工具的基本用法. 1. 简介 IPython是<利用Python进行数据分析>一书中主要用到的Python开发环境,简单来说是对原生python交互环 ...
- Web Scraping with Python
Python爬虫视频教程零基础小白到scrapy爬虫高手-轻松入门 https://item.taobao.com/item.htm?spm=a1z38n.10677092.0.0.482434a6E ...
随机推荐
- ajax跳转到新的jsp页面
ajax可以实现局部刷新页面,即在不刷新整个页面的情况下更新页面的局部信息. 项目中遇到一个问题:在用户列表也,当点击某个按钮时需要去查询用户的信息,查询成功跳转到用户详情界面:查询失败,则在原页面弹 ...
- TP5使用phpmailer实现邮件发送
1.从github下载PHPMailer,在vendor目录中新建文件夹phpmailer,将压缩包中的class.phpmailer.php和class.smtp.php复制到phpmailer中, ...
- base64是啥原理
Base64是一种基于64个可打印字符来表示二进制数据的表示方法.由于2的6次方等于64,所以每6个比特为一个单元,对应某个可打印字符.三个字节有24个比特,对应于4个Base64单元,即3个字节可表 ...
- CSS3之border-radius圆角
CSS3之border-radius圆角 DIV盒子圆角 图片圆角,CSS3样式实现盒子对象圆角.图片圆角效果.div css3 border-radius圆角样式教程篇. 一.css3单词与语法结构 ...
- removeClass()
定义和用法 removeClass() 方法从被选元素移除一个或多个类. 注释:如果没有规定参数,则该方法将从被选元素中删除所有类. 语法 $(selector).removeClass(class) ...
- phpwind9.0升级到php7后出现的问题修复
最近将一个两年多以前的用phpwind9.0搭建的论坛升级到php7,遇到了页面无法打开,显示为500错误,排查了一整天时间,终于解决! 1.打开文件:src/applications/appcent ...
- ios 继承关系图
- Java多线程异常处理
在java多线程程序中,所有线程都不允许抛出未捕获的checked exception,也就是说各个线程需要自己把自己的checked exception处理掉.这一点是通过java.lang.Run ...
- MyBatis的关于批量数据操作的测试
摘录自:http://www.linuxidc.com/Linux/2012-05/60863.htm MyBatis的前身就是著名的Ibatis,不知何故脱离了Apache改名为MyBatis.My ...
- Redis进阶实践之七Redis和Lua初步整合使用
一.引言 Redis学了一段时间了,基本的东西都没问题了.从今天开始讲写一些redis和lua脚本的相关的东西,lua这个脚本是一个好东西,可以运行在任何平台上,也可以嵌入到大多数语言当 ...