22.2.11爬虫基础和数据解析

爬虫基础和数据解析

1.web请求过程剖析:

  • 服务器渲染:
    • 在服务器那边直接把数据和HTML整合在一起,统一返回给浏览器,这种渲染方式在页面源码中看得到数据。

    • 例如:在浏览器(客户端)中输入IU时,浏览器向服务器发送带有“IU”的请求,服务器会返回带有IU的经过整理后的HTML给浏览器(客户端)。

  • 客户端渲染:
    • 第一次请求时服务器只会返回一个HTML骨架,在第二次请求时才会拿到数据,进行数据展示。这种渲染方式在页面源码中看不到数据,只有找到了对应的URL才能看到数据。

2.HTTP协议:

  • HTTP协议将一条消息分为三块内容:
    • 请求:

      • 请求行:一般是请求方式(get/post),请求URL的地址,协议。。。。。。

      • 请求头:存放一些服务器要使用的附加信息。

      • 请求体:一般放一些请求参数。

    • 响应:

      • 响应行:协议,状态码(404,200.。。。。。。)

      • 响应头:放客户端要使用的附加信息;

      • 相应体:服务器返回的真正客户端要使用的内容(HTML,JSON等)。

  • 请求头中常见重要内容:
    • user-Agent:请求载体的身份标识。

    • Referer:防盗链(这次请求是从哪个页面来,在反爬中常用)。

    • cookie:本地字符串中数据信息(用户登录信息,反爬的token)。

  • 响应头中常见重要内容:
    • cookie:

    • 一些字符串:一般是token字样,防止攻击和反爬。

  • 请求方式:
    • get:显示提交,查询时多用。get是根据URL直接获取网页信息(即某个网址所包含的信息),get方法获取到的内容是稳定的(即每个人打开某个网页获得的信息相同)。get直接输入URL即可。

    • post:隐示提交,post是要携带用户信息的请求方式,post要获取的内容只靠网址是不能获取到的,需要提交一些额外的信息,这种信息在不同的网页中发挥不同功能。例如在查询天气的网页,可能就是要输入城市信息;在登录某些网页时,又是账号和密码的载体。post需要输入特定信息,那么得到的网页内容就会有特异性。post每次获取某个特定网页都需要输入额外信息

