python 基础 网络爬虫 day04

目录

1.xpath工具(解析)

2.lxml库及xpath使用


day04

1.requests模块方法

  1. get()参数
    1. 查询参数:params - 字典
    2. 代理:proxies - 字典
      1. 普通代理:{'协议':"协议://ip地址:端口号"}
      2. 私密代理:{'协议':"协议://用户名:密码@ip地址:端口号"}
    3. Web客户端验证:auth - 元组
      auth = ('tarenacode','code_2014')
    4. SSL证书:verify -> 默认True
    5. timeout
  2. post()方法
    1. data - 字典,Form表单数据
  3. 响应对象属性
    1. text - 字符串
    2. encoding - res.enconding = 'utf-8'
    3. content -> 字节流
    4. status_code - 服务器响应码

2.数据持久化储存

  1. MySQL流程
    1. db = pymysql.connect('local',...'库名',charset='uft8')
    2. cursor = db.cursor()
    3. cursor.execute("sql命令",[])
    4. db.commit()
    5. cursor.close()
    6. db.close()
  2. mongodb流程
    1. conn = pymongo.MongoClient('localhost',27017)
    2. db = conn.库名
    3. myset = db.集合名
    4. myset.insert(字典)
      终端操作
      1. mongo
      2. show dbs
      3. use 库名
      4. show tables
      5. db.集合名.find().pretty()

