整合營銷服務商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          57個挑戰(zhàn)之57(part6):客戶端+web前端+

          57個挑戰(zhàn)之57(part6):客戶端+web前端+服務端代碼實現(xiàn)

          題目:

          接前面:

          https://www.toutiao.com/article/7131944951776150056/

          https://www.toutiao.com/article/7129048315920335399/

          https://www.toutiao.com/article/7128604966595920414/

          https://www.toutiao.com/article/7128196832081183236/

          上一篇:

          https://www.toutiao.com/article/7133396498141954595/

          上面設計好邏輯之后,主要做代碼實現(xiàn):

          代碼:57-57clientsidev5.py

          import requests
          import random
          import time
          from flask import Flask,request,render_template,url_for,redirect
          import redis
          from redis import StrictRedis,ConnectionPool
          import json
          app=Flask(__name__)
          
          
          
          def get_data():
              """
              函數(shù)作用:從服務端讀入題庫,以JSON格式返回
              輸入:無
              返回:從服務端題庫隨機讀取10個題目,并返回
              """
              print("start process get_data")
              url="http://127.0.0.1:8008/get"
              ret=requests.post(url)
              dic1=ret.json()
              print("end process get_data")
              return dic1
          
          
          def orderlize(questionlist):
              """
              函數(shù)作用:讀入列表,并把列表做處理,按照列表中每個字典的‘R’(難度) 大小排序。
              輸入:問題list列表
              返回:根據(jù)'R‘排序后的問題列表
              """
              print("start process orderlize")
              print("列表通過難度值進行排序")
              sortedlist=sorted(questionlist,key=lambda i : i['R'])
              print(sortedlist)
              print("end process orderlize")
              return sortedlist
          
          
          def randomlize_input(dic1):
              """
              函數(shù)作用:輸入問題,對這個問題里面的答案和干擾項目做隨機化,并返回給展示界面,包含問題、正確答案、隨機化的答案+干擾項目
              輸入:問題list 列表中的每一個對象(字典對象)
              輸出:返回這個字典
              """
              list1=[dic1['A'], dic1['D1'], dic1['D2'], dic1['D3']]
              listrandom=random.sample(list1,4)
              return dic1['Q'],dic1['A'],listrandom
          
          
          @app.route('/',methods=['GET','POST'])
          def start_html():
              """
              1.get請求打開首頁,選擇開始答題。
                介紹規(guī)則,選擇10道題,然后從容易往復雜進行答復,如果答題錯誤則結(jié)束。
              2.post請求 展示開始答題
                跳轉(zhuǎn)到函數(shù)答題
              """
              #邏輯1:點擊開始答題,讀取題庫信息
          
              if request.method=="POST": #這里是web端提交了開始答題,
                 name=request.form["name"]
                 print("考生名字:{0}".format(name))
                 timetitle=time.strftime("%Y-%m-%d-%H:%M:%S", time.localtime())
                 print("時間:{0}".format(timetitle))
                 token=hash(name+timetitle) #根據(jù)考生名字和時間產(chǎn)生考號token
                 print(token)
                 count=0  #因為是第一次答題,count 初始化為0
                 return redirect(url_for('start_question',token=token,count=0))
          
          
              if request.method=="GET":
                 #1.展示首頁,展示"開始答題"
                 #1.1 點擊開始答題發(fā)送請求到后端開始答題
                 return render_template('index57.html')
          
          
          @app.route('/question',methods=['GET','POST'])
          def start_question():
              if request.method=="POST": #其實這個邏輯沒有太多變化。
                 totalcorrectquestion=request.json["count"]
                 info="total answered correct question is {0}".format(totalcorrectquestion)
                 print(info)
                 #2.1 接收用戶選擇,
                 return render_template('finish.html',info=info)
          
              if request.method=="GET":
                 # 接收傳入的數(shù)據(jù),count 及 token,并基于token在redis池中讀取數(shù)據(jù)。
                 # 當count 為0的時候,把數(shù)據(jù)緩存到redis池中。
                 # 當count 為1的時候,把數(shù)據(jù)從redis池中取出。
                 valueargs=request.args 
                 print(valueargs) #debug
                 count=int(valueargs.get('count'))
                 token=valueargs.get('token')
                 print("we have received 'count', value is {0}".format(count))
                 pool=ConnectionPool(host='localhost', port=6379, db=0, decode_responses=True) #連接本地數(shù)據(jù)庫
                 r=StrictRedis(connection_pool=pool) #進入連接池
                 #如果count為0,調(diào)用get_data()函數(shù),并緩存數(shù)據(jù)到本地redis,
                 #讀出列表中第一個數(shù)據(jù),并展示到web端
                 if  count==0: 
                     print("initialize")
                     dic1=get_data() #調(diào)用get_data()函數(shù)
                     print(dic1) #debug
                     questionlist=dic1['data'] #緩存返回的list數(shù)據(jù)
                     sortedlist=orderlize(questionlist)  #把返回的list數(shù)據(jù)做排序
                     print(sortedlist) #debug 展示排序后的數(shù)據(jù)
                     r.hset("Qlib",token,json.dumps(sortedlist))#把排序后的數(shù)據(jù),sortedlist存儲到本地redis
                     Q, A, listrandom=randomlize_input(sortedlist[count])  # 取出第count道題,并做排序
                     print("it's {0} round,the question is {1} and the answer is {2}".format(count, Q, A))
                     return render_template('start_question7.html', Q=Q, A=A, listrandom=listrandom, count=count, token=token) #如果count為0,表示初始化,這個時候傳遞列表第一個元素到客戶端。
                  #如果count為不為0,從本地redis讀取緩存的數(shù)據(jù)
                  #取列表中第count 個數(shù)據(jù),并展示到前端
                  else: #如果count不為0,則進入下一個邏輯
                     sorted_list_json=r.hget("Qlib", token) #從本地內(nèi)存中讀取數(shù)據(jù)
                     sortedlist=json.loads(sorted_list_json) #把數(shù)據(jù)存儲起來,
                     print("come to next question") #跳到下一個問題
                     print(sortedlist)
                     print(len(sortedlist))
                     #從本地讀取sortedlist到內(nèi)存
                     if  int(count)<len(sortedlist): #如果count的長度比sortedlist要短,則執(zhí)行取題的操作
                         print(count)
                         Q, A, listrandom=randomlize_input(sortedlist[count])  # 取出第count道題,并做排序
                     if int(count)==len(sortedlist): #表示所有題目已經(jīng)做完了,而且都正確了
                         info="Congratulations, user {0} has finished all the question".format(token)
                         print(info)
                         return render_template('finish.html',info=info)
                     print("it's {0} round,the question is {1} and the answer is {2}".format(count, Q, A))
                     return render_template('start_question7.html', Q=Q, A=A, listrandom=listrandom, count=count, token=token) #取出題目,并發(fā)送到web端
          
          
          
          @app.route('/statistic',methods=['GET','POST'])
          def take_account():
              # 當?shù)竭@個界面,表示沒有完全做完,這里做個統(tǒng)計即可,表示做完幾道題。
              valueargs=request.args
              print(valueargs)  # debug
              count=int(valueargs.get('count'))
              token=valueargs.get('token')
              info="token {0} : total answered correct question is {1}".format(token,count)
              return render_template('finish.html',info=info)
          
          
          
          if __name__=='__main__':
              app.run(host='0.0.0.0',port=80,debug=True)
          
          
          
          

          幾個比較難理解的拿出來單獨說一下:

          • sortedlist=sorted(questionlist,key=lambda i : i['R'])

          這里表示從questionlist 列表中取出每個元素(是字典元素),并按照字典元素中的['R']進行排序,

          • listrandom=random.sample(list1,4)

          • return redirect(url_for('start_question',token=token,count=0))

          函數(shù)內(nèi)部跳轉(zhuǎn),跳轉(zhuǎn)到start_question 函數(shù),且?guī)蟽蓚€參數(shù),toke 和count。

          web 端程序:start_question7.html

          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>start_question7.html</title>
              <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
          </head>
          <body>
          
          問題是:<div id="q"> </div>
          <form action="">
             <input type="radio" name="sex" value="0"   id="a1"> <label for="a1" id="c1" onclick="doPost(0)">Huey</label><br>
             <input type="radio" name="sex" value="1"   id="a2"> <label for="a2" id="c2" onclick="doPost(1)">Huey</label><br>
             <input type="radio" name="sex" value="2"   id="a3"> <label for="a3" id="c3" onclick="doPost(2)">Huey</label><br>
             <input type="radio" name="sex" value="3"   id="a4"> <label for="a4" id="c4" onclick="doPost(3)">Huey</label><br>
          </form>
          
          <script>
              function myFunction(){
              if("undefined"==typeof list1) //如果未定義,字符串取數(shù)值
             { var list1={{listrandom|tojson}};}
             if("undefined"==typeof question) //如果未定義,問題取數(shù)值
             { var question={{Q|tojson}};}
             console.log("come to myFunction()");
             console.log("The question is "+question)
             document.getElementById("q").innerHTML=question+"()";
             document.getElementById("c1").innerHTML=list1[0];
             document.getElementById("c2").innerHTML=list1[1];
             document.getElementById("c3").innerHTML=list1[2];
             document.getElementById("c4").innerHTML=list1[3];
              }
              window.onload=myFunction();
          
              function doPost(idnumber){
              console.log("come to collect info first");
              var count={{count|tojson}};
              var list1={{listrandom|tojson}};
              var correct={{A|tojson}}
              var tokenid={{token|tojson}}
              var answer=list1[idnumber];
              console.log("come to doPost() function");
              console.log("The choice is "+answer);
              console.log("The correct answer is "+ correct);
              console.log("Your token id is " + tokenid);
              console.log("The count now is "+ count);
          
              if (answer==correct)//如果答案正確,則跳轉(zhuǎn)到URL2,傳遞token,以及count+1
                 {
                   var count=count+1;
                   url="http://127.0.0.1/question";
                   url2=url+"?token="+tokenid+"&count="+count;
                   $.ajax({
                    type:"GET",
                  url:url,
                  data:{"count":count,"token":tokenid},
                  async:false,
                  contentType:"application/json",
                  success:function(data)
                  {
                   window.location.href=url2;
                  }
                   })
                 }
               if(answer !=correct) //如果答案是錯誤的,則到統(tǒng)計界面,傳遞token及count
                      {
                        var jsondoc={"count":count};
                        url="http://127.0.0.1/question";
                        url2="http://127.0.0.1/statistic"+"?token="+tokenid+"&count="+count;
                       $.ajax({
                       type:"POST",
                       url:url,
                       async:false,
                       contentType:"application/json",
                       data:JSON.stringify(jsondoc),
                       success:function()
                        {
                         window.location.href=url2;
                        }
                       });
                       }
          
          
              }
          
          
          
          </script>
          </body>
          </html>


          解釋下面的一段JS腳本:

          1. 先通過 list1={{ listrandom|tojson}} 收集客戶端傳遞來的數(shù)據(jù)

          if("undefined"==typeof list1) //如果未定義,字符串取數(shù)值

          { var list1={{listrandom|tojson}};}

          if("undefined"==typeof question) //如果未定義,問題取數(shù)值

          { var question={{Q|tojson}};}

          2.再通過document.getElementById("c1").innerHTML=list1[2]

          來把數(shù)據(jù)展示到前端。

          3.這里 window.onload=myFunction()

          表示打開頁面后自動調(diào)用這個函數(shù)。

          function myFunction(){
          if("undefined"==typeof list1) //如果未定義,字符串取數(shù)值
          { var list1={{listrandom|tojson}};}
          if("undefined"==typeof question) //如果未定義,問題取數(shù)值
          { var question={{Q|tojson}};}
          console.log("come to myFunction()");
          console.log("The question is "+question)
          document.getElementById("q").innerHTML=question+"()";
          document.getElementById("c1").innerHTML=list1[0];
          document.getElementById("c2").innerHTML=list1[1];
          document.getElementById("c3").innerHTML=list1[2];
          document.getElementById("c4").innerHTML=list1[3];
          }
          window.onload=myFunction();


          解釋下面的一段代碼;

          • 首先onclick=doPost(0) 表示在label 上點擊鼠標后,會調(diào)度doPost()函數(shù),且入?yún)?,
          • doPost(1),doPost(2),doPost(3) 一樣,分別入?yún)?,2,3。
          • 進入doPost(idnumber)函數(shù),
          1. var answer=list1[idnumber], 選擇答案。
          2. correct 為服務端傳來的正確答案 correct={{A|tojson}}
          3. 最后判斷用戶的選擇 answer 和 實際答案 corret是否一致。

          如果一致,表示用戶選擇正確的答案,則跳到下一道題,

          否則直接統(tǒng)計。


          <form action="">
          <input type="radio" name="sex" value="0" id="a1"> <label for="a1" id="c1" onclick="doPost(0)">Huey</label><br>
          <input type="radio" name="sex" value="1" id="a2"> <label for="a2" id="c2" onclick="doPost(1)">Huey</label><br>
          <input type="radio" name="sex" value="2" id="a3"> <label for="a3" id="c3" onclick="doPost(2)">Huey</label><br>
          <input type="radio" name="sex" value="3" id="a4"> <label for="a4" id="c4" onclick="doPost(3)">Huey</label><br>
          </form>
          function doPost(idnumber){
          console.log("come to collect info first");
          var count={{count|tojson}};
          var list1={{listrandom|tojson}};
          var correct={{A|tojson}}
          var tokenid={{token|tojson}}
          var answer=list1[idnumber];
          console.log("come to doPost() function");
          console.log("The choice is "+answer);
          console.log("The correct answer is "+ correct);
          console.log("Your token id is " + tokenid);
          console.log("The count now is "+ count);
          if (answer==correct)//如果答案正確,則跳轉(zhuǎn)到URL2,傳遞token,以及count+1
          {
          var count=count+1;
          url="http://127.0.0.1/question";
          url2=url+"?token="+tokenid+"&count="+count;
          $.ajax({
          type:"GET",
          url:url,
          data:{"count":count,"token":tokenid},
          async:false,
          contentType:"application/json",
          success:function(data)
          {
          window.location.href=url2;
          }
          })
          }
          if(answer !=correct) //如果答案是錯誤的,則到統(tǒng)計界面,傳遞token及count
          {
          var jsondoc={"count":count};
          url="http://127.0.0.1/question";
          url2="http://127.0.0.1/statistic"+"?token="+tokenid+"&count="+count;
          $.ajax({
          type:"POST",
          url:url,
          async:false,
          contentType:"application/json",
          data:JSON.stringify(jsondoc),
          success:function()
          {
          window.location.href=url2;
          }
          });
          }
          }


          index57.html

          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>57-index</title>
          </head>
          <body>
          
          <p>注意,一共10道題,逐題做答復,如果答題成功,則進入下一道題,只到結(jié)束。</p>
          <p>如果答復失敗,則直接退出。并統(tǒng)計所有答復正確的題數(shù)。</p>
          
          <form method="post">
              <input type="text" name="name" value="請輸入姓名">
              <input type="submit" name="submit" value="開始答題">
          </form>
          
          
          </body>
          </html>

          finish.html

          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>finish.html</title>
          </head>
          <body>
          
          {{info}}
          </body>
          </html>

          57-serversidev3.py

          import copy
          import flask,pymongo
          from flask import Flask,jsonify,request
          
          app=Flask(__name__)
          
          
          def insert_mongo(list1):
              myclient=pymongo.MongoClient('mongodb://127.0.0.1:27017/')
              mydb=myclient.client["lukedb5"]
              mycol=mydb["site"]
              x=mycol.insert_many(list1)
              print(x.inserted_ids)
              return "success"
          
          
          def get_mongo():
              myclient=pymongo.MongoClient('mongodb://127.0.0.1:27017/')
              mydb=myclient.client["lukedb5"]
              mycol=mydb["site"]
              list2=[]
              for x in mycol.aggregate([{'$sample':{'size':10}}]):
                  del x['_id'] #把id項目刪除
                  list2.append(x)
              print(list2)
              return list2,"success"
          
          def getall_mongo():
              myclient=pymongo.MongoClient('mongodb://127.0.0.1:27017/')
              mydb=myclient.client["lukedb5"]
              mycol=mydb["site"]
              list3=[]
              for x in mycol.find({},{"_id":0}):#把id項目刪除
                  list3.append(x)
              print(list3)
              return list3,"success"
          
          
          def update_mongo(listold,listnew):
              myclient=pymongo.MongoClient('mongodb://127.0.0.1:27017/')
              mydb=myclient.client["lukedb5"]
              mycol=mydb["site"]
              for x in range(0,len(listold)):#把id項目刪除
                  myquery=listold[x]
                  newvalues={"$set":listnew[x]}
                  mycol.update_one(myquery,newvalues)
              return "success"
          
          @app.route('/')
          def hello_world():
              return 'Hello World!'
          
          
          @app.route('/get',methods=['POST'])
          def get():
          #調(diào)用查詢邏輯
              #獲取題目10個
              #獲取難度3個容易,5個中等,2個難題
              list2,info=get_mongo()
              return jsonify({"info":info,"data":list2})
          
          @app.route('/append',methods=['GET','POST'])
          def append():
          #調(diào)用插入邏輯
              list1=request.json["list"]
              #dic1={"Q":"How old is Republic of China1","A":"73","D1":"72","D2":"74","D3":"111"}
              #list1=[dic1]
              list2=copy.deepcopy(list1)
              info=insert_mongo(list1)
              #print(info)
              #print(dic1)
              #print(list2)
              return jsonify({"info":info,"data":list2})
          
          @app.route('/getall', methods=['POST'])
          def getall():
          # 調(diào)用抽取接口,把題庫數(shù)據(jù)讀出來
              list3,info=getall_mongo()
              return jsonify({"whole question lib is":list3,"info":info})
          
          @app.route('/update', methods=['POST'])
          def update():
          # 調(diào)用update 接口,修改題目
              listold=request.json["listold"]
              listnew=request.json["listnew"]
              info=update_mongo(listold,listnew)
              return jsonify({"info": info,"oldinfo":listold,"newinfo":listnew})
          
          
          if __name__=='__main__':
              app.run(host='0.0.0.0',port=8008,debug=True)

          效果圖:


          前端的日志:


          編輯題庫的邏輯應該差不多,這里不想重復了。

          大體方法也是,先編寫邏輯,基于邏輯編寫實現(xiàn)代碼。

          類似這樣:編寫邏輯

          邏輯實現(xiàn)后,直接做代碼實現(xiàn)即可。

          這兩天有點卡在這個題目上了,還好今天close掉了。。

          、前言

          在使用爬蟲的時候,很多網(wǎng)站都有一定的反爬措施,甚至在爬取大量的數(shù)據(jù)或者頻繁地訪問該網(wǎng)站多次時還可能面臨ip被禁,所以這個時候我們通常就可以找一些代理ip,和不用的瀏覽器來繼續(xù)爬蟲測試。下面就開始來簡單地介紹一下User-Agent池和免費代理ip池。

          二、User-Agent池

          User-Agent 就是用戶代理,又叫報頭,是一串字符串,相當于瀏覽器的身份證號,我們在利用python發(fā)送請求的時候,默認為: python-requests/2.22.0,所以我們在利用爬蟲爬取網(wǎng)站數(shù)據(jù)時,頻繁更換它可以避免觸發(fā)相應的反爬機制。

          構(gòu)建User-Agent池,這里介紹兩種方法:1,手動構(gòu)造隨機函數(shù)。2,第三方庫fake-useragent

          方法1:構(gòu)造隨機函數(shù)

          自己手動編寫User-Agent池,然后隨機獲取其中一個就行了。

          def get_ua():
              import random
              user_agents=[
                  'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60',
          		'Opera/8.0 (Windows NT 5.1; U; en)',
          		'Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50',
          		'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50',
          		'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0',
          		'Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10',
          		'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2 ',
          		'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36',
          		'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
          		'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16',
          		'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36',
          		'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko',
          		'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11',
          		'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER',
          		'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)',
          		'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 SE 2.X MetaSr 1.0',
          		'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; SE 2.X MetaSr 1.0) ',
              ]
              user_agent=random.choice(user_agents) # 隨機抽取對象
              return user_agent
          
          # 調(diào)用
          get_ua()

          至于,在哪里找這些瀏覽器,網(wǎng)上一大堆,復制過來即可。

          實際環(huán)境調(diào)用隨機User-Agent池

          import requests
          
          def get_page(url):
              ua=get_ua()
              headers={'User-Agent': ua}
              response=requests.get(url=url, headers=headers)
              print(response.text)
          
          if __name__=='__main__':
              get_page('https://www.baidu.com')


          方法2: fake-useragent 庫自動生成

          注: 此庫在2018年已經(jīng)停止更新,版本目前停止在0.1.11,所以生成的瀏覽器版本都比較低。如果有網(wǎng)站檢測瀏覽器版本號大小(范圍)的話,就可能會被檢測到。

          安裝:

          pip install fake-useragent

          調(diào)用第三方庫,生成指定瀏覽器的user-agent

          from fake_useragent import UserAgent
          ua=UserAgent()
          
          ua.ie
          # Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US);
          ua.msie
          # Mozilla/5.0 (compatible; MSIE 10.0; Macintosh; Intel Mac OS X 10_7_3; Trident/6.0)'
          ua['Internet Explorer']
          # Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.4; InfoPath.2; SV1; .NET CLR 3.3.69573; WOW64; en-US)
          ua.opera
          # Opera/9.80 (X11; Linux i686; U; ru) Presto/2.8.131 Version/11.11
          ua.chrome
          # Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.2 (KHTML, like Gecko) Chrome/22.0.1216.0 Safari/537.2'
          ua.google
          # Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/537.13 (KHTML, like Gecko) Chrome/24.0.1290.1 Safari/537.13
          ua['google chrome']
          # Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11
          ua.firefox
          # Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:16.0.1) Gecko/20121011 Firefox/16.0.1
          ua.ff
          # Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:15.0) Gecko/20100101 Firefox/15.0.1
          ua.safari
          # Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25
          
          # and the best one, random via real world browser usage statistic
          ua.random


          官方文檔:https://fake-useragent.readthedocs.io/en/latest/

          實際示例代碼:

          from fake_useragent import UserAgent
          import requests
          
          ua=UserAgent()
          #請求的網(wǎng)址
          url="http://www.baidu.com"
          #請求頭
          headers={"User-Agent":ua.random}
          #請求網(wǎng)址
          response=requests.get(url=url,headers=headers)
          #響應體內(nèi)容
          print(response.text)
          #響應狀態(tài)信息
          print(response.status_code)
          #響應頭信息
          print(response.headers)


          三、IP代理池

          開源IP代理池,這里推薦兩個:

          https://github.com/Python3WebSpider/ProxyPool

          https://github.com/jhao104/proxy_pool

          這里用第二個測試,使用人數(shù)更多,而且一直在更新。

          1:下載啟動

          Linux下載

          git clone git@github.com:jhao104/proxy_pool.git
          #或者
          git clone https://github.com/jhao104/proxy_pool.git

          使用docker compose啟動

          #進入目錄
          cd proxy_pool/
          #啟動代理池
          docker compose up -d

          啟動web服務后, 默認配置下會開啟 http://127.0.0.1:5010 的api接口服務:

          api:

          • /get :GET, 隨機獲取一個代理 ,可選參數(shù): ?type=https 過濾支持https的代理
          • /pop :GET, 獲取并刪除一個代理, 可選參數(shù): ?type=https 過濾支持https的代理
          • /all :GET, 獲取所有代理 ,可選參數(shù): ?type=https 過濾支持https的代理
          • /count :GET, 查看代理數(shù)量,
          • /delete :GET, 刪除代理, ?proxy=host:ip

          訪問瀏覽器測試,我這里IP,192.168.152.100

          2:爬蟲使用

          如果要在爬蟲代碼中使用的話, 可以將此api封裝成函數(shù)直接使用,例如

          import requests
          
          def get_proxy():
              return requests.get("http://127.0.0.1:5010/get/").json()
          
          def delete_proxy(proxy):
              requests.get("http://127.0.0.1:5010/delete/?proxy={}".format(proxy))
          
          # your spider code
          
          def getHtml():
              # ....
              retry_count=5
              proxy=get_proxy().get("proxy")
              while retry_count > 0:
                  try:
                      html=requests.get('http://www.example.com', proxies={"http": "http://{}".format(proxy)})
                      # 使用代理訪問
                      return html
                  except Exception:
                      retry_count -=1
              # 刪除代理池中代理
              delete_proxy(proxy)
              return None

          更多使用方法,參考官方文檔:https://proxy-pool.readthedocs.io/zh/latest/

          以上是基本使用方法,都是免費的,質(zhì)量有限,如需要付費的。

          付費代理推薦: luminati-china. 國外的亮數(shù)據(jù)BrightData(以前叫l(wèi)uminati)被認為是代理市場領導者,覆蓋全球的7200萬IP,大部分是真人住宅IP,成功率扛扛的。

          分享成果,隨喜正能量】人生,有多少計較,就有多少痛苦。有多少寬容,就有多少歡樂。痛苦與歡樂都是心靈的折射,就像鏡子里面有什么,決定于鏡子面前的事物。心里放不下,自然成了負擔,負擔越多,人生越不快樂。計較的心如同口袋,寬容的心猶如漏斗。復雜的心愛計較,簡單的心易快樂。

          《VBA信息獲取與處理》教程是我推出第六套教程,目前已經(jīng)是第一版修訂了。這套教程定位于最高級,是學完初級,中級后的教程。這部教程給大家講解的內(nèi)容有:跨應用程序信息獲得、隨機信息的利用、電子郵件的發(fā)送、VBA互聯(lián)網(wǎng)數(shù)據(jù)抓取、VBA延時操作,剪貼板應用、Split函數(shù)擴展、工作表信息與其他應用交互,F(xiàn)SO對象的利用、工作表及文件夾信息的獲取、圖形信息的獲取以及定制工作表信息函數(shù)等等內(nèi)容。程序文件通過32位和64位兩種OFFICE系統(tǒng)測試。是非常抽象的,更具研究的價值。

          教程共兩冊,八十四講。今日的內(nèi)容是專題八“VBA與HTML文檔”的第二節(jié)上半部分:HTML文檔元素

          第二節(jié) HTML文檔的元素分析之一

          大家好,我們這講開始HTML的講解,為了認識這種特殊的語言,我們要先看看這種語言中的各種元素個代表什么意義。上節(jié)中在講這種語言的特征時講過,標簽是用來描述網(wǎng)頁的。瀏覽器讀取HTML文檔,識別標簽,并按標簽要求以網(wǎng)頁進行顯示文本。大部分標簽都是成隊出現(xiàn)的。

          起始標簽和結(jié)束標簽之間的所有文本,都叫做元素。也就是這個格式就是:

          <起始標簽:也叫元素名>元素的內(nèi)容<結(jié)束標簽:/+元素名>

          標簽是可以擁有屬性的,屬性提供了元素的一些附加信息,起始標簽,有時候格式如下:

          <元素名 屬性名稱=”屬性值”>

          同時,元素是可以擁有元素的,即某個元素的內(nèi)容有時候是一個子元素。

          元素這東西,比較抽象,我們可以把它且當作一個對象來理解,例如工作簿對象,每個工作簿的名稱都不一樣(屬性),每個工作簿里面都有工作表(子元素),每個表都有名稱(屬性),里面填寫的內(nèi)容也不一樣(元素的內(nèi)容)。

          1 HTML文檔構(gòu)成的整體框架結(jié)構(gòu)

          在上一講中我們舉了一個最為簡單的實例來說明HTML文檔:

          <html>

          <body>

          <h1>學習VBA語言</h1>

          <p>為了更好的掌握VBA的各個知識點,您可以參考我的第一套教程:VBA代碼解決方案</p>

          </body>

          </html>

          我們將上面的格式修正一下,如下面:

          <html>

          <head> <!--注釋:文檔頭部,文檔相關消息,并不提供文檔內(nèi)容-->

          <title>

          VBA應用提高篇

          </title>

          </head>

          <body> <!--注釋:文檔主體-->

          <h1>學習VBA語言</h1>

          <p>為了更好的掌握VBA的各個知識點,您可以先參考我的第一套教程:VBA代碼解決方案</p>

          </body>

          </html>

          將上面的內(nèi)容寫入記事本中保存為.html文件:HTML基礎學習-1.html

          然后我們雙擊打開這個文件,看看瀏覽器的翻譯效果:

          我們再看看網(wǎng)頁的源碼:

          從上面的框架代碼,我們可以看出,一般的頁面,都有html元素,其一般內(nèi)含兩個元素,一個是head元素,一個是body元素。Head元素僅僅說明文檔的相關消息,并不展示文檔實體,body元素才是真正展示文檔主體的,所有要在頁面展示的元素,都要在body內(nèi)進行書寫。

          2 HTML文檔常用元素的構(gòu)成

          1)HTML標題 <h1> - <h6>

          標題(Heading)是通過 <h1> - <h6> 等標簽進行定義的。<h1> 定義最大的標題。<h6> 定義最小的標題。瀏覽器會自動地在標題的前后添加空行。標題很重要,將 HTML heading 標簽只用于標題。不要僅僅是為了產(chǎn)生粗體或大號的文本而使用標題。因為用戶可以通過標題來快速瀏覽您的網(wǎng)頁,所以用標題來呈現(xiàn)文檔結(jié)構(gòu)是很重要的。應該將 h1 用作主標題(最重要的),其后是 h2(次重要的),再其次是 h3,以此類推。在HTML基礎學習.HTML文件中我們已經(jīng)用到了標題的元素

          2)HTML水平線 <hr />

          <hr /> 標簽在 HTML 頁面中創(chuàng)建水平線。可用于分隔內(nèi)容。

          [待續(xù)]

          本節(jié)參考文件:HTML基礎學習-1.html;HTML基礎學習-2.html

          我20多年的VBA實踐經(jīng)驗,全部濃縮在下面的各個教程中,教程學習順序:

          【分享成果,隨喜正能量】人生,一歲有一歲的味道,一站有一站的風景,你的年齡應該成為你生命的勛章而不是你傷感的理由。 ??


          主站蜘蛛池模板: 国产伦精品一区二区三区| 男人的天堂精品国产一区| 亚洲码欧美码一区二区三区 | 国产精品视频一区二区噜噜 | 国产主播福利精品一区二区| 中文字幕人妻无码一区二区三区 | 无码精品人妻一区二区三区免费| 国产精品一区二区久久精品| 国产精品区一区二区三在线播放| 国产日韩精品一区二区在线观看| 国产成人午夜精品一区二区三区 | 一区二区三区精品高清视频免费在线播放| 亚洲综合一区二区精品导航| 国产激情一区二区三区 | 国产激情一区二区三区| 久久精品国产一区二区三| 人妻无码一区二区三区免费| 亚洲一区综合在线播放| 在线观看国产区亚洲一区成人 | 色视频综合无码一区二区三区 | 在线播放国产一区二区三区 | 久久久久人妻一区二区三区vr| 麻豆一区二区三区精品视频| 久久精品国内一区二区三区| 大帝AV在线一区二区三区| 成人免费一区二区无码视频| 一区二区高清在线| 久草新视频一区二区三区| 日韩视频一区二区在线观看| 搜日本一区二区三区免费高清视频| 亚洲日韩激情无码一区| 亚洲一区二区三区久久| 亚洲高清一区二区三区电影| 国产未成女一区二区三区| 国产在线视频一区| av一区二区三区人妻少妇| 精品亚洲AV无码一区二区| 精品国产一区二区三区香蕉事| 欧洲亚洲综合一区二区三区| 日韩AV无码久久一区二区| 亚洲综合无码一区二区|