Python爬虫

这篇博客介绍了如何使用Python的requests库获取网页内容,并通过BeautifulSoup4库解析HTML。BeautifulSoup对象允许以树形结构处理HTML,通过Tag对象的name、attrs和string属性获取内容。还讲解了find()和find_all()方法来查找特定标签,以及正则表达式在字符串检索中的应用。最后,以中国大学排名爬虫为例展示了爬虫的构建步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

获取一个网页内容的函数建议采用:

import requests
def getHTMLText():
    try:
        r=requests.get(url,timeout=30)
        r.raise_for_status() #如果状态不是200,引发异常。200成功 404失败
        r.encoding='utf-8' #无论原来使用什么编码。都改成utf-8
        return r.text #返回url的内容
    except:
        return ""

测试代码

url="http://www.baidu.com"
print(getHTMLText(url))

关于requests更多介绍:

http://docs.python-requests.org

使用requests库获取HTML页面并且将其转换为字符串后,需要进一步解析HTML页面格式,需要处理HTML和XML的函数库

beautifulsoup4库,也称Beautiful Soup库或bs4库,用于解析和处理HTML和XML,注意:它不是Beautifulsoup库。它最大的优点是能根据HTML和XML语法建立解析树,进而高效地解析其中的内容

它把每一个页面当做一个对象

使用它之前需要进行引用,可以采用from-import的方式从库中直接引用BeautifulSoup类,如下:

>>>from bs4 import BeautifulSoup

更多:http://www.crummy.com/software/BeautifulSoup/bs4

创建的BeautifulSoup对象是一个树形结构,它包含HTML页面中的每一个Tag(标签)元素,如<head>.<body>等。

具体来说,HTML中的主要结构都变成了BeautifulSoup对象的一个属性,可以直接用<a>.<b>形式获得,其中<b>的名字采用HTML中标签的名字。


>>> from bs4 import BeautifulSoup
>>> soup=BeautifulSoup(r.text)
>>> type(soup)
<class 'bs4.BeautifulSoup'>
>>> soup.head #略去<style>
<head><meta content="text/html;charset=utf-8" http-equiv="content-type"/><meta content="IE=Edge" http-equiv="X-UA-Compatible"/><meta content="always" name="referrer"/><link href="http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/><title>百度一下,你就知道</title></head>
>>> soup.head #略去<sttyle>标签输出
<head><meta content="text/html;charset=utf-8" http-equiv="content-type"/><meta content="IE=Edge" http-equiv="X-UA-Compatible"/><meta content="always" name="referrer"/><link href="http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/><title>百度一下,你就知道</title></head>
>>> title=soup.title #HTML页面标题,在<head>之中,由<title>标记
>>> title
<title>百度一下,你就知道</title>
>>> type(title)
<class 'bs4.element.Tag'>
>>> soup.body  #<body>内容    每个对应的HTML Tag的属性是一个Tag类型
<body link="#0000cc"> <div id="wrapper"> <div id="head"> <div class="head_wrapper"> <div class="s_form"> <div class="s_form_wrapper"> <div id="lg"> <img height="129" hidefocus="true" src="//www.baidu.com/img/bd_logo1.png" width="270"/> </div> <form action="//www.baidu.com/s" class="fm" id="form" name="f"> <input name="bdorz_come" type="hidden" value="1"/> <input name="ie" type="hidden" value="utf-8"/> <input name="f" type="hidden" value="8"/> <input name="rsv_bp" type="hidden" value="1"/> <input name="rsv_idx" type="hidden" value="1"/> <input name="tn" type="hidden" value="baidu"/><span class="bg s_ipt_wr"><input autocomplete="off" autofocus="" class="s_ipt" id="kw" maxlength="255" name="wd" value=""/></span><span class="bg s_btn_wr"><input class="bg s_btn" id="su" type="submit" value="百度一下"/></span> </form> </div> </div> <div id="u1"> <a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻</a> <a class="mnav" href="http://www.hao123.com" name="tj_trhao123">hao123</a> <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图</a> <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频</a> <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧</a> <noscript> <a class="lb" href="http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1" name="tj_login">登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');</script> <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品</a> </div> </div> </div> <div id="ftCon"> <div id="ftConw"> <p id="lh"> <a href="http://home.baidu.com">关于百度</a> <a href="http://ir.baidu.com">About Baidu</a> </p> <p id="cp">©2017 Baidu <a href="http://www.baidu.com/duty/">使用百度前必读</a>  <a class="cp-feedback" href="http://jianyi.baidu.com/">意见反馈</a> 京ICP证030173号  <img src="//www.baidu.com/img/gs.gif"/> </p> </div> </div> </div> </body>
>>> soup.p #页面中第一个<p>内容
<p id="lh"> <a href="http://home.baidu.com">关于百度</a> <a href="http://ir.baidu.com">About Baidu</a> </p>
>>> 

BeautifulSoup属性与HTML的标签名称相同,远不止上述,更多请结合HTML语法理解。

每一个Tag标签在beautifulsoup4库中也是一个对象,称为Tag对象。

每个标签对象在HTML中都有类似的结构:

<a class="mnav" href="http://www.nuomi.com">糯米</a>

其中:

<>中标签的名字是name,字符串,标签的名字,比如div

其他项是attrs,字典,包含了原来页面Tag所有的属性,比如href

<>之间的内容是string,字符串,Tag所包围的文本,网页中真实的文字

contents,列表,这个Tag下所有子Tag的内容

因此,可以通过Tag对象的name、attrs、和string属性获得相应内容