3.Handler处理器(urllib库中)

  1. 使用流程
    1. 创建Handler:ProxyHandler(普通代理IP)
    2. 创建opener:build_opener(Handler)
    3. 发请求:opener.open(requeust)
  2. ProxyHandler
    1. ph = urllib.request.ProxyHandler({'http':'IP: ..'})
    2. opener = urllib.request.bulid_opener(ph)
    3. req = urllib.request.Request(url,headers=headers...)
    4. res = opener.open(req)
    5. html = res.read().decode('utf-8')
  3. Handler处理器分类
    1. ProxyHandler({普通代理IP})
    2. ProxyBasicAuthHandler(密码管理器对象)
    3. HTTPBasicAuthHandler(密码管理器对象)
    4. 流程
      1. 创建
        pwdmg = urllib.request.HTTPPasswordMgrWith...()
      2. 添加认证信息
        pwdmg.add_password(None,{"协议":"IP:..},"user","pwd")
      3. Handler开始

day04

1.xpath工具(解析)

  1. xpath
    在xml文档中查找信息的语言,同样适用于HTML文档的检索
  2. xpath辅助工具
    1. Chrome插件:XPath Helper
      1. 打开:Ctrl + Shift + 大写X
      2. 关闭:Ctrl + Shift + 大写X
    2. Firefox插件:Xpath checker
    3. XPath表达式编辑工具:XML quire
  3. xpath匹配规则
    1. 匹配演示
      1. 查找bookstore下所有节点:/bookstore
      2. 查找所有的book节点://book
      3. 查找所有book下的title节点中,lang属性为‘en’的节点://book/title[@lang="en"]
      4. 查找bookstore下的第2个book节点下的title节点:/bookstore/book[2]/title/text()
        <?xml version="1.0" encoding="ISO-8859-1"?>
        <bookstore>
        <book>
        <title lang="en">Harry Potter</title>
        <author>J K. Rowling</author> 
        <year>2005</year>
        <price>29.99</price>
        </book>
        <book>
        <title lang="chs">Python</title>
        <author>Joe</author> 
        <year>2018</year>
        <price>49.99</price>
        </book>
        </bookstore>
        
    2. 选取节点
      /    :  从根节点开始选取
      //   :  从整个文档中查找节点
      @  : 选取某个节点的属性
           //title[@lang="en"]
    3. @的使用
      1. 选取1个节点://title[@lang="en"]
      2. 选取n个节点://title[@lang]
      3. 选取节点的属性值://title/@lang
    4. 匹配多路径
      1. 符号:|
      2. 获取所有book节点下的title节点和price节点
        //book/title | //book/price
    5. 函数
      1. contains():匹配一个属性值中包含某些字符串的节点
        //title[contains(@lang,'e')]
      2. text()
        //title[contains(@lang,'e')]/text()

2.lxml库及xpath使用

  1. lxml库:HTML/XML解析库
    1. 安装
      python -m pip install 1xml
      conda install lxml
    2. 使用流程
      1. 导模块
        from 1xml import etree
      2. 利用lxml库的etree模块创建解析对象
        parseHtml = etree.HTML(html)
      3. 解析对象调用xpath工具定位节点信息
        r_list = parseHtml.xpath('xpath表达式')
        ##只要调用了xpath,结果一定是列表
    3. 示例:
      from lxml import etree
      
      html = """<div class="wrapper">
      	<i class="iconfont icon-back" id="back"></i>
      	<a href="/" id="channel">新浪社会</a>
      	<ul id="nav">
      		<li><a href="http://domestic.firefox.sina.com/" title="国内">国内</a></li>
      		<li><a href="http://world.firefox.sina.com/" title="国际">国际</a></li>
      		<li><a href="http://mil.firefox.sina.com/" title="军事">军事</a></li>
      		<li><a href="http://photo.firefox.sina.com/" title="图片">图片</a></li>
      		<li><a href="http://society.firefox.sina.com/" title="社会">社会</a></li>
      		<li><a href="http://ent.firefox.sina.com/" title="娱乐">娱乐</a></li>
      		<li><a href="http://tech.firefox.sina.com/" title="科技">科技</a></li>
      		<li><a href="http://sports.firefox.sina.com/" title="体育">体育</a></li>
      		<li><a href="http://finance.firefox.sina.com/" title="财经">财经</a></li>
      		<li><a href="http://auto.firefox.sina.com/" title="汽车">汽车</a></li>
      	</ul>
      	<i class="iconfont icon-liebiao" id="menu"></i>
      </div>"""
      # 构造解析对象
      parseHtml = etree.HTML(html)
      # 利用解析对象调用xpath匹配
      r1 = parseHtml.xpath('//a/@href')
      #print(r1)
      
      # 获取 /
      r2 = parseHtml.xpath('//a[@id="channel"]/@href')
      #print(r2)
      
      # 获取非 /
      r3 = parseHtml.xpath('//ul[@id="nav"]//a/@href')
      #print(r3)
      # 获取所有 a 节点的文本内容
      r4 = parseHtml.xpath('//a/text()')
      #print(r4)
      # 获取 图片、军事 ... 
      r5 = parseHtml.xpath('//ul[@id="nav"]//a')
      for i in r5:
          print(i.text)
      扫描二维码关注公众号,回复: 3832914 查看本文章
    4. 如何获取节点对象的内容
      节点对象.text
    5. 案列1:获取百度贴吧帖子里面所有的图片
      1. 目标:抓取指定贴吧所有图片
      2. 思路
        1. 获取贴吧主页URL,下一页:找URL规律
        2. 获取1页中每个帖子的URL
        3. 对每个帖子URL发请求,获取帖子里图片URL
        4. 对图片URL发请求,以wb方式写入本地文件
      3. 步骤
        1. 获取贴吧主页URL
          http://tieba.baidu.com/f? + 查询参数
        2. 找到页面中所有帖子的URL
          src:完整链接
          href:和主URL进行拼接
            /p/5926064184
            http://tieba.baidu.com/p/5926064184
          xpath匹配
            写法1: //div[@class="col2_right j_threadlist_li_right"]/div/div/a/@href
            写法2(推荐): //div[@class="t_con cleafix"]/div/div/div/a/@href
        3. 找每个帖子中图片URL
          Xpath匹配:
            //img[@class="BDE_Image"]/@src
        4. 代码实现
          '''02_百度贴吧图片抓取案例.py'''
          import requests
          from lxml import etree
          
          class BaiduImageSpider:
              def __init__(self):
                  self.headers = {"User-Agent":"Mozilla/5.0"}
                  self.baseurl = "http://tieba.baidu.com"
                  self.pageurl = "http://tieba.baidu.com/f?"
                  
              # 获取所有帖子URL列表
              def getPageUrl(self,params):
                  res = requests.get(self.pageurl,params=params,headers=self.headers) 
                  res.encoding = "utf-8"
                  html = res.text
                  # 构建解析对象
                  parseHtml = etree.HTML(html)
                  # 帖子链接列表
                  t_list = parseHtml.xpath('//div[@class="t_con cleafix"]/div/div/div/a/@href')
                  # t_list : ['/p/233432','/p/2039820',..]
                  #print(t_list)
                  for t_link in t_list:
                      # 拼接帖子完整链接
                      t_link = self.baseurl + t_link
                      self.getImageUrl(t_link)
              
              # 获取帖子中图片URL列表
              def getImageUrl(self,t_link):
                  res = requests.get(t_link,headers=self.headers)
                  res.encoding = "utf-8"
                  html = res.text
                  # 构造解析对象
                  parseHtml = etree.HTML(html)
                  img_list = parseHtml.xpath('//img[@class="BDE_Image"]/@src')
                #  print(img_list)
                  for img_link in img_list:
                      self.writeImage(img_link)
              
              # 保存到本地
              def writeImage(self,img_link):
                  # 获取图片的bytes
                  res = requests.get(img_link,headers=self.headers)
                  res.encoding = "utf-8"
                  html = res.content
                  # filename
                  filename = img_link[-12:]
                  with open(filename,"wb") as f:
                      f.write(html)
                      print("%s下载成功" % filename)
              
              # 主函数
              def workOn(self):
                  name = input("请输入贴吧名:")
                  begin = int(input("请输入起始页:"))
                  end = int(input("请输入终止页:"))
                  
                  for n in range(begin,end+1):
                      pn = (n-1)*50
                      params = {
                              "kw":name,
                              "pn":str(pn)
                          }
                      self.getPageUrl(params)
                      
          if __name__ == "__main__":
              spider = BaiduImageSpider()
              spider.workOn()
    6. 案例2:嗅事百科 - xpath
      1. 目标:用户名称
      2. 步骤
        1. 找URL
          https://www.qiushibaike.com/8hr/page/1/
        2. xpath匹配
          1. 基准xpath://div[contains(@id,"qiushi_tag_")]
            用户昵称:./div/a/h2
            段子内容:.//div[@class="content"]/span
            好笑数量:.//i
            评论数量:.//i
      3. 写代码:
        '''03_糗事百科案例.py'''
        import requests
        from lxml import etree
        import pymongo
        
        class QiuShiSpider:
            def __init__(self):
                self.url = "https://www.qiushibaike.com/8hr/page/1/"
                self.headers = {"User-Agent":"Mozilla/5.0"}
                self.conn = pymongo.MongoClient("localhost",27017)
                self.db = self.conn.Baikedb
                self.myset = self.db.baikeset
                
            def getPage(self):
                res = requests.get(self.url,headers=self.headers)
                res.encoding = "utf-8"
                html = res.text
                self.parsePage(html)
            
            def parsePage(self,html):
                parseHtml = etree.HTML(html)
                # 基准xpath,每个段子的列表
                base_list = parseHtml.xpath('//div[contains(@id,"qiushi_tag_")]')
                # 遍历每个段子的节点对象(base)
                for base in base_list:
                    # 用户昵称
                    username = base.xpath('./div/a/h2')
                    if len(username) == 0:
                        username = "匿名用户"
                    else:
                        username = username[0].text
                    # 段子内容
                    content = base.xpath('.//div[@class="content"]/span')[0].text
                    # 好笑数量
                    # [<element.好笑数量>,<eleme.评论>,<element...>]
                    laughNum = base.xpath('.//i')[0].text 
                    # 评论数量
                    pingNum = base.xpath('.//i')[1].text
                    
                    d = {
                          "username":username.strip(),
                          "content":content.strip(),
                          "laughNum":laughNum.strip(),
                          "pingNum":pingNum.strip()
                      }
                    self.myset.insert(d)
                    print("存入数据库成功")
        
        if __name__ == "__main__":
            spider = QiuShiSpider()
            spider.getPage()

3.动态网站数据抓取

  1. Ajax动态加载
    1. 特点:滚动鼠标滑轮时加载
    2. 抓包工具:查询参数在 WebForms - QueryString

今日示例

猜你喜欢

转载自blog.csdn.net/qq_42584444/article/details/83443281
今日推荐