关于python:python爬虫requestsBeautifulSoup

40次阅读

共计 5672 个字符,预计需要花费 15 分钟才能阅读完成。

requests 模块介绍

绝对于 python 自带的 urllib 模块,requests 模块提供了绝对更高层的 api 来进行网页拜访的工作。

对于 requests 模块,应用很简略,个别咱们会用到两个函数:

  • requests.get(url,params=None,**kwargs) 这里的 params 是咱们要传入的 query,它的格局是 dict。
  • requests.post(url,data=None,**kwargs) 这里的 data 就是咱们要提交的表单 data,也是间接传入 dict 就好。

以上两个函数别离对应 http 协定中的 ”GET” 办法与 ”POST” 办法,而除了这两者,还有如 ”PUT”、”DELETE”、”HEAD” 等办法,在 requests 模块中有一个对立的函数来发动不同“办法”的 http 申请报文:

  • requests.request(method,url,**kwargs) 能够看到该函数的第一个参数 method 的取值就是 ”GET”、”POST” 等。
  • 该办法与上文提到的两个办法,返回值都是 requests.Response 对象,前面咱们会对该对象与 requests.Request 对象进行介绍
  • 较罕用的关键字参数:params,data,headers,proxies,stream 等。
  • 其实上文所介绍的两个函数 get 和 post,或是对应其余办法的函数,它们的实现就是应用 request.requests 函数的:
    def get(url, params=None, **kwargs):
         kwargs.setdefault('allow_redirects', True)
         #这里可见 request.get 的本质
         return request('get', url, params=params, **kwargs)

这里来具体介绍一下 headers,proxies 和 stream 关键字参数的用处:

  • headers 参数就是 http 申请报文的头部,它的格局是一个 dict,其中最为罕用的 headers 元素就是 User-Agent,模拟浏览器拜访网页。
  • proxies 参数就是代理,它的格局也是一个 dict,每一个键值对是这样的模式:” 协定 ”:”ip:port”。
  • stream 参数是绝对前两者较生疏的一个参数,该参数默认为 False,意味着咱们会一下子把网页内容都下载,但如果被动设置为 True 的话,则不会立即下载网页内容,而是等到应用 requests.Response 的 iter_content 才会迭代地把数据下载并读进内存中。

requests.Request&requests.Response

这两个对象具体对爬虫有过理解的敌人们都很相熟了,它们是在爬虫逻辑中很要害的两个对象,简略来说:收回 Request,返回 Response

requests.Request

咱们在应用 requests 时个别不会间接创立 Request 对象,所以这里咱们大抵理解一下即可:

requests.Request(method=None, url=None, headers=None, data=None, params=None) 咱们列出 Request 类结构时所需的一些罕用参数,并且前文咱们提到 requests.get 等函数的本质是 requests.request 函数,那么其实钻研该函数的源码:

def request(method, url, **kwargs):
    with sessions.Session() as session:
        #能够看到在 request 函数内调用了 session.request 办法
        return session.request(method=method, url=url, **kwargs)
        

#这个是 session.request 办法的定义
def request(self, method, url,
        params=None, data=None, headers=None, cookies=None, files=None,
        auth=None, timeout=None, allow_redirects=True, proxies=None,
        hooks=None, stream=None, verify=None, cert=None, json=None):
    
    #能够看到这里其实应用传入参数
    #创立了一个 requests.Request 实例
    req = Request(method=method.upper(),
        url=url,
        headers=headers,
        files=files,
        data=data or {},
        json=json,
        params=params or {},
        auth=auth,
        cookies=cookies,
        hooks=hooks,
    )
    #进一步解决,失去对应的 PreparedRequest 对象
    prep = self.prepare_request(req)

    proxies = proxies or {}

    settings = self.merge_environment_settings(prep.url, proxies, stream, verify, cert)

    # Send the request.
    send_kwargs = {
        'timeout': timeout,
        'allow_redirects': allow_redirects,
    }
    send_kwargs.update(settings)
    #这里是真正的 send Request,并返回一个 Response 对象
    resp = self.send(prep, **send_kwargs)
    return resp

由以上代码可知,其实 requests.request 办法的本质就是创立一个 Request 实例,在对其进行肯定预处理后将其 send,而后失去 Response。

requests.Response

咱们之前的 requests.get、requests.post 或是 requests.request 函数的返回对象就是一个 requests.Response 实例。对于 Response 类,咱们次要介绍几个罕用属性与办法:

  • Response.content 以 bytes 的模式失去返回 Response 的内容,其实也就是未解码的 html 文件
  • Response.text 文本模式的 Response 内容,也就是解码了的 html 文件,且如 Response.encoding 属性为 None 的话,那么会以 chardet 去猜想 bytes 内容的编码方式。当然咱们也能够在 access 这个属性前人为指定一种编码方式。
  • Response.encoding 指定以何种形式来解码,Response 内容的编码齐全基于 HTTP 报头,遵循 RFC2616 文件。
  • Response.url 即 Response 的 url
  • Response.status_code 相应的状态码,如胜利的话该值就是 200
  • Response.request 失去对应于这个 Response 的 Request 对象,其实是(PreparedRequest),通过这个 request 对象咱们能够失去过后拜访时的 url、method、headers 等属性。
  • Response.iter_content(chunk_size=1),该函数返回一个 generator,其中的 chunk_size 决定咱们每次下载并读进内存中多少个字节,个别应用办法为 for item in Response.iter_content(256)这样的 for 循环遍历即可。

BeautifulSoup

BeautifulSoup 是一个能够从 HTML 或 XML 文件中提取数据的 Python 库,通常咱们应用 requests 失去 html 文件(Response.text),而后咱们再应用 BeautifulSoup 来解决。从而提取到咱们须要的信息。