>>> soup.p #页面中第一个<p>内容
<p id="lh"> <a href="http://home.baidu.com">关于百度</a> <a href="http://ir.baidu.com">About Baidu</a> </p>
>>> soup.a
<a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻</a>
>>> soup.a.name
'a'
>>> soup.a.attrs
{'href': 'http://news.baidu.com', 'name': 'tj_trnews', 'class': ['mnav']}
>>> soup.a.string
'新闻'
>>> title.name
'title'
>>> title.string
'百度一下,你就知道'
>>> soup.p.contents
[' ', <a href="http://home.baidu.com">关于百度</a>, ' ', <a href="http://ir.baidu.com">About Baidu</a>, ' ']

 

HTML语法可以在标签中嵌套其他标签,所以,string属性的返回值遵循如下原则。

(1)如果标签内部没有其他标签,string属性返回其中的内容

(2)如果标签内部还有其他标签,但只有一个标签,string属性返回最里面标签的内容

(3)如果标签内部有超过1层嵌套的标签,string属性返回None(空字符串)

 

HTML语法中同一个标签会有很多内容,例如<a>标签,百度首页一共有13处,直接调用soup.a只能返回第一个。

当需要列出标签对应的所有内容或者需要找到非第一个标签,使用BeautifulSoup的find()和find_all()方法。这两个方法会遍历整个HTML文档:

BeautifulSoup.find_all(name,attrs,recursive,string,limit)

作用:根据参数找到对应标签,返回列表类型(标签列表)

参数:

name:按照Tag标签名字检索,名字用字符串形式表示,例如div、li

attrs:按照Tag标签属性值检索,列出需要的属性名称和值,采用JSON表示

recursive:设置查找层次,只查找当前标签下一层时使用recursive=False

string:按照关键字检索string属性内容,采用string=开始

limit:返回结果的个数,默认返回全部结果

 

>>> a=soup.find_all('a')  #查找所有的<a>
>>> len(a)
11
>>> soup.find_all('script')
[<script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');</script>]
>>> soup.find_all('script',{'src':'http://www/zqxiangxin.com/\jquery/jquery-1.9.4.min.js'}) #筛选,只查找src=字符和串的标签
[]
>>> import re #使用正则表达式库,可以用这个库实现字符串片段匹配
>>> soup.find_all('script',{'src':re.compile('jquery')})
[]
>>> soup.find_all(string=re.compile('百度'))
['百度一下,你就知道', '关于百度', '使用百度前必读']
>>> a
[<a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻</a>, <a class="mnav" href="http://www.hao123.com" name="tj_trhao123">hao123</a>, <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图</a>, <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频</a>, <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧</a>, <a class="lb" href="http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1" name="tj_login">登录</a>, <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品</a>, <a href="http://home.baidu.com">关于百度</a>, <a href="http://ir.baidu.com">About Baidu</a>, <a href="http://www.baidu.com/duty/">使用百度前必读</a>, <a class="cp-feedback" href="http://jianyi.baidu.com/">意见反馈</a>]

通过片段字符串检索可以根据需要使用正则表达式re函数库,re是Python标准库。

采用re.compile('jquery')实现对片段字符串(如'jquery')的检索。 

当对标签属性检索时,属性和对应的值采用JSON格式,例如:

'src':re.compile('jquery')

其中,键值对中值的部分可以是字符串或者正则表达式。

find()方法与find_all()方法的区别是,前者只返回找到的第一个结果,后者返回更多结果,所以前者返回字符串形式,后者返回列表形式。

正则表达式:

正则表达式是字符串的一种逻辑表达,一般在计算机编译器中使用。Python语言采用正则表达式辅助字符串查找。正则表达式是一种规则,只要字符串符合这个规则,就算作匹配。例如,通过re.compile()函数注册一个正则表达式'jquery',则所有包含该表达式的字符串都与它匹配。除了字符串,正则表达式还可以通过*+{}等符号扩展功能。

 

实例:中国大学排名爬虫

上海交通大学研发的“软科中国最好大学排名2016”:

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

爬虫的构建需要三个步骤:

第一、从网络上获取网页内容(requests库)

第二、分析网页内容并且提取有用数据到恰当的数据结构中(beautifulsoup4库)

第三、利用数据结构展示或进一步处理数据

为了解析网页数据,首先需要观察爬虫页面的特点,找到拟获取数据在HTML页面中的格式。打开网址,查看网页源代码。

HTML表示表格中一行地标签是<tr></tr>,在这行中,每列用<td></td>表示

 

整体代码如下:

import requests
from bs4 import BeautifulSoup

allUniv=[]
def getHTMLText(url):
    try:
        r=requests.get(url,timeout=30)
        r.raise_for_status()
        r.encoding='utf-8'
        return r.text
    except:
        return ""

def fillUnivList(soup):
    data=soup.find_all('tr')
    for tr in data:
        ltd=tr.find_all('td')
        if len(ltd)==0:
            continue
        singleUniv=[]
        for td in ltd:
            singleUniv.append(td.string)
        allUniv.append(singleUniv)

def printUnivList(num):
    print("{:^4}{:^10}{:^5}{:^8}{:^10}".format("排名","学校名称","省市","总分","培养规模")
    for i in range(num):
          u=allUniv[i]
          print("{:^4}{:^10}{:^5}{:^8}{:^10}".format(u[0],u[1],u[2],u[3],u[6]))

def main(num):
          url='http://zuihaodaxue.cn/zuihaodaxuepaiming2016.html'
          html=getHTMLText(url)
          soup=BeautifulSoup(html,"html.parser")
          fillUnivList(soup)
          printUnivList(num)
main(10)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值