zoukankan      html  css  js  c++  java
  • 爬虫_基础知识

    一,一些基本的内容

    # 什么是爬虫?

    爬虫就是模拟客户端(浏览器)发送网络请求,获取响应,按照一定的规则提取数据,模拟客户端发(浏览器)送网络请求:发送和浏览器一模一样的数据,获取和浏览器一模一样的请求

    # 爬虫的数据去哪了
    呈现出来:展示在网页上,展示在app上
    就行分析:对爬取的数据进行分析

    # HTTP:超文本传输协议
    以明文方式进行传输
    效率高,但是安全性低

    # HTTPS:HTTP+SSL(安全套接字层)
    传输之前先进行加密,之后再进行解密获取内容
    效率较低,但是安全

    # HTTP协议之请求
    1:请求行
    2:请求头
    User-Agent:用户代理,对方的服务器能通过User-Agent直到当前请求对方服务器的资源的是什么浏览器
    Cookie:用来存储用户的部分信息,每次请求时会携带Cookie发送给对方的服务器
    3:请求体
    用于携带数据
    GET请求没有请求体
    POST请求有请求体

    # HTTP协议之响应
    1:响应头
    Set-Cookie:对方通过该字段设置Cookie到本地
    2:响应体
    url地址对应的响应

    # 使用超时参数

    requests.get(url,headers = headers,timeout=3)    # 该请求再3秒内必须返回响应,否则会报错
    二,retrying模块
    raise会抛出异常(自定义异常)
    # 如果出现错误就会一直重试
    @retry
    def func():
        print("...")
        
    # stop_max_attempt_number 最带的重试次数
    @retry(stop_max_attempt_number = 5)
    def func():
        print("ERROR")
        raise
    
    # stop_max_delay 失败重试最大事件,单位为毫秒,超出时间立即停止重试
    @retry(stop_max_delay=1000)
    def func():
        print("重试执行该方法的时间为1秒,超过1秒则不继续执行")
        raise
        
    # wait_fixed 设置失败重试的时间间隔
    @retry(wait_fixed = 1000)
    def func():
        print("该方法会一直重试,其每次重试的时间隔为秒")
        raise
    
    # wait_random_min, wait_random_max 设置失败重试随机性间隔时间
    @retry(wait_random_min=1000, wait_random_max=3000)
    def func():
        print("每次失败是重试的时间间隔为随机性的,且该随机数再1秒和3秒之间")
    
    # wait_exponential_multiplier-间隔时间倍数增加,wait_exponential_max-最大间隔时间
    
    @retry(wait_exponential_multiplier=1000, wait_exponential_max=10000)
    def func():
        print "Wait 2^x * 1000 milliseconds between each retry, up to 10 seconds, then 10 seconds afterwards"
        print int(time.time())
        raise
    三,requests 模块的使用
     # requests中的参数
    1
    method # 请求方式,常见的请求方式有GET/POST 2 url # 将要获取的页面的url链接 3 param # 可以利用 字典/字符串/字节作为url的参数 4 data # 可以利用 字典/字符串/字节/文件最为Request请求携带的数据 5 json # 用以json为格式的数据,用来作为Request的内容 6 headers # 以字典的形式,请求中携带的一些请求头如user-agent,来模拟浏览器的访问 7 cookies # 用来存储用户的部分信息,用来进行下一次访问携带的数据 8 files # 传输文件 9 auth # 权限,以元组形式,支持HTTP认证的功能 10 timeout # 超时参数,可设置最长链接时间,或设置连接时间和内容读取时间(元组形式) 11 allow_redirects # 是否允许重定向 12 proxies # 字典类型,可设置代理服务器 13 verify # 自动进行网站证书的认证,默认为True 14 stream # 是否将获取的内容立即下载,默认为True

    # request中参数的解释

    # method
    def param_method():
        requests.request(method = "get")
        requests.request(method = "post")
    
    # url
    def param_url():
        requests.request(
            method = "get",
            url = "https://www.baidu.com"
        )
    
    # data
    def param_data():
        # data可以是字典的形式
        requests.request(
            method = 'post',
            url = "https://www.baidu.com",
            data = {"k1":"v1","k2":"v2"}
        )
        
        # data可以是字符串的形式
        requests.request(
            method = 'post',
            url = "https://www.baidu.com",
            data = "k1=v1; k2=v2;"
        )
    
        # data可以是以字节的形式
        # 待补充
        
        # data可以是以文件的形式
        requests.request(
            method = 'post',
            url = "https://www.baidu.com",
            data = open('test.py', mode='r', encoding='utf-8'), 
            # 文件内容是:k1=v1;k2=v2
        )
    
    # json
    def param_json():
        # 将json中对应的数据进行序列化成一个字符串,json.dumps(...)
        # 然后发送到服务器端的body中,并且Content-Type是 {'Content-Type': 'application/json'}
        post_dict = {
            "BaseRequest": {
                "DeviceID": "e155674455601272",
                "Sid": TICKET_DICT["wxsid"],
                "Skey": TICKET_DICT["skey"],
                "Uin": TICKET_DICT["wxuin"],
            },
            "SyncKey":USER_INIT_DICT["SyncKey"],
            "rr":1
        }
        requests.request(
            method = 'POST',
            url = "https://www.baidu.com"
            json = post_dict
        )
    
    # headers
    def param_headers():
        headers =     {
            "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
            "Host":"www.baidu.com"
            }
        requests.request(
            method = "GET",
            url = "https://www.baidu.com",
            headers = headers
        )
    
    # cookies
    def param_cookies():
        cookie = "...sug=3; sugstore=0; ORIGIN=0;..."
            requests.request(
            method = "GET",
            url = "https://www.baidu.com",
            cookies = cookie
        )
    
    # files 文件上传
    def param_file():
        requests.post(
            url="https://www.baidu.com",
            file={"files":open("images.jpg"."rb")}
        )
    
    # 遇到需要认证的网站 可以使用requests中的auth实现
    from requests.auth import HTTPBasicAuth, HTTPDigestAuth
    ret = requests.request(
        method = "get",
        url = 'https://www.baidu.com',
        auth=HTTPBasicAuth('user', '123'))
            
    # timeout 超时参数    
    requests.get(url,headers = headers,timeout=3)    # 该请求再3秒内必须返回响应,否则会报错
    
    # timeout元组类型(发送时间/读取时间)
    ret = requests.get(url, timeout=(5, 1))
        
    # 是否允许重定向
    ret = requests.get('https://www.baidu.com', allow_redirects=False)    
    
    # proxies 代理(向代理服务器发送请求,代理服务器再向url发送请求)
    response = requests.get(
        url = url,
         proxies = {
              "http": "http://127.0.0.1:9743",        # 代理服务器IP地址
              "https": "https://127.0.0.1:9743",
            }
        )        
    
    # stream 流 当请求时不立即获取结果,可通过迭代的方式来获取结果
    如果为false会将所有文件一下子下载下来
    如果为true会一点一点的下载文件(内存不足情况下使用)
    def param_stream():
        ret = requests.get('https://www.baidu.com', stream=True)
        print(ret.content)
        ret.close()
    
        # 迭代
        from contextlib import closing
        with closing(requests.get('https://www.baidu.com', stream=True)) as r:
        # 在此处理响应。
        for i in r.iter_content():
        print(i)
    
    # 证书
    response = requests.get(
        url = url,
        cert="test.pem",    # 主动提供证书文件,证书文件引入方式
        verify=False        # 忽略网站证书的存在,照样能返回结果
    )    
    四,BeautifulSoup 模块的使用

     BeautifulSoup是做什么用的?

    BeautifulSoup是一个模块,该模块用于接收一个HTML或XML字符串,然后将其进行格式化,之后遍可以使用他提供的方法进行快速查找指定元素,从而使得在HTML或XML中查找指定元素变得简单。

    from bs4 import BeautifulSoup
    
    html_list = """
    <html>
        <head>
            <title>BeautifulSoup</title>
        </head>
    <body>
        <div class="title">
            <b>这是title中的b标签中的文本</b>
            <h1>这是title中h1标签中的文本</h1>
        </div>
    <div class="story">
        <p>友情链接</p>
        <a href="https://www.baidu.com" class="link" id="link2">百度首页</a>
        <a href="https://fanyi.baidu.com/" class="link" id="link3">百度翻译</a>
    </div>
    </body>
    </html>
    """
    # # 利用BeautifulSoup将html对象转成BeautifulSoup对象soup
    # # features="html.parser" 为本次处理的引擎
    soup = BeautifulSoup(html_list,features="html.parser")
    
    # 利用find来获取第一个匹配的标签
    tag = soup.find("a")
    tag = soup.find(name="a",attrs={"class":"link"},test="百度首页")    # 中可有多个参数,必须都匹配才能被选中
    
    # 获取所有匹配的标签
    tag = soup.find_all("a")
    tag = soup.find_all(name="a",attrs={"class":"link"},test="百度首页")
    #
    # 找到第一个a标签
    tag_a1 = soup.find(name = "a")
    
    # 找到所有的a标签
    tag_a_all = soup.find_all(name = "a")
    
    # 找到id为link2的标签
    tag_id = soup.select("#link2")
    
    # 找到class为link的标签
    tag_class = soup.select(".link")
    
    ## name 标签名称操作
    tag = soup.find("a")
    name = tag.name         # 获取当前标签的名称
    tag.name = "p"          # 修改标签的名称
    print(soup)
    
    ## 标签属性操作
    tag1 = soup.find("a")
    attrs = tag1.attrs          # 获取属性的值 href class id 的值
    tag1.attrs["id"] = "newid"  # 将id的值修改为newid
    del attrs["class"]          # 将class属性删除
    print(attrs)
    
    ## 获取所有的子标签
    body = soup.find("body")
    c = body.children           # 获取body中所有的子标签
    print(list(c))
    
    ## 获取所有子子孙孙标签
    body1 = soup.find("body")
    d = body1.descendants
    print(list(d))
    
    ## 将所有的子标签清空
    tag = soup.find("body")
    tag.clear()         # 留下<body></body>
    print(soup)
    
    ## 利用递归删除所有的标签,并获取被删除的标签
    test = soup.find("body")
    e = test.extract()      # 将body标签也删除
    print(soup)
    print(e)                # e 的值包括所有被删除的标签及其其中的内容
    
    # 将对象转为字符串
    test = soup.find("body")
    d = test.decode()           # 获取标签及其标签中的内容,也就是包括body标签
    d2 = test.decode_contents() # 只获取标签中的内容,也就是步包括body标签
    print(d2)
    
    # 将对象转为字节
    test = soup.find("body")
    e = test.encode()           # 包含当前的标签
    e2 = test.encode_contents() # 不含当前的标签
    print(e2)
    
    ## 找到所有的a和p标签
    t = soup.find_all(name=["a","p"])
    
    ## 找到id = "link"  或者 id="link2",class也是如此
    t = soup.find_all(id = ["link","link2"])
    
    ## 找到文本文件
    t = soup.find_all(text="百度首页")
    
    # get, 获取标签属性
    tag = soup.find('a')
    v = tag.get('id')
    print(v)
    
    # has_attr, 检查标签是否具有该属性
    tag = soup.find('a')
    v = tag.has_attr('id')
    print(v)
    
    # get_text, 获取标签内部文本内容
    tag = soup.find('a')
    v = tag.get_text()
    print(v)
    
    # index, 检查标签在某标签中的索引位置
    tag = soup.find('body')
    v = tag.index(tag.find('div'))
    print(v)
    
    tag = soup.find('body')
    for i,v in enumerate(tag):
        print(i,v)
    
    # is_empty_element,是否是空标签(是否可以是空)或者自闭合标签,
    # 判断是否是如下标签:'br' , 'hr', 'input', 'img', 'meta','spacer', 'link', 'frame', 'base'
    tag = soup.find('br')
    v = tag.is_empty_element
    print(v)
    
    ## 获取标签中的内容
    tag = soup.find("p")
    print(tag.string)                  # 获取标签中的内容
    tag.string = "修改原有的内容"      # 设置内容
    print(tag.string)
    tag = soup.find("body")
    a = tag.stripped_strings            # 获取标签内部所有的文本信息,提取所有的文本内容
    print(list(a))
    
    ## 追加标签
    tag = soup.find("body")
    tag.append(soup.find("a"))      # 取得a标签,将其追加到body中,将原本存在的a标签删除(相当于移动)
    print(soup)
    
    ## 创建一个标签,并将其追加到body的末尾
    from bs4.element import Tag
    obj = Tag(name='i',attrs={'id': 'idvalue'})
    obj.string = '我是标签中的文本内容'
    tag = soup.find('body')
    tag.append(obj)
    print(soup)
    
    ## 在当前标签内部指定位置插入一个标签
    from bs4.element import Tag
    obj = Tag(name='i', attrs={'id':'idvalue'})
    obj.string = '我是标签中的文本内容'
    tag = soup.find('body')
    tag.insert(1, obj)      # 为1表示再body中的第一个位置插入该标签,为2表示再body中第一个子标签后插入该标签
    print(soup)
    
    ## insert_after,insert_before 在当前标签后面或前面插入
    from bs4.element import Tag
    obj = Tag(name='i', attrs={'id': 'idvalue'})
    obj.string = '我是标签中的文本内容'
    tag = soup.find('body')
    tag.insert_before(obj)            # 在当前标签的前面插入(例如body之前)
    # tag.insert_after(obj)           # 在当前标签的后面插入
    print(soup)
    
    ## 将当前标签替换为指定标签(会将原本标签删除,再加入该标签)
    from bs4.element import Tag
    obj = Tag(name='i', attrs={'id': 'idvalue'})
    obj.string = '我是标签中的文本内容'
    tag = soup.find('div')
    tag.replace_with(obj)
    print(soup)
    
    ## 创建标签之间的关系
    tag = soup.find('div')
    a = soup.find('a')
    tag.setup(previous_sibling=a)
    print(tag.previous_sibling)
    
    ## wrap,将指定标签把当前标签包裹起来
    from bs4.element import Tag
    obj1 = Tag(name='div', attrs={'id': 'it'})
    obj1.string = '我是一个新来的'
    tag = soup.find('a')
    v = tag.wrap(obj1)      # a标签将被新创建的div标签包裹起来
    print(soup)
    
    ## 去掉当前标签,将保留其包裹的标签,该标签的子标签也会保留,该标签的文本内容也会被保留
    tag = soup.find('a')
    v = tag.unwrap()        # 将第一个a标签去掉 保留其包裹的标签
    print(soup)

    # BeautifulSoup中的css选择器

    # 选择二所有的title标签
    soup.select("title")
    # 选择所有p标签中的第三个标签 soup.select("p:nth-of-type(3)")

    # 选择body下的 a 标签 soup.select("body a")

    # 选择html下的head下的title标签 soup.select("html head title") soup.select("span,a")

    # 选择head标签下的直接title标签 soup.select("head > title")

    # 选择p节点下id=link1的直接子节点 soup.select("p > #link1")

    # 选择body下的所有a直接节点 soup.select("body > a")

    # 选择id为link1后的class=sisiter的所有兄弟节点 soup.select("#link1 ~ .sister")

    # 选择id为link1后的class=sisiter的第一个兄弟节点 soup.select("#link1 + .sister")

    # 选择class=sisiter的所有节点 soup.select(".sister")

    # 选择class=sisiter的所有节点 soup.select("[class="sister]")

    # id为link1的节点 soup.select("#link1")

    # 选择a节点,且a节点的id为link2 soup.select("a#link2")

    # 选择所有的a节点,且a节点含有属性href soup.select('a[href]')

    # 指定href属性值的a节点 soup.select('a[href="http://example.com/elsie"]')

    # 指定href属性以指定值开头的a节点 soup.select('a[href^="http://example.com/"]')

    # 指定href属性以指定结尾的所有a节点 soup.select('a[href$="tillie"]')

    # 利用正则表达式进行匹配 soup.select('a[href*=".com/el"]')

    待补充...

  • 相关阅读:
    程序员:不要自称为码农
    SpringBoot对静态资源配置
    LeetCode 572. Subtree of Another Tree(子树)
    LeetCode 437. Path Sum III(统计路径和等于sum的路径数量)
    LeetCode 112. Path Sum(判断路径和是否等于一个数)
    LeetCode 617. Merge Two Binary Trees(归并两棵二叉树)
    LeetCode 226. Invert Binary Tree(翻转二叉树)
    Failure to transfer org.apache.maven.plugins:maven-resources-plugin:pom:2.6 的解决办法
    linux-查询某软件的安装的目录
    WebService概念解释
  • 原文地址:https://www.cnblogs.com/Doaoao/p/10425921.html
Copyright © 2011-2022 走看看