Android 小項目之标准体重测量仪:Bundle对象的实现

其实就只是一个Activity跳转页面然后接收值做处理的例子而已。
  废话不多说,直接进入正题。
  首先我们利用网友用JAVA编写的基于android的可视化GUI布局拖拉工具程序 –DroidDraw。布局以下界面:
此页面位于res/layout/main.xml。
制作接收值页面,页面如下:

%title插图%num
此页面位于res/layout/mainlayout.xml,到此为止准备工作全部做好了,接下来正式进入 我们的代码实现功能。。
  主页面代码位于src/cn.terry/BundleObject.java
  代码如下:
  1. import android.app.Activity;
  2. import android.app.AlertDialog;
  3. import android.os.Bundle;
  4. import android.view.View;
  5. import android.view.View.OnClickListener;
  6. import android.widget.*;
  7. import android.content.DialogInterface;
  8. import android.content.Intent;
  9. import android.graphics.Color;
  10. public class BundleObject extends Activity {
  11. private Button mButton;
  12. private EditText mEditText;
  13. private RadioGroup mRadioGroup;
  14. private double height;
  15. private String Sex;
  16. /** Called when the activity is first created. */
  17. @Override
  18. public void onCreate(Bundle savedInstanceState) {
  19. super.onCreate(savedInstanceState);
  20. setContentView(R.layout.main);
  21. mButton=(Button)findViewById(R.id.confirm);
  22. mButton.setOnClickListener(new OnClickListener() {
  23. @Override
  24. public void onClick(View v) {
  25. // TODO Auto-generated method stub
  26. mEditText=(EditText)findViewById(R.id.heigt);
  27. if(mEditText.getText().toString().length()==0)
  28. {
  29. /* AlertDialog builder = new AlertDialog.Builder(BundleObject.this).create();
  30. builder.setTitle(“提示”);
  31. builder.setMessage(“請輸入您的身高!!”);
  32. builder.show();*/
  33. new AlertDialog.Builder(BundleObject.this)
  34. .setMessage(“请輸入您的身高”)
  35. .setTitle(“提示”)
  36. .setNeutralButton(“确定”,new DialogInterface.OnClickListener() {
  37. @Override
  38. public void onClick(DialogInterface dialog, int which) {
  39. // TODO Auto-generated method stub
  40. mEditText.setHighlightColor(Color.RED);
  41. }
  42. }).create()
  43. .show();
  44. return;
  45. }
  46. mRadioGroup=(RadioGroup)findViewById(R.id.sex);
  47. height=Double.parseDouble(mEditText.getText().toString());
  48. if(mRadioGroup.getCheckedRadioButtonId()==R.id.M)
  49. {
  50. Sex=”M”;
  51. }
  52. else
  53. {
  54. Sex=”F”;
  55. }
  56. Intent intent=new Intent();
  57. intent.setClass(BundleObject.this, Next.class);
  58. Bundle bun=new Bundle();
  59. bun.putDouble(“Height”, height);
  60. bun.putString(“Sex”, Sex);
  61. intent.putExtras(bun);
  62. startActivity(intent);
  63. BundleObject.this.finish();
  64. }
  65. });
  66. }
  67. }

在此有一点想让大家注意的是:弹出对话框的时候AlertDialog.Builder()这个方法在1.5以上都要加上类名.this 比如 我的页面的名字叫BundleObject.java就必须如下写下

  1. AlertDialog.Builder(BundleObject.this)

复制代码

1.5以下的版本直接this即可。。 到此为止己经完成了一半的功能了,那么在Acitivity2(Next.java)要如何接收来自Activity1(BundleObject.java)传递过来的数据呢?试想,在Activity1是以Bundle封装对象,自然在Activity2亦是以Bundle的方式来解开封装的数据咯;程序中以

  1. Bundle bun=this.getIntent().getExtras();

