美文网首页
爬虫学习笔记(1)

爬虫学习笔记(1)

作者: TOP生物信息 | 来源:发表于2019-10-06 13:50 被阅读0次

    爬虫入门的学习比我想象的要简单,目前已经掌握了固定网页的定向爬取。

    网页爬取

    Requests库的7个主要方法

    requests.request()  构造一个请求,支撑以下各方法的基础方法
    requests.get()  获取HTML网页的主要方法,对应于HTTP的GET
    requests.head() 获取HTML网页头信息的方法,对应于HTTP的HEAD
    requests.post() 向HTML网页提交POST请求的方法,对应于HTTP的POST
    requests.put()  向HTML网页提交PUT请求的方法,对应于HTTP的PUT
    requests.patch()    向HTML网页提交局部修改的请求,对应于HTTP的PATCH
    requests.delete()   向HTML网页提交删除请求,对应于HTTP的DELETE
    

    get()和head()对于普通用户来说是最常用的。

    requests.request()
    requests.request(method, url, **kwargs)
    
    method: 请求方式,包括7种
    GET HEAD POST PUT PATCH delete OPTIONS
    
    **kwargs: 控制访问的参数,均为可选项
    #重点掌握
    params: 字典或字节序列,作为参数增加到url中,对url进行修改
    data: 字典、字节序列、文件对象,作为Request的内容(作为向服务器提交资源时使用)
    json: JSON格式的数据,作为Request的内容,用法同data参数
    headers: 字典,“定制访问某个URL的HTTP的协议头”
    
    cookies: 字典或CookieJar,Request中的cookie。“从HTTP协议中解析cookie”
    auth: 元组,支持HTTP认证功能
    files: 字典,向服务器传输文件
    timeout: 设定超时时间,秒为单位。请求的内容超时了还没有返回,就会返回一个timeout异常
    proxies: 字典类型,设定访问代理服务器,可以增加登录认证(隐藏用户爬取网页原的IP地址信息)
    
    #开关字段
    allow_redirects: True/False, 默认为True, 重定向开关
    stream: True/False, 默认为True, 获取内容立即下载开关
    verify: T/F,默认为T,认证SSL证书开关
    
    cert: 保存本地SSL证书路径
    

    用法举例

    #params
    kv={"key1": "value1", "key2": "value2"}
    r=requests.request("GET", "http://python123.io/ws", params=kv)
    print(r.url)
    https://python123.io/ws?key1=value1&key2=value2
    
    #data
    #同下文requests.post()的用法
    
    #headers
    hd={"user-agent":"chrome/10"}
    r=requests.request("POST", "http://python123.io/ws", headers=hd)
    ##模拟chrome v10浏览器向服务器发起访问
    
    #files
    fs={"file": open("tmp.xlsx", "rb")}
    r=requests.request("POST", "http://python123.io/ws", files=fs)
    
    #proxies
    pxs={'http': 'http://user:pass@10.10.10.1:1234', 'https': 'http://10.10.10.1:4321'}
    r=requests.request("GET", "http://www.baidu.com", proxies=pxs)
    
    requests.get()

    requests库最常用方法

    #标准用法:
    #requests.get(url, params=None, **kwargs)
    #r=requests.get(url)
    #右边构造一个向服务器请求资源的Requests对象,此对象是Requests库内部生成的
    #左边是返回的一个包含服务器所有相关资源的Response对象
    r=requests.get("http://m.dict.cn/msearch.php?q=request")
    r.status_code #状态码200为连接成功
    r.encodeing="utf-8"
    r.text
    
    requests.head()

    当资源很大时,用head()方法获得资源概要

    #标准用法:
    #requests.head(url, **kwargs)
    r=requests.head("http://www.chinadaily.com.cn/a/201910/01/WS5d92b7a1a310cf3e3556e759.html")
    r.headers
    
    requests.post()
    #标准用法:
    #requests.post(url,data=None,json=None,**kwargs)
    test_dict={"user_name": "hsy", "user_age": "23"}
    
    r=requests.post("http://httpbin.org/post", data=test_dict)
    
    print(r.text)
    {
      "args": {}, 
      "data": "", 
      "files": {}, 
      "form": {
        "user_age": "23", 
        "user_name": "hsy"
      }, 
      "headers": {
        "Accept": "*/*", 
        "Accept-Encoding": "gzip, deflate", 
        "Content-Length": "25", 
        "Content-Type": "application/x-www-form-urlencoded", 
        "Host": "httpbin.org", 
        "User-Agent": "python-requests/2.22.0"
      }, 
      "json": null, 
      "origin": "115.27.203.85, 115.27.203.85", 
      "url": "https://httpbin.org/post"
    }
    

    向URL POST一个字典, 自动编码为form

    r=requests.post("http://httpbin.org/post", data="huangsiyuan")
    
    print(r.text)
    {
      "args": {}, 
      "data": "huangsiyuan", 
      "files": {}, 
      "form": {}, 
      "headers": {
        "Accept": "*/*", 
        "Accept-Encoding": "gzip, deflate", 
        "Content-Length": "11", 
        "Host": "httpbin.org", 
        "User-Agent": "python-requests/2.22.0"
      }, 
      "json": null, 
      "origin": "115.27.203.85, 115.27.203.85", 
      "url": "https://httpbin.org/post"
    }
    

    追加字符串则是在"data"中

    requests.put()

    与上面类似,只是有覆盖操作

    #标准用法:
    requests.put(url,data=None,**kwargs)
    
    requests.patch()
    requests.patch(url,data=None,**kwargs)
    
    requests.delete()
    requests.delete(url,**kwargs)
    

    Response对象的属性

    r.status_code HTTP请求的返回状态,200表示连接成功,404(只要不是200)表示失败
    r.text url对应的页面内容
    r.encodeing 从HTTP header中猜测页面内容的编码方式
    r.apparent_encoding 从内容文本中分析出编码方式(备选编码,如果文本中有中文,需将r.apparent_encoding赋值给r.encodeing)
    r.content 页面内容的二进制形式
    

    Requests库的异常

    requests.ConnectTimeout 连接远程服务器超时(一个预定时间)异常
    requests.ConnectionError    网络连接错误异常,如DNS查询失败、(服务器防火墙)拒绝连接等
    requests.HTTPError  HTTP错误异常
    requests.URLRequired    URL缺失异常
    requests.TooManyRedirects   超过最大重定向次数,产生重定向异常
    requests.Timeout    请求URL(到获得返回内容整个过程)超时,产生超时异常
    

    爬取网页的通用代码框架

    r.raise_for_status() 如果状态码不是200就会爆出requests.HTTPError,利用这个特性可以放在代码中检验
    Python中异常处理用到try except

    import requests
    
    def getHTMLText(url):
        try:
            r=requests.get(url, timeout=30)
            r.raise_for_status()
            r.encoding=r.apparent_encoding
            return r.text
        except:
            return "产生异常"
    if __name__ == "__main__":
        url="http://www.chinadaily.com.cn/"
        print(getHTMLText(url))
    

    HTTP协议

    url格式
    #http://host[:port][path]
    #host: 合法的Internet主机`域名`或`IP地址`
    #port: 端口号,缺省端口为80
    #path: 请求资源的内部路径
    
    http://www.chinadaily.com.cn/a/201910/01/WS5d92b7a1a310cf3e3556e759.html
    

    如何理解URL

    URL是通过HTTP协议存取资源的Internet路径,一个URL对应一个数据资源。好比电脑上一个文件(夹)路径对应一个文件(夹)。

    HTTP协议对资源的操作
    GET 请求获取URL的资源
    HEAD 请求获取URL位置资源的头部信息
    POST 请求向URL位置的资源后附加新的数据
    PUT 请求向URL位置存储一个资源,覆盖原URL位置的资源
    PATCH 改变该处资源的部分内容
    DELETE 请求删除URL位置存储的资源
    

    与Requests库中的6个方法一致

    关于网络爬虫

    网络爬虫的尺寸

    爬取网页 Requests库 占比90%
    爬取网站 Scrapy库
    爬取全网(为了建立搜索引擎,如百度,谷歌背后的爬虫)

    网络爬虫的限制
    • 来源审查:判断User-Agent进行限制
      检查来访HTTP协议头的User-Agent域,只响应浏览器或友好爬虫的访问
    • 发布公告:Robots协议
      告知所有爬虫网站的爬取策略,要求爬虫遵守
    Robots协议

    作用:网站告知网络爬虫哪些页面可以爬取,哪些不行
    形式:在网站根目录下的robots.txt文件
    使用

    • 网络爬虫:自动或人工识别robots.txt,再进行内容爬取
    • 约束性:商业用途格外小心;可以不遵守但存在法律风险

    类人行为可不参考Robots协议,比如一天只访问一个网页几次

    网页解析

    Beautiful Soup

    HTML格式

    例子

    <html><head><title>This is a python demo page</title></head><body><p class="title"><b>The demo python introduces several python courses.</b></p><p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:<a href="http://www.icourse163.org/course/BIT-268001" class="py1" id="link1">Basic Python</a> and <a href="http://www.icourse163.org/course/BIT-1001870001" class="py2" id="link2">Advanced Python</a>.</p></body></html>
    

    标签的基本结构

    基本用法
    import requests
    #课程的例子
    #r=requests.get("https://www.python123.io/ws/demo.html")
    #在海词词典网页版上面查询单词:prologue。url如下,判断接口的什么样子。
    r=requests.get("http://m.dict.cn/msearch.php?q=prologue")
    r.status_code
    r.text
    
    demo=r.text #此时demo是一个html格式的信息
    
    from bs4 import BeautifulSoup #从库中引入一个类
    #在提供了demo, 解析器之后生成一个名叫soup的对象
    soup=BeautifulSoup(demo,"html.parser")
    print(soup.prettify())
    

    最终可以解析成树形结构

    或者直接从HTML文件开始解析

    理解:HTML文档,标签树,BeautifulSoup类三者等价

    BeautifulSoup库的解析器
    解析器 用法  条件
    bs4的HTML解析器 BeautifulSoup(mk,'html.parser') 安装bs4库
    lxml的HTML解析器    BeautifulSoup(mk,'lxml')    安装lxml
    lxml的XML解析器 BeautifulSoup(mk,'xml') 安装lxml
    html5lib的解析器    BeautifulSoup(mk,'html5lib')    安装html5lib
    
    BeautifulSoup类的基本元素

    获取标签内容
    任何符合HTML语法的标签都可以通过类似soup.tag获取

    >>> soup.strong
    <strong>开场白;序言;序幕</strong>
    

    当相同名称的标签有多个时,上述用法会返回第一个

    >>> soup.ol
    <ol>
    <li>序言</li>
    <li>开场白</li>
    <li>序幕</li>
    <li>序诗</li>
    <li>序幕性事件</li>
    <li>序</li>
    <li>开端</li>
    <li>作开场白的演员</li>
    </ol>
    >>> soup.ol.li
    <li>序言</li>
    

    Name

    >>> soup.strong.name
    'strong'
    >>> soup.strong.parent.name
    'li'
    

    属性

    >>> soup.div.attrs
    {'class': ['tm']}
    #查看具体的value
    >>> soup.div.attrs['class']
    ['tm']
    

    标签内部的字符串

    >>> soup.strong.string
    '开场白;序言;序幕'
    

    注释
    在HTML格式中,代表注释信息

    基于bs4库的HTML网页内容遍历方法

    标签树的下行遍历

    .contents   子节点的列表,将<tag>所有F1节点存入列表(在列表中不只有tag,还可能有"\n"等字符串)
    .children   子节点的迭代类型,与.content类似,用于循环遍历F1节点
    .descendants    子孙节点的迭代类型,包含所有子孙节点,用于循环遍历
    
    #后面两个用法类似
    for child in soup.ol.children:
        print(child)
    

    标签树的上行遍历

    .parent 节点的父亲标签
    .parents    节点先辈标签的迭代类型,用于循环遍历先辈节点
    
    for parent in soup.strong.parents:
        if parent is None:
            print(parent)
        else:
            print(parent.name)
    

    标签树的平行遍历

    .next_sibling   返回按照HTML文本顺序的下一个平行节点标签(可能会返回字符串,如"\n")
    .previous_sibling   返回按照HTML文本顺序的上一个平行节点标签
    .next_siblings  迭代类型,返回按照HTML文本顺序的后续所有平行节点标签
    .previous_siblings  迭代类型,返回按照HTML文本顺序的前续所有平行节点标签
    
    基于bs4库的HTML格式输出

    prettify()方法为标签树各个层次更友好地输出

    信息标记和提取

    信息标记的3种方法

    XML(HTML属于此类) 最早的通用信息标记语言,可扩展性好,但繁琐;Internet上的信息交互与传递
    JSON 信息有类型,适合程序处理(js),较XML简洁;移动应用云端和节点的信息通信,程序对接口的处理,无注释
    YAML 信息无类型,文本信息比例最高,可读性好;各类系统的配置文件,有注释易读

    信息提取的一般方法

    如何从已标记的信息中提取想要的部分?
    方法一
    完整解析信息的标记形式(3种),再提取关键信息
    需要标记解析器,如:bs4库的标签树遍历
    优点:准确
    缺点:繁琐,耗时
    方法二
    无视标记形式,直接搜索关键信息
    对信息的文本使用查找函数即可
    优点:简洁,快
    缺点:提取准确性与信息内容复杂程度相关
    融合方法
    需要标记解析器及文本查找函数

    实例
    提取HTML中所有URL链接
    思路:

    1. 搜索所有<a>标签
    2. 解析<a>标签格式,提取href后的链接内容
    for link in soup.find_all('a'):
        print(link.get('href'))
    
    基于bs4库的HTML内容查找方法
    .find_all(name, attrs, recursive, string, **kwargs) 返回一个列表类型,存储查找的结果
    
    name: 对标签名称的检索字符串
    soup.find_all('strong') 寻找strong标签
    for tag in soup.find_all(True):print(tag.name)  打印所有标签名称
    
    attrs: 对标签属性值的检索字符串,可标注属性检索
    soup.find_all('div','cl')
    soup.find_all(id="dbann") #此时是精确查找
    soup.find_all(id=re.compile('d')) #正则查找
    
    recursive: 是否对子孙全部搜索,默认为True
    soup.find_all('li',recursive=False)
    
    string: <>...</>中字符串区域的检索字符串
    soup.find_all(string="海词词典") #此时是精确查找
    soup.find_all(string=re.compile("海词"))
    

    综上:正则表达式+find_all()
    简写形式

    soup(...)等价于soup.find_all(...)
    <tag>(...)等价于soup.find_all(...)
    

    拓展方法
    参数同find_all(), 不一定常用

    .find() 搜索且只返回一个结果,字符串类型
    .find_parents() 在先辈节点中搜索,返回列表类型
    .find_parent()  在先辈节点中返回一个结果,字符串类型
    .find_next_siblings()   在后续平行节点中搜索,返回列表类型
    .find_next_sibling()    在后续平行节点中搜索,字符串类型
    .find_previous_siblings()   在前续平行节点中搜索,返回列表类型
    .find_previous_sibling()    在前续平行节点中返回一个结果,字符串类型
    

    前面都需要接tag标签,如果是一个具体的bs对象,比如上文的soup,则相当于根节点,查找时不包括当前节点。

    print()的格式化输出

    print("{:^10}\t{:>6}\t{:6}\t{:^10}".format("排名","学校名称","地区","总分"))
    
    #每一个槽从左到右可以设置哪些东西
    :   引导符号
    <填充>    用于填充的单个字符
    <对齐>    <左对齐    >右对齐    ^居中对齐
    <宽度>    槽的设定输出宽度
    ,   数字的千位分隔符适用于整数和浮点数
    <.精度>   浮点数小数部分的精度或者字符串的最大输出长度
    <类型>    整数类型b,c,d,o,x,X  浮点数类型e,E,f,%
    
    tplt="{0:^10}\t{1:{4}^10}\t{2:{4}^10}\t{3:^10}"
    print(tplt.format("排名","学校名称","地区","总分",chr(12288)))
    

    相关文章

      网友评论

          本文标题:爬虫学习笔记(1)

          本文链接:https://www.haomeiwen.com/subject/gqaypctx.html