• 爬虫_基础知识


    一,一些基本的内容

    # 什么是爬虫?

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

    # 爬虫的数据去哪了
    呈现出来:展示在网页上,展示在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"]')

    待补充...

  • 相关阅读:
    变分自编码器(Variational Autoencoder, VAE)通俗教程
    神经网络图灵机(Neural Turing Machines, NTM)
    【Java设计模式】单例模式
    SupportV7包中 SwipeRefreshLayout 修改下拉控件的距离
    eclipse项目导入androidstudio
    LiveWriter Test
    【Android学习】XML文本的三种解析方式(通过搭建本地的Web项目提供XML文件)
    【百度地图学习-一】初始化以及TextOverlay
    【Android学习】四种布局方式
    【Android学习】数据传递三种方式
  • 原文地址:https://www.cnblogs.com/Doaoao/p/10425921.html
Copyright © 2020-2023  润新知