这样的方法来取得Bundle对象传递过来的性别与身高,经过计算之后,显示在屏幕上。废话到此为止,第二个页面的处理程序如下:

  1. import java.text.DecimalFormat;
  2. import java.text.NumberFormat;
  3. import android.content.Intent;
  4. import android.app.Activity;
  5. import android.os.Bundle;
  6. import android.view.View;
  7. import android.view.View.OnClickListener;
  8. import android.widget.*;
  9. public class Next extends Activity {
  10. private TextView mTextView01;
  11. private TextView mTextView02;
  12. private Button mButton1;
  13. private String Sex;
  14. private double Height;
  15. private String SextText;
  16. public void onCreate(Bundle savedInstanceState) {
  17. super.onCreate(savedInstanceState);
  18. setContentView(R.layout.mainlayout);
  19. Bundle bun=this.getIntent().getExtras();
  20. Sex=bun.getString(“Sex”);
  21. Height=bun.getDouble(“Height”);
  22. if(Sex.equals(“M”))
  23. {
  24. SextText=”男性”;
  25. }
  26. else
  27. {
  28. SextText=”女性”;
  29. }
  30. //取得標準體重
  31. String Weight=getWeight(Sex, Height);
  32. mTextView01=(TextView)findViewById(R.id.TextView01);
  33. mTextView02=(TextView)findViewById(R.id.TextView02);
  34. String result = “您是一位” + SextText +
  35. “您的身高为:” + Height + “cm”;
  36. String result2= “您的标准体重为:” + Weight +”千克”;
  37. mTextView01.setText(result);
  38. mTextView02.setText(result2);
  39. mButton1=(Button)findViewById(R.id.Button03);
  40. mButton1.setOnClickListener(new OnClickListener() {
  41. @Override
  42. public void onClick(View v) {
  43. // TODO Auto-generated method stub
  44. Intent intent=new Intent();
  45. intent.setClass(Next.this, BundleObject.class);
  46. startActivity(intent);
  47. Next.this.finish();
  48. }
  49. });
  50. }
  51. //四舍五入的方法
  52. private String format(double num)
  53. {
  54. NumberFormat formatter=new DecimalFormat(“0.00”);
  55. String s=formatter.format(num);
  56. return s;
  57. }
  58. //取得體重
  59. public String getWeight(String Sex,double height)
  60. {
  61. String Weight=””;
  62. if(Sex.equals(“M”))
  63. {
  64. Weight=format((height-80)*0.7);
  65. }
  66. else
  67. {
  68. Weight=format((height-70)*0.6);
  69. }
  70. return Weight;
  71. }
  72. }

有一点需要大家注意的是,如果要在新建的项目多新建一个处理类那必需在配置文件为他显示声明,程序才会运行通过,这里配置文件java的命名方式如下:AndroidManifest.xml  相当于asp.net 的web.config为了代码的完整性,我顺便把配置文件也贴出来,高手可以直接跳过

  1. <manifest xmlns:android=”http://schemas.android.com/apk/res/android”
  2. package=”cn.terry”
  3. android:versionCode=”1″
  4. android:versionName=”1.0″>
  5. <application android:icon=”@drawable/icon” android:label=”@string/app_name”>
  6. <activity android:name=”.BundleObject”
  7. android:label=”@string/app_name”>
  8. <intent-filter>
  9. <action android:name=”android.intent.action.MAIN” />
  10. <category android:name=”android.intent.category.LAUNCHER” />
  11. </intent-filter>
  12. </activity>
  13. <activity android:name=”.Next”></activity>
  14. </application>
  15. </manifest>

Android一个界面实现标准体重计算器

%title插图%num
界面设计

<RelativeLayout xmlns:tools=”http://schemas.android.com/tools”
xmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:paddingBottom=”@dimen/activity_vertical_margin”
android:paddingLeft=”@dimen/activity_horizontal_margin”
android:paddingRight=”@dimen/activity_horizontal_margin”
android:paddingTop=”@dimen/activity_vertical_margin”
tools:context=”.MainActivity” >

<TextView
android:id=”@+id/textView2″
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_alignLeft=”@+id/textView1″
android:layout_alignParentTop=”true”
android:layout_marginTop=”17dp”
android:text=”@string/hello_world” />

<TextView
android:id=”@+id/textView1″
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_alignParentLeft=”true”
android:layout_alignParentTop=”true”
android:layout_marginLeft=”18dp”
android:layout_marginTop=”68dp”
android:text=”@string/sex” />

<RadioGroup
android:id=”@+id/radioGroup1″
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_alignTop=”@+id/textView1″
android:layout_marginLeft=”25dp”
android:layout_toRightOf=”@+id/textView1″ >

<RadioButton
android:id=”@+id/radio0″
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”@string/sex1″ />

<RadioButton
android:id=”@+id/radio1″
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”@string/sex2″ />
</RadioGroup>

<TextView
android:id=”@+id/TextView01″
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_alignLeft=”@+id/textView1″
android:layout_centerVertical=”true”
android:text=”@string/high” />

<EditText
android:id=”@+id/editText1″
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_centerVertical=”true”
android:layout_toRightOf=”@+id/TextView01″
android:ems=”10″
android:inputType=”number” >

<requestFocus />
</EditText>