3.数据解析:

  • 方式:
    • 共有三种,分别为re解析,bs4解析,xpath解析。

    • re解析:
      • 正则表达式:

        • 1.元字符:
          . 匹配除了换行符以外的任意字符
          \w 匹配数字,字母,下划线
          \s 匹配任意空白符
          \d 匹配数字
          \n 匹配一个换行符
          \t 匹配一个制表符
          ^ 匹配输入字符串的开始位置
          $ 匹配输入字符串的结束位置
          \W 匹配除了数字字母下划线
          \S 匹配非空白符
          \D 匹配非数字
          () 匹配并获得与括号内的表达式相匹配的串
          [...] 字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'
          [^...] 负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain"    'p''l''i''n'


          2.量词:控制元字符出现的次数;
          * 0次或更多次
          + 1次或更多次
          ? 0次或1次
          {n} 重复n次
          {n,} 重复>=n次
          {n,m} 重复n到m次


          3.贪婪匹配和惰性匹配:
           (假设有字符串txzmytxzmytxzmy)
          贪婪匹配: .* 尽可能匹配最远的 例如t.*y   对于上述字符串得到结果 txzmytxzmytxzmy
          惰性匹配: .*? 尽可能匹配最近的 例如t.*?y 对于上述字符串得到结果 txzmy

      • re模块:

        • findall:匹配字符串中所有复合的内容。

        • finfiter:匹配字符串中所有复合的内容,返回值是一个迭代器,从迭代器中取得内容要用.group()

        • search:返回match对象,拿数据需要.group()

        • match:从头开始匹配。

      • 预加载正则表达式:

        • obj = re.compile(r"正则表达式") #便于多次利用正则表达式。

          补充:
          (?P<名字>正则表达式) 可以拿到特别标识的(名字)内容
          re.S 可以将不同行的字符串连接起来整体匹配
      • 练习:

        • import requests
          from requests.packages.urllib3.exceptions import InsecureRequestWarning

          requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
          # 解决 InsecureRequestWarning: Unverified HTTPS request is being made to host(requests证书警告)

          import selenium
          import re

          url = "https://dytt89.com/"
          response = requests.get(url = url,verify=False)
          response.encoding = "gb2312"
          edge = response.text
          obj = re.compile(r'2022新片精品.*? <ul>.*?彻底解决迅雷无法下载</font></a><span><font color="#FF0000">02-11</font></span></li>(?P<web>.*?) </div>',re.S)
          res = obj.finditer(edge)
          obj2 = re.compile(r"<a href='(?P<herf>.*?)' title="'(?P<title>.*?)'">",re.S)
          obj3 = re.compile(r'<td style="WORD-WRAP: break-word" bgcolor="#fdfddf"><a href="(?P<adress>.*?)">magnet')
          for i in res:
             url2 = i.group("web")
             res2 = obj2.finditer(url2)
             for j in res2:
                 print(j.group("title"))
                 print("下载地址 ")
                 url3 = url+j.group("herf").strip("/")
                 #print(url3)
                 response2 = requests.get(url3)
                 response2.encoding = "gb2312"
                 res3 = obj3.finditer(response2.text)
                 for k in res3:
                  print("'"+k.group("adress")+"'")
                 
          #在第二个for里面也可以将url3存在一个列表里
        •  

    • bs4解析:
      • bs4解析可以通过网页源码的标签来获得藏在网页源码中的数据。

      • bs4解析的流程:

        • 先创建BeautifulSoup对象;

        • 从对象中利用find("标签","limit")和find_all("标签","limit")找数据。

          • find_all和find的使用: 1、在提取标签的时候,第一个参数是标签的名字。如果在提取标签的时候想要使用标签属性进行过滤,那么可以在这个方法中通过关键字参数的形式,将属性的名字以及对应的值传进去,或者是使用attrs属性,将所有的属性以及对应的值放在一个字典中传给attrs属性。

            2、有时,在提取标签的时候,不想提取那么多,可以使用limit参数限制提取个数。

            find与find_all的区别: 1、find:找到第一个满足条件的标签就返回,只返回一个元素。 2、find_all:将所有满足条件的标签都返回,返回多个(以列表的形式)。 使用find和find_all的过滤条件: 1、关键字参数:将属性的名字作为关键字参数的名字,以及属性的值作为关键字参数的值进行过滤。 2、attrs参数:将属性条件放到一个字典中,传给attrs参数。

      • 练习:

        • import re
          from bs4 import BeautifulSoup


          url = "http://www.netbian.com/"
          headers = {
          "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36"
          }
          response = requests.get(url)
          response.encoding = "gbk"
          #print(response.text)

          bser = BeautifulSoup(response.text,"html.parser")
          alist = bser.find("div",attrs={"class":"wrap clearfix"}).find_all("img")
          #print(alist)
          for a in alist:
             print(a.get("src"))

           

    • xpath解析:
      • xpath解析是依靠节点之间的关系(主要是利用关系,也可以向上面的解析方式一样利用属性)查找数据。

      • 相关的知识点:

        • xml格式:

          • xml格式包含html,调用xpath时传入的参数要对应,其格式大致如下:

          • 。。。
               <Teams>
                   <Member team="X" Description="X">
                       <name>灵动生活</name>
                       <position>planning</position>
                   </Member>
                   <Member team="Y" Description="Y">
                       <name>蓝蓝海天</name>
                       <position>support</position>
                   </Member>
                   <Member team="Z" Description="Z">
                       <name>神舟龙</name>
                       <position>lean</position>
                   </Member>
               </Teams>
            。。。
          • 例如:拿到数据蓝蓝海天:

            • "Teams/Member[2]/name/text()"
              text()可以拿到标签中的文字内容。
          • 补充:

            • //  可以拿到后代中所有的
              eg:
              "Teams//name/text()"
              能拿到灵动生活,蓝蓝海天,神州龙

              [@... = ...] 属性筛选
              eg:
                 "Teams/Member[@team = x]/name/text()"
                 能拿到灵动生活
                 
              相对路径查找:
              假设省略号到达的路径为li = html.xpath("...一个html网页")
                 则name = li/xpath("./Teams/Member[@team = x]/name/text()")
                 
              要拿到"X"
              则x = li/xpath("./Teams/Member/@team")
      • 练习(爬取猪八戒网址):

        • import requests
          from lxml import etree

          url = "https://search.zbj.com/f/?type=new&kw=SaaS&fr=newpdy.it.20.8.04"
          response = requests.get(url)
          #print(response.text)

          html = etree.HTML(response.text)
          divs = html.xpath("/html/body/div[6]/div/div/div[2]/div[5]/div[1]/div")

          for div in divs:
             location = div.xpath("./div/div/a[1]/div[1]/div/span/text()")[0]
             price = div.xpath("./div/div/a[2]/div/div[1]/span[1]/text()")[0].strip("¥")
             appinfo = "saas".join(div.xpath("./div/div/a[2]/div/div[2]/p/text()"))
             name = div.xpath("./div/div/a[1]/div[1]/p/text()")[1]
             print(name)
             print(appinfo)
             print(price)
             print(location)

           

        •  

posted @ 2022-02-11 22:50  张满月。  阅读(162)  评论(0编辑  收藏  举报