如何应用 BeautifulSoup

from bs4 import BeautifulSoup
#其中 html 是返回的网页文本,也就是 response.text
#而 lxml 是 BeautifulSoup 应用的文档解析器,须要咱们
#曾经事后 pip install 好 lxml 这个模块,或者咱们也可
#应用 python 自带的 html.parser,不过它的速度较慢些
#而 soup 就是一个 BeautifulSoup 对象,它承载了一个
#由 html 文档外部各个元素所造成的树形构造。soup=BeautifulSoup(html,"lxml")
#以下就是几个最简略根本的应用
#间接以属性援用的形式失去 html 文档中的第一个 a 标签
print(soup.a)
#进一步失去 html 文档中第一个 a 标签的中的字符串局部(如果存在的话)print(soup.a.string)
#拿到 html 文档中第一个 a 标签的 href 属性的值
print(soup.a["href"])

以上大抵介绍了 BeautifulSoup 的简略实用,接下来咱们进行更具体地剖析:
BeautifulSoup 将 HTML 文档转换成一个简单的树形构造,该树形构造中的每个节点都是 Python 对象,所有对象可分为 4 种: Tag、NavigableString、BeautifulSoup、Comment。

  • Tag 对象 对应的就是 html 文档中的标签,它有很多属性与办法,这里先介绍它最重要的两个属性:1.tag.name 返回的就是该 tag 标签的名字(比方 tag 对应 a 标签,那么 tag.name 返回的就是 ”a”)。2.tag.attrs 以字典的模式返回该标签所有的属性,如{“herf”:”www.baidu.com”}。而咱们想拿到属性值就能够用 tag.attrs[“href”],不过上文也看到了,这里其实能够间接简写为 tag[“href”]。
  • NavigableString 对象 它其实就是咱们应用 soup.a.string 时真正返回的对象,它是对 python 自带的 string 对象进行了一个包装,咱们能够就把它当作 string 应用,不须要在意其它。
  • BeautifulSoup 对象 它对应咱们文档的全部内容,也就是上文的 soup 对象,大部分工夫咱们能够把它当作 tag 对象一样来应用 办法,不过它没有 attrs 属性,并且它的 name 属性的值只为:[“document”]。
  • Comment 对象 它对应 html 文档中的正文标签:<!– 此处写正文 –>,该标签很特地的是它不会被浏览器显示,只是一个对程序员正文的作用。该对象在理论利用中很少应用,这里不作更进一步的介绍。

接下来咱们要来对 tag 对象以及 BeautifulSoup 对象在应用 method 上进行更进一步的介绍:

而所谓的 method 应用,咱们着眼的就是在失去的 BeautifulSoup 对象的树形构造中对所须要的信息进行搜寻的工作。

这样的搜寻工作依据对 节点自身信息 节点之间在树形构造中的关系 的利用不同而 分为两种

第一种,由节点自身信息对节点进行搜寻

所谓 tag.a 其实就是 tag.find("a"),该办法的具体函数头如下
find(name,attrs,recursive,string,**kwargs)
name 就是标签名,它的值是一个“过滤器”。attrs 就是该 name 对应标签的属性,同样值也是一个“过滤器”。recursive 是一个 bool 值,默认为 True。它的意思是搜寻以后 tag 的所有子孙节点,如果为 False,则只搜寻以后 tag 的间接子节点
string 就是该 name 对应的 string 值,也是一个“过滤器”。**kwargs 个别应用不必理睬。当然下面的 tag.a 或是 tag.find("a")都只能失去 tag 下的第一个 a 标签,这太局限了,如果咱们想要的是前面的第三个 a 标签呢?于是就有了
tag.find_all("a")办法,返回一个列表,来失去所有的 a 标签,简写为 tag("a")。find_all(name,attrs,recursive,string,**kwargs)
参数的意义和 find 函数一样

上面咱们来解说一下这个所谓的“过滤器”到底是什么货色
具体的代码实现有点繁琐,总之咱们能够把它了解为一种
对象,咱们容许这个对象有多种值。(1)字符串值 最简略的就是传入字符串值,如之前的 tag.a
(2)正则表达式值 即 re.compile(r"\d+")这样的模式
(3)列表值 如 name=["a","div"],则 find 只会返回其中的后者,find_all 会返回一个列表,蕴含 tag 下的所有 a 和 div 标签。(4)True 意思不做过滤,对于 find 是返回 tag 下符合要求的标签的第一个,对于 find_all 是返回所有。比方 name=True,那么就不对 name
过滤,对其余 attrs 或 string 持续筛选过滤。

第二种,依据节点所在树形构造中的关系对其它节点进行搜寻

间接子节点:tag.childern 和 tag.contents 是 tag 对象的两个属性,留神不是对应标签的属性!!!它们返回以后 tag 节点在树形构造中的间接子节点。tag.childern 返回一个生成器
tag.contents 返回一个列表

子孙节点:tag.descendants 返回一个生成器,对它进行遍历能够失去以后 tag 节点的所有子孙节点的循环遍历后果。间接父节点:tag.parent 获取以后 tag 的间接父节点

所以父节点:tag.parents 返回一个生成器,能够获取以后 tag 的所有父辈节点

next 的兄弟节点:tag.next_sibling 和 tag.next_siblings,返回值类型不必赘述。previous 的兄弟节点:tag.previous_sibling 和 tag.previous_siblings,同样返回类型不必赘述。

以上大略就是 BeautifulSoup 在搜寻信息时所需的常识,其它如两种形式联合的 tag.find_parent(name,attrs,recursive,string,**kwargs)等办法,之后能够缓缓理解。

正文完
 0