<Button
android:id=”@+id/button1″
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_below=”@+id/editText1″
android:layout_marginTop=”72dp”
android:layout_toRightOf=”@+id/textView2″
android:onClick=”ClickHandler”
android:text=”@string/calculate” />

</RelativeLayout>

实现功能:

package org.wwj.calculate;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.Toast;

public class MainActivity extends Activity {

//定义各个组件
private Button cal;
private EditText high;
private RadioGroup sex;
private RadioButton sex1;
private RadioButton sex2;
private Double weight;
String sex3;

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//通过findViewById获取对象
cal=(Button) this.findViewById(R.id.button1);
high=(EditText) this.findViewById(R.id.editText1);
sex=(RadioGroup) this.findViewById(R.id.radioGroup1);
sex1=(RadioButton) this.findViewById(R.id.radio0);
sex2=(RadioButton) this.findViewById(R.id.radio1);

//设置Button事件监听
cal.setOnClickListener(new OnClickListener() {
public void onClick(View v) {

/*设置事件监听*/
sex.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {

//事件处理
if(checkedId==sex1.getId()){
weight=(Double.parseDouble(high.getText().toString()) – 80) * 0.7;
sex3=”男性”;
}else if(checkedId==sex2.getId()){
weight=(Double.parseDouble(high.getText().toString()) – 70) * 0.6;
sex3=”女性”;
}
}
});

/*Toast显示内容*/
Toast.makeText(MainActivity.this, “你是一位”+sex3+”\n”
+”你的身高是”+high.getText().toString()+”\n”+”你的标准体重是”+weight,
Toast.LENGTH_LONG).show();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}

————————————————

1025. 反转链表 (25) python篇

1025. 反转链表 (25) python篇
1025. 反转链表 (25)
时间限制
300 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
CHEN, Yue
给定一个常数K以及一个单链表L,请编写程序将L中每K个结点反转。例如:给定L为1→2→3→4→5→6,K为3,则输出应该为3→2→1→6→5→4;如果K为4,则输出应该为4→3→2→1→5→6,即*后不到K个元素不反转。
输入格式:
每个输入包含1个测试用例。每个测试用例第1行给出第1个结点的地址、结点总个数正整数N(<= 105)、以及正整数K(<=N),即要求反转的子链结点的个数。结点的地址是5位非负整数,NULL地址用-1表示。
接下来有N行,每行格式为:
Address Data Next
其中Address是结点地址,Data是该结点保存的整数数据,Next是下一结点的地址。
输出格式:
对每个测试用例,顺序输出反转后的链表,其上每个结点占一行,格式与输入相同。
输入样例:
00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
输出样例:
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1
# -*- coding: utf-8 -*-
# 思路:从给定的链首到链末共有数据个数n加1项,id为前n项,next为后n项
def link(address,head,li):  # 采用递归将链表所用节点依次存入列表
    if head in address:
        arrow = address[head]
        li.append(arrow)
        return link(address,arrow,li)
    else:
        return li
head,N_all,cell = input().split()  # 读取*行输入:首项元素id,元素个数N_all,反转间隔cell
N_all,cell = int(N_all),int(cell)  # 将N与cell转换为整数
address,data = {},{}  # 初始化两个字典,其中address保存id-next关系,data保存id-data关系
for i in range(N_all):  # 将输入信息存入address和data中
    a,b,c = input().split()
    address[a],data[a] = c,b
# 调用link()函数将所给信息按链接顺序存入id_plus,有N_all+1个元素,末项为链尾指针,指向未知id或为-1
id_plus = link(address,head,[head])  # 第三项必须为[head]而不是[],因为link()函数无法添加*个id
id_plus[-1] = ‘-1’  # 指定链尾指针指向-1
N_e = len(id_plus) – 1  # id_plus中的元素个数为可链接到的元素,从首项到*后的-1,实际对应的数据个数应减1
num, rem = N_e // cell, N_e % cell  # 判断要对那些数据进行反转
if num:  # 可链接到的数据个数不小于反转间隔
    for i in range(num):
        id_plus[(i*cell):((i+1)*cell)] = id_plus[(i*cell):((i+1)*cell)][::-1]  # 反转
for k,v in enumerate(id_plus[:-1]):  # 按规定格式,打印id,data,next
    s = ‘{} {} {}’.format(v,data[v],id_plus[k+1])
    print(s)
有一个测试点超时,请大神指教!
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100010 //用双向静态链表来解决本问题,定义链表长度为100010
typedef struct Node    //定义结点
{
int data;          //存储数据
int addr;          //存储当前地址
int next;          //后指针,存储下一节点的地址
int prior;         //前指针,存储前一节点的地址
}Node;
int num,n,address,sum=1;    //num为输入节点的总数,n为每次反转节点的个数,address为*个结点的地址,sum为计数器,记录有效节点的个数
void read(Node Nodes[]);   //读取数据,建立链表
void reverse(Node Nodes[]); //反转链表,输出结果
int main()
{
Node Nodes[MAXSIZE];
scanf(“%d%d%d”,&address,&num,&n);
read(Nodes);
reverse(Nodes);
return 0;
}
void read(Node Nodes[])   //读取数据
{
int i,addre,addre_p;   //addre为当前结点的地址,addre_p为前一节点的地址
for (i=0;i<num;i++)      //将每个结点放在地址对应下标的数组单元中,并使当前结点的后指针指向下一节点
{
scanf(“%d”,&addre);
scanf(“%d%d”,&Nodes[addre].data,&Nodes[addre].next);
Nodes[addre].addr=addre;
}
addre=address;
Nodes[addre].prior=-1;   //使*个结点的前指针指向-1
addre_p=Nodes[addre].addr; //记录*个结点的地址
addre=Nodes[addre].next;   //使下一个结点成为当前结点
while (addre!=-1)
{
Nodes[addre].prior=addre_p;  //使当前结点的前指针指向前一个结点
addre_p=Nodes[addre].addr;   //使当前结点成为前结点
addre=Nodes[addre].next;     //使下一个结点成为当前结点
sum++;                       //有效结点数+1
}
}
void reverse(Node Nodes[])  //反转链表,输出数据
{
int i,addre,j,addre_save,addre_prior; //addre为当前结点的地址,addre_save为每次反转前的n个结点中*后一个结点的地址,
addre=address;                        //addre_prior为每次反转前的n个结点中首个结点的地址
if (n==1||n>sum)                      //如果每次反转结点的个数等于1或大于有效结点的个数,则不反转,依次输出即可
{
while(addre!=-1)
{
if (Nodes[addre].next==-1)
printf(“%05d %d %d\n”,Nodes[addre].addr,Nodes[addre].data,Nodes[addre].next);
else
printf(“%05d %d %05d\n”,Nodes[addre].addr,Nodes[addre].data,Nodes[addre].next);
addre=Nodes[addre].next;
}
}else                                //否则,进行反转,每次反转n个结点
{
for (i=0;i<sum/n;i++)           //总反转的次数为 sum/n
{
for (j=0;j<n-1;j++)         //寻找每次反转前的n个结点中*后一个结点的地址
{
addre=Nodes[addre].next;
}
addre_save=addre;          //保存本次反转前*后一个结点的地址
if (i!=0)                  //*次反转不输出,输出前一次反转后的n个结点中*后一个结点的地址,数据以及本次反转后*个结点的地址(注意,这样每次反转才能衔接)
printf(“%05d %d %05d\n”,Nodes[addre_prior].addr,Nodes[addre_prior].data,Nodes[addre].addr);
for (j=0;j<n-1;j++)       //除*后一个结点,依次输出本次反转后的其余结点
{
printf(“%05d %d %05d\n”,Nodes[addre].addr,Nodes[addre].data,Nodes[addre].prior);
addre=Nodes[addre].prior;
}
addre_prior=addre;      //保存本次反转*后一个结点的地址
if (Nodes[addre_save].next==-1)  //如果有效结点已用完,即没有剩余有效结点,则输出*后一个结点,注意其下一个结点地址为-1
printf(“%05d %d %d\n”,Nodes[addre].addr,Nodes[addre].data,-1);
else if (i==sum/n-1)            //如果这是*后一次反转,则输出*后一个结点,注意其下一个结点的地址为不反转的*个结点的地址
printf(“%05d %d %d\n”,Nodes[addre].addr,Nodes[addre].data,Nodes[addre_save].next);
addre=Nodes[addre_save].next;  //使下次反转前的*个结点成为当前结点
}
for (i=0;i<sum%n;i++)    //依次输出剩余不需要反转的结点
{
if (Nodes[addre].next==-1)
printf(“%05d %d %d\n”,Nodes[addre].addr,Nodes[addre].data,Nodes[addre].next);
else
printf(“%05d %d %05d\n”,Nodes[addre].addr,Nodes[addre].data,Nodes[addre].next);
addre=Nodes[addre].next;
}
}
}
用双向静态链表解决,这次不再超时

ES6学习笔记2 变量的解构赋值

ES6学习笔记2 变量的解构赋值
基本用法
ES6允许按照一定模式从数组和对象中提取值,然后对变量进行赋值
let [a,b,c] = [1,2,3];
a    //1
b    //2
c    //3
let [a, [[b], c]] = [1, [[2], 3]];
a    //1
b    //2
c    //3
let [x, ,y] = [1,2,3];
x  //1
y  //3
如果对应变量解构不成功,则该变量的值将会为undefined
let [x,y] = [1];
x   //1
y   //undefined
如果=的右边不是可迭代的结构,就会报错。事实上,只要某种数据结构具有Iterator接口,就可以采用数组形式的解构赋值,例如Set结构,Generator函数
let [foo] = 1;     //报错
let [foo] = true;  //报错
let [foo] = null;  //报错
let [foo] = undefined;  //报错
let [x,y,z] = new Set([‘a’,’b’,’c’]);
x     //’a’
function* fibs(){
    let a = 0;
    let b = 1;
    while(true){
        yield a;
        [a,b] = [b,a+b]
    }
}
let [first,second,third,fourth,fifth,sixth] = fibs();
sixth    //5
默认值
解构赋值允许指定默认值,若对应的变量解构后值为undefined,则将采用默认值,,否则默认值不生效
let [x=1] = [];
x     //1
let [x,y=2] = [1];
x     //1
y     //2
如果默认值是一个表达式,则这个表达式是惰性求值的,即只有将其作为默认值赋值时才会求值
function f(){
    return 2;
}
let [x = f()] = [1];
上述代码中,因为x能取到值,因此函数f不会执行
默认值可以引用其他变量,但该变量必须已经声明
let [x=1, y=x] = [2]    //x=2,y=2
let [x=y, y=1] = []     //报错,因为y未声明就被先使用
对象的解构赋值
对象的解构与数组有一个重要不同,对象的属性没有次序,变量必须与属性名同名才能取到正确的值
let { foo, bar} = {foo:’aaa’, bar:’bbb’};
foo   //’aaa’
bar   //’bbb’
如果变量名与属性名不一致,必须写成如下格式
let {foo:baz} = {foo:’aaa’, bar:’bbb’};
baz   //’aaa’
实际上,对象的解构赋值是下面形式的简写
let { foo:foo, bar:bar} = {foo:’aaa’, bar:’bbb’};
1
这表示对象的解构赋值的内部机制是先找到同名属性,然后再赋值给对应的变量。真正被赋值的是后者,而不是前者
let {foo:baz} = {foo:’aaa’, bar:’bbb’};
baz   //’aaa’
foo   //报错,foo未定义
与数组一样,解构也可以用于嵌套结构的对象
let obj = {
    p: [
        ‘hello’,
        {y:’world’}
    ]
};
let { p:[x, {y}] } = obj;
x     //’hello’
y     //’world’
对象的解构也可以指定默认值,默认值生效的条件与数组类似
var {x, y=5} = {x:1};
x    //1
y    //5
var {x:y=3} = {x:5};
y    //5
如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,将会报错,原因在于此时将对undefined取子属性
let {foo:{bar}} = {baz:’baz’};  //报错
如果要将一个已经声明的变量,用于解构赋值,应该小心
let x;
{x} = {x:1};  //报错
上述javascript会将{x}理解为一个代码块,只有不将大括号写在行首,才能避免此问题
let x;
({x} = {x:1});  //x=1
常见应用
获取Math对象的方法
let {log, sin, cos} = Math;
获取数组项
let arr = [1,2,3];
let {0:first, [arr.length – 1]:last} = arr;
first  //1
last   //3
字符串的解构赋值
字符串被转换为一个类似于数组的对象
const [a,b,c] = ‘xyz’;
a    //’x’
b    //’y’
c    //’z’
let {length:len} = ‘xyz’;
len  //3
数值和布尔值的解构赋值
如果等号右边是数值和布尔值,则会先转化为对象,再赋值
let {toString:s} = 123;
s  //’123′
let {toString:s} = true;
s  //’true’
此处数值和布尔值包装对象都有toString属性,因此他们都能取到值
函数参数的解构赋值
参数传入那一刻,自动被解构赋值
function add([x,y]){
    return x+y;
}
add([1,2]);  //3
可以使用默认值
function add([x=0,y=0]){
    return x+y;
}
add([]);  //0
add([1]);  //1
add([1,1]);  //2
圆括号问题
以下情况不能使用圆括号:
变量声明语句
let [(a)] = [1];  //报错
1
函数参数
function f([(z)]){
    return z;
}  //报错
赋值语句的模式
([a]) = [5];   //报错
({p:a}) = {p:1};   //报错
圆括号只能使用在赋值语句的非模式部分
[(b)] = [3];    //正确
({p:(d)} = {});   //正确
上述*行语句,模式是取数组*个成员,与圆括号无关。第二个语句,模式是p,与圆括号无关。
用途
从函数返回多个值
function example(){
    return [1,2,3];
}
let [a,b,c] = example();
函数参数的定义
function f([x,y,z]){ … }
f([1,2,3]);
提取JSON数据
let jsonData = {
    id:42,
    status:’ok’,
    data:[1,2,3]
}
let {id,status,data} = jsonData;
函数默认参数值、遍历Map结构、输入模块指定方法等

Python爬虫入门:使用urllib模块获取请求页面信息

Python爬虫入门:使用urllib模块获取请求页面信息
  欢迎来到拖更王的小博客,天天想着要把学习和工作中遇到的内容发布到空间,但是因为忙总是忘(这个借口真好)。以后还应该会坚持什么时候想起来什么时候更新的好习惯吧。
  今天说一下python爬虫中一个常用的模块urllib,urllib和requests一样都是用来发起页面请求进行获取页面信息的模块,但是不同的是requests要比urllib更强大,用起来更方便,requests属于第三方模块,需要单独安装,而urllib属于内置模块,可以直接导入使用,下面就使用urllib写两个小的案例进行实际演示,建议新手也跟着操作一下。一个是获取页面信息,一个是使用cookie登录人人网登录。
# 导入urllib模块,想用哪种方式自己选择
# import urllib.request
from urllib import request
# 目标网址
url = ‘http://www.baidu.com’
# 发起请求
response = request.urlopen(url)
# 使用*种导入模块的方式如下
# response = urllib.request.urlopen(url)
# 直接打印response的话只能得到一个HTTPResposne类型的对象
# print(response)
# 所以需要使用read()方法解析获取页面,*后并转码为utf-8
html = response.read().decode(‘utf-8’)
# 打印获取页面
print(html)
  部分网站有简单的反爬措施,比如需要加上headers信息,如User-Agent、Cookie等,添加上即可。
  此时再多加上一行创建请求对象的代码即可。如下:
# 在解析页面时,部分网站需要添加请求头信息来跳过基本的反爬措施,可以使用Request构建带有请求头的对象
resobj = request.Request(url,headers=headers)
from urllib import request, parse
# 使用cookiejar获取cookie
from http import cookiejar
# 构造cookie_bag储存对象
cookie_bag = cookiejar.CookieJar()
# 请求页面时将获取的cookie存入cookie_bag中
handler = request.HTTPCookieProcessor(cookie_bag)
# 在相应页面时处理cookie的时候使用handler内部中的build_opener创建一个opener对象,用来存储cookie对象
opener = request.build_opener(handler)
# url建议从network进行复制选择
url = ‘http://www.renren.com/ajaxLogin/login?’
# form可以F12查看从network中查看一下登录的Form Data,如没有登录一下进行刷新,并勾选Preserve log
form = {
    ’email’:’xxxxx@163.com’,
    ‘icode’:”,
    ‘origURL:http’:’//www.renren.com/home’,
    ‘domain’:’renren.com’,
    ‘key_id’:’1′,
    ‘captcha_type’:’web_login’,
    ‘password’:’xxxxx’,
    ‘rkey’:’cb15f985754fd884a44506ff5db1256e’,
    ‘f’:”,
}
form = parse.urlencode(form).encode(‘utf-8’)
response = opener.open(url, form)
res = response.read()
print(res)

一个小例子助你彻底理解协程

一个小例子助你彻底理解协程
一个小例子助你彻底理解协程
协程,可能是Python中*让初学者困惑的知识点之一,它也是Python中实现并发编程的一种重要方式。Python中可以使用多线程和多进程来实现并发,这两种方式相对来说是大家比较熟悉的。事实上,还有一种实现并发的方式叫做异步编程,而协程就是实现异步编程的必要方式。
所谓协程,可以简单的理解为多个相互协作的子程序。在同一个线程中,当一个子程序阻塞时,我们可以让程序马上从一个子程序切换到另一个子程序,从而避免CPU因程序阻塞而闲置,这样就可以提升CPU的利用率,相当于用一种协作的方式加速了程序的执行。所以,我们可以言简意赅的说:协程实现了协作式并发。
接下来用一个小例子帮助大家理解什么是协作式并发,先看看下面的代码。
import time
def display(num):
    time.sleep(1)
    print(num)
for num in range(10):
    display(num)
上面这段代码相信大家很容看懂,程序会输出0到9的数字,每隔1秒中输出一个数字,因此整个程序的执行需要大约10秒时间。值得注意的是,因为没有使用多线程或多进程,程序中只有一个执行单元,而time.sleep(1)的休眠操作会让整个线程停滞1秒钟,对于上面的代码来说,在这段时间里面CPU是完全闲置的没有做什么事情。
我们再来看看使用协程会发生什么事情。从Python 3.5开始,使用协程实现协作式编发有了更为便捷的语法,我们可以使用async来定义异步函数,可以使用await让一个阻塞的子程序将CPU让给与它协作的子程序。在Python 3.7中,asyanc和await成为了正式的关键字,让开发者有一种喜大普奔的感觉。我们先看看如何定义一个异步函数。
import asyncio
async def display(num):
    await asyncio.sleep(1)
    print(num)
接下来敲黑板说重点。异步函数不同于普通函数,调用普通函数会得到返回值,而调用异步函数会得到一个协程对象。我们需要将协程对象放到一个事件循环中才能达到与其他协程对象协作的效果,因为事件循环会负责处理子程序切换的操作,简单的说就是让阻塞的子程序让出CPU给可以执行的子程序。
我们先通过下面的列表生成式来代码10个协程对象,跟刚才在循环中调用display函数的道理一致。
coroutines = [display(num) for num in range(10)]
通过下面的代码可以获取事件循环并将协程对象放入事件循环中。
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(coroutines))
loop.close()
执行上面的代码会发现,10个分别会阻塞1秒钟的协程总共只阻塞了约1秒种的时间,这就说明协程对象一旦阻塞会将CPU让出而不是让CPU处于闲置状态,这样就大大的提升了CPU的利用率。而且我们还会注意到,0到9的数字并不是按照我们创建协程对象的顺序打印出来的,这正是我们想要的结果啊;另外,多次执行该程序会发现每次输出的结果都不太一样,这正是并发程序本身执行顺序不确定性造成的结果。
上面的例子来自于著名的“花书”(《Python高级并发编程》),为了让大家对协程的体会更加深刻,对原书的代码做了小的改动,这个例子虽然简单,但是它已经让你体会到了协作式并发的魅力。在商业项目中,如果需要使用协作式并发,还可以将系统默认的事件循环替换为uvloop提供的事件循环,这样会获得更好的性能,因为uvloop是基于著名的跨平台异步I/O库libuv实现的。另外,如果要做基于HTTP的网络编程,三方库aiohttp是不错的选择,它基于asyncio实现了异步的HTTP服务器和客户端。

