爬虫笔记-01-爬虫介绍和BeautifulSoup

介绍

一直想有时间学习爬虫技术,现在来吧,跟着OReilly 出版的Web Scraping with Python 这本书来学习。

环境准备

因为本书推荐Python3为例,去官网下载Python3.x版本的Python安装包,直接安装就好了。安装的时候注意勾选加入path

话说我还没有学Python呢亲( ⊙ o ⊙ )!,没关系先稀里糊涂的用吧~~~ 不行了再说

第一只爬虫

书中首先做了一些介绍,主要内容是网络传输的过程,说白了就是web交互其实可以跟浏览器没有啥关系,而爬虫就是不通过浏览器从服务端去爬数据...

初见

ok闲言碎语不要讲来写爬虫吧
新建一个文件夹,里面建一个test.py文件,在里面写入:

from urllib.request import urlopen
html = urlopen("http://pythonscraping.com/pages/page1.html")
print(html.read())

据说Python是一个很矫情的对空格、缩进敏感的语言..所以一定要注意不要乱打空格和缩进
保存,然后命令行cd到这个文件的目录:

phython test.py

可以看到打印出来的html

美丽的汤

BeautifulSoup是一个lib,用来更好的解析html和xml的。

安装汤

python3自带了pip所以可以直接用pip安装

pip install beautifulsoup4

Virtual Environments是一个隔离各个项目lib防止冲突的机制,由于我初学,先不用

安装完bs4之后试一下:

from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/page1.html")
bsObj = BeautifulSoup(html.read())
print(bsObj.h1)

直接使用bsObj.h1找到了html中的h1标签里的内容。这是比较暴力的写法,比较精确的写法是bsObj.html.body.h1

异常处理

异常处理可以使程序更健壮,不容易直接挂掉。看下面的写法:

from urllib.request import urlopen
from urllib.error import HTTPError
from bs4 import BeautifulSoup

def getTitle(url):
    try:
        html = urlopen(url)
    except HTTPError as e:
        return None
    try:
        bsObj = BeautifulSoup(html.read())
        title = bsObj.body.h1
    except AttributeError as e:
        return None
    return title
title = getTitle("http://www.pythonscraping.com/pages/page1.html")
if title == None:
    print("Title could not be found")
else:
    print(title)

以上方法才是比较正规健壮的写法,一定要注意格式,不然会报错的,不行就装个IDE 比如Pycharm,如果格式不正确会有提示。

高级HTML解析

从一个复杂的页面提取到需要的信息可能需要深层的抓取比如:
bsObj.findAll("table")[4].findAll("tr")[2].find("td").findAll("div")[1].find("a")
这样的代码很可怕也很脆弱,当页面出现改动后,这个路径就抓不到信息了。
有什么解决方案?

  • 通过手机版或打印预览,来获取更规范的HTML
  • 解析网页引用的js文件
  • 通过网页URL获取信息
  • 从其他类似的网站获取信息

书上说的以上方法很湿,一点都不干货...

BeautifulSoup 的其功能

使用属性、导航树、搜索标签
网页的样式表 也可以用来查找信息

看例子,这个网页,有red和green的文字:
http://www.pythonscraping.com/pages/warandpeace.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())

以上,使用bsObj.findAll(tagName, tagAttributes)查询返回列表

find()和findAll()的用法

findAll(tag, attributes, recursive, text, limit, keywords)
find(tag, attributes, recursive, text, keywords)

查找多个类型的标题:

.findAll({"h1","h2","h3","h4","h5","h6"})

查找多个属性:

.findAll("span", {"class":"green", "class":"red"})

递归

findAll()方法的递归属性默认是true,意味着查找所有子节点。

以内容为条件查询标签:

nameList = bsObj.findAll(text="the prince")
print(len(nameList))

limit

limit是限制查找的个数,比如只返回前10个符合条件的标签

keywords

有点复杂 先不看

Navigation Trees

Navigation Tree就类似这种用法:
bsObj.tag.subTag.anotherSubTag

一个用来做例子的页面:
http://www.pythonscraping.com/pages/page3.html

处理子节点和后代节点

在BeautifulSoup里面 子节点child和“”孙子及后代“descendants 是被两个概念。两个范围没有交集。
注意bsObj.body.h1这个代码返回的不一定是 body-h1,而有可能是body-........h1。
如果只想得到儿子则使用:bsObj.find("table",{"id":"giftList"}).children这种方式。

处理sibling兄弟姐妹

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)

打印出了所有的产品内容,出了第一行title。原因:

  • sibling(兄弟)不包括自己
  • next_siblings只返回next的,而不是它和它之前的,如果object本身在在队列中间,那么只返回它后面的兄弟

同理如果需要返回前面的兄弟可以使用previous_siblings

以上两周可以理解为,返回哥哥、返回弟弟
另外,去掉siblings后面的s 可以只返回一个靠的最近的兄弟。

处理爹妈,父标签(这标题...)

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())
逆时针箭头顺序

正则表达

正则表达式....呃 头大

As the old computer-science joke goes: “Let’s say you have a problem, and you decide
to solve it with regular expressions. Well, now you have two problems.”

爬虫技术脱不了使用正则表达式

上面的例子使用的是准确的src来找到特指的img,但是如果要找很多的img就要使用正则了:

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")})
for image in images:
    print(image["src"])

获取属性

myImgTag.attrs['src']

Lambda表达式

将一个方法作为变量传递到另一个方法中,但是方法的参数必须是一个tag返回一个boolean
例子:
soup.findAll(lambda tag: len(tag.attrs) == 2)
返回有两个属性的标签
这可能是替代正则表达式的一种方法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容