Python中格式化字符串更酷的方式

Python中格式化字符串更酷的方式
Python中格式化字符串更酷的方式
在 Python 中,大家都习惯使用 %s 或 format 来格式化字符串,在 Python 3.6 中,有了一个新的选择 f-string。
使用对比
我们先来看下 Python 中已经存在的这几种格式化字符串的使用比较。
# %s
username = ‘tom’
action = ‘payment’
message = ‘User %s has logged in and did an action %s.’ % (username, action)
print(message)
# format
username = ‘tom’
action = ‘payment’
message = ‘User {} has logged in and did an action {}.’.format(username, action)
print(message)
# f-string
username = ‘tom’
action = ‘payment’
message = f’User {user} has logged in and did an action {action}.’
print(message)
f”{2 * 3}”
# 6
comedian = {‘name’: ‘Tom’, ‘age’: 20}
f”The comedian is {comedian[‘name’]}, aged {comedian[‘age’]}.”
# ‘The comedian is Tom, aged 20.’
相比于常见的字符串格式符 %s 或 format 方法,f-strings 直接在占位符中插入变量显得更加方便,也更好理解。
方便的转换器
f-string 是当前*佳的拼接字符串的形式,拥有更强大的功能,我们再来看一下 f-string 的结构。
f ‘ <text> { <expression> <optional !s, !r, or !a> <optional : format specifier> } <text> … ‘
其中 ‘!s’ 调用表达式上的 str(),’!r’ 调用表达式上的 repr(),’!a’ 调用表达式上的 ascii()。大家可以看看下面的例子。
class Person:
    def __init__(self, name, nickname):
        self.name = name
        self.nickname = nickame
    def __str__(self):
        return self.name
    def __repr__(self):
        return self.nickname
person = Person(‘王大锤’, ‘Wang Gangdan’)
print(f'{person!s}’)
print(f'{person!r}’)
print(f'{person.name!a}’)
print(f'{person.nickname!a}’)
性能
f-string 除了提供强大的格式化功能之外,还是这三种格式化方式中性能*高的实现。
>>> import timeit
>>> timeit.timeit(“””name = “Eric”
… age = 74
… ‘%s is %s.’ % (name, age)”””, number = 10000)
0.003324444866599663
>>> timeit.timeit(“””name = “Eric”
… age = 74
… ‘{} is {}.’.format(name, age)”””, number = 10000)
0.004242089427570761
>>> timeit.timeit(“””name = “Eric”
… age = 74
… f'{name} is {age}.'”””, number = 10000)
0.0024820892040722242
坦白的说,f-string 就是字符串 format 方法一个语法糖,但它进一步简化了格式化字符串的操作并带来了性能上的提升。使用 Python 3.6+ 的同学,使用 f-string 来代替你的 format 函数,以获得更强大的功能和更高的性能。

速看在线代理的选择技巧

因特网时代有许多提供代理ip服务的服务商,因为现在服务数量较多,大家在选择代理ip时当然要多考虑一些。所以如何选择一个好的网上代理呢?下面就跟随小编一起来了解下:

1、选择ip的数量很多,如果一个代理ip服务商能够提供海量ip资源,那么可以看出这个ip代理服务商是具有实力的。

2、选择高效ip,一些代理IP服务商ip虽然数量多,但连接的效率较低,尽量选择使用效率高的代理ip,否则会浪费大量的成本和时间,影响工作的效率。

3、要考虑到ip的连接质量,一个高质量的ip地址具有连接有效率高、存取速度快、稳定等特点。比如独享代理ip,其网速和连接速度都非常快,而且隐蔽性强,能保证用户的信息安全。

优质代理ip的特征有哪些

%title插图%num

有很多原因可以导致动态IP代理,并且它的使用可能会根据个人或企业的*终目标而变化。

1、加强安全。
安全*,这是您使用代理的*重要和*主要的原因。这对涉及大量敏感资料的企业来说尤为重要,因为这些资料为当今数据驱动世界的黑客和网络窃贼提供了非常有价值的信息缓存。正如一条护城河,或者是在一座古老城堡周围一样,代理服务器起了一道前线,可以保护潜在的入侵者(并且有希望阻止它),这就给这些网络罪犯提供了另一种防御手段,他们必须努力绕开将数据实际存储在家庭服务器上的做法,即使他们试图破解。

2、提倡匿名。
除安全之外,许多人使用代理的第二个原因是保密。AgentShared其指定的IP地址代替了您自己的IP地址,因此您可以在使用Internet时保持匿名。所以,不管你是试图做敏感的竞争者分析,还是仅仅想增加一些浏览时的身份保护,代理都能让你的身份对网站和其他用户隐藏。
以匿名方式访问代理不仅有助于保护您的个人信息,还能隐藏您的浏览习惯。

3、确立并克服限制。

没有一家公司希望因业务和客户信息的敏感性而不安全或不合适地访问公司网络的网站。通过允许管理员设置可以访问网络的设备,以及限制这些站点可以访问的站点,代理可以帮助解决这个问题,从而帮助降低联机工作而不受保护的风险。除提供对病毒的防御、对恶意软件的保护以及对可能的数据泄露的保护外,网络管理员还可以记录正在访问的站点,而代理则可以帮助您绕过地理封锁内容等限制。

动态ip服务器是什么

动态ip服务器通常称为DHCP服务器,动态主机设置协议(DynamicHostConfiguraeProtocys,DHCP)是一种LAN网络协议,使用UDP协议工作,主要有两种用途:将IP地址自动分配给内部网络或网络服务提供商,作为对所有计算机进行集中管理的一种方式,向内部网络管理员自动分配IP地址。您可以切换地址,您可以自己设置地址池,也可以手动更改与您的服务器所在的地址。

简而言之,动态服务器就是一台能被VPS主机控制的远程计算机,它可以部署自己的应用程序,然后申请一个域名,再正式在互联网上发布。事实上,VPS也可以自行搭建。在拥有高性能服务器的情况下,只需使用一个IP地址。可将一台高性能服务器,快速变为5台、10台、20台的虚拟服务器。在自己的VPS上面,可以发布各种应用程序,也可以将剩余的服务器资源出租给其他因特网用户。

我们大概已经知道什么是动态IP服务器了吧,那么使用它有什么好处呢?通过使用DHCP,DHCP允许服务器动态地为网络中的其他服务器提供IP地址,并且在使用DHCP的情况下,除了DHCP、LS和WINS服务器之外,还可以不为任何服务器设置和维护静态IP地址。利用DHCP可以*大地简化配置客户hcp的TCP/IP的工作,特别是当某些TCP/IP参数发生变化时,IP地址和子网掩码会发生变化,例如网络的大规模重建。