冲刺(二)

徐利峰:

今天利用爬虫去解析铁道大学新闻官网:http://xcb.stdu.edu.cn/2009-05-05-02-26-33.html

分析后发现其标题都是在tr,class="sectiontableentry1"和class=“sectiontableentry2”的里面,因此我就将这两种全部获取

获取后遍历存储他们的href(单个新闻的网址)

通过对单个网址进行分析,打算存入数据库里的信息有:标题,日期,点击次数,正文,图片链接

对于标题,日期,点击次数比较简单

难点在于:正文的爬取和图片链接

 

①爬取正文时:正文都在div.article-content下的p标签里,因此我们获取所有的p标签的集合

一开始我以为就是在p标签下的span里的是正文,爬取了10个后发现漏了一点东西,原来b标签里的也是正文里的内容

由于整篇文章是有p标签分割的,一个p标签代表这一段,因此我将爬取的所有p标签遍历,之后通过p的contents来访问他的子节点,根据子节点的name属性来判断是“span”还是“p”,爬取完一段后存储到正文集合里。

复制代码
r=requests.get(url,headers=headers)
    content=r.content.decode('utf-8')
    soup = BeautifulSoup(content, 'html.parser')
    trs=soup.find_all('tr',class_='sectiontableentry1')
    trs+=soup.find_all('tr',class_='sectiontableentry2')
    for i in range(len(trs)):
        strs='http://xcb.stdu.edu.cn/'
        link=strs+trs[i].a['href']
        r = requests.get(link, headers=headers)
        content = r.content.decode('utf-8')
        soup = BeautifulSoup(content, 'html.parser')
        title=soup.find('h2',class_='contentheading').text.strip()
        title=title.replace(' ', '')
        date=soup.find('span',class_='createdate').text.strip()[5:]
        click=soup.find('span',class_='hits').text.strip()[5:-1]
        #print(title,date,click)
        #用来截取文章内容

        doc=[]
        listp=soup.select('div.article-content > p')
        for j in range(len(listp)):
            #print(listp[j])
            pp=''
            for k in range(len(listp[j].contents)):
                if(listp[j].contents[k].name=='span'):
                    pp+=listp[j].contents[k].text
                elif(listp[j].contents[k].name=='b'):
                    pp+=listp[j].contents[k].span.text
            doc.append(pp)
        doc='\n'.join(doc)
        #print(doc)
复制代码

 

②爬取图片链接:

一开始也是以为只是在span里的input标签里,之后爬取10条数据后比较原文发现少了几张图片,于是回头在取分析少的图片,发现原来有的图片在img标签里

然后再爬取image里的图片链接,之后将两个爬取的链接合并,图片链接之间用空格分割

 

单个网页爬取完成后,分析我要是爬取10页内容,发现他们之间的规律,每翻一页后面就会发生变化:

第一页:http://xcb.stdu.edu.cn/2009-05-05-02-26-33.html

第二页:http://xcb.stdu.edu.cn/2009-05-05-02-26-33.html?start=10

第三页:http://xcb.stdu.edu.cn/2009-05-05-02-26-33.html?start=20

发现start里的数字都是10个10的加,因此我们就可以翻页爬取,然后存入数据库

 

数据库截图:

 

戴伟伟:

代码:

import android.content.DialogInterface;
import android.os.Bundle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;

import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.lh.std_everything.ui.home.hometype.blog.WriteViewModel;

public class MainActivity extends AppCompatActivity {

    private NavController controller;

    public static String getUserid() {
        return userid;
    }

    private static String userid;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        BottomNavigationView bottomNavigationView=findViewById(R.id.bottomNavigationView);
        controller = Navigation.findNavController(this,R.id.navhost);
        AppBarConfiguration configuration=new AppBarConfiguration.Builder(bottomNavigationView.getMenu()).build();
        NavigationUI.setupActionBarWithNavController(this, controller,configuration);
        NavigationUI.setupWithNavController(bottomNavigationView, controller);

        userid=getIntent().getStringExtra("id");
    }

MainActivity
public class Login extends AppCompatActivity {

    private static final String SHARED_FILE_NAME ="USERCOUNT" ;
    private AutoCompleteTextView search;
    private EditText pwd;
    private FloatingActionButton login_btn;
    private final static String requrl="http://39.98.165.112/STDEverything/login_servlet"; //ip:116.62.178.231
    private TextView tip=null;

    // 要申请的权限
    private String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.CALL_PHONE,
            Manifest.permission.CAMERA,Manifest.permission.ACCESS_COARSE_LOCATION};


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_login);
        getPower();
        initView();
        String[] arr = getUserCount();
        ArrayAdapter<String> adapter= new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, arr);
        search.setAdapter(adapter);
        tip.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(Login.this,Register.class));
            }
        });
        login_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final String name=search.getText().toString();
                String userpwd=pwd.getText().toString();
                final String reqdata="method=login&name="+name+"&pwd="+userpwd+"";
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            final JSONObject jsonObject=new JSONObject(String.valueOf(HttpUtil.sendPost(requrl,reqdata)));//子线程获取json结果
                            runOnUiThread(new Runnable() {    //主线程运行跳转活动
                                @Override
                                public void run() {
                                    try {
                                        Toast.makeText(Login.this, jsonObject.get("msg").toString(), Toast.LENGTH_SHORT).show();
                                        if(jsonObject.get("status").equals("1")){  //状态码1代表登陆成功
                                            if(!judgeUserExists(name))
                                                recordUser(name);
                                            startActivity(new Intent(Login.this, MainActivity.class)
                                                    .putExtra("id",jsonObject.get("id").toString()));
                                        }
                                    } catch (JSONException e) {
                                        e.printStackTrace();
                                    }
                                }
                            });
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        });
    }
private void recordUser(String val){     //保存用户账户
        Date date=new Date();
        SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddhhmmssSSS");
        SharedPreferences shf=getSharedPreferences(SHARED_FILE_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor=shf.edit();
        editor.putString(sdf.format(date),val);
        editor.apply();
    }

Login
public class Register extends AppCompatActivity {

    private RegisterHandler handler=null;
    private EditText name_text=null;
    private EditText pwd_text=null;

    private final static String requrl="http://39.98.165.112/STDEverything/login_servlet"; //ip:116.62.178.231
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_register);
        FloatingActionButton register_btn = findViewById(R.id.register_btn);
        name_text=findViewById(R.id.name);
        pwd_text=findViewById(R.id.pwd);
        handler=new RegisterHandler(this);
        register_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name=name_text.getText().toString();
                String pwd=pwd_text.getText().toString();
                final String reqdata="method=login&name="+name+"&pwd="+pwd+"";
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            JSONObject jsonObject=new JSONObject(String.valueOf(HttpUtil.sendPost(requrl,reqdata)));
                            Message msg=new Message();
                            msg.what=100;
                            msg.obj=jsonObject;
                            handler.sendMessage(msg);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        });

    }

    static class RegisterHandler extends Handler{

        private final WeakReference<Register> mcontext;

        RegisterHandler(Register context){
            mcontext=new WeakReference<>(context);
        }
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if(msg.what==100){
                JSONObject jsonObject= (JSONObject) msg.obj;
                try {
                    if(jsonObject.get("name").equals("yes"))
                        Toast.makeText(mcontext.get(),"用户名已存在",Toast.LENGTH_SHORT).show();
                    else if(jsonObject.get("name").equals("no")){
                        new Thread(new Runnable() {
                            @Override
                            public void run() {
                                String name=mcontext.get().name_text.getText().toString();
                                String pwd=mcontext.get().pwd_text.getText().toString();
                                final String reqdata="method=register&name="+name+"&pwd="+pwd+"";
                                HttpUtil.sendPost(requrl,reqdata);
                                sendEmptyMessage(888);
                            }
                        }).start();
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }else if(msg.what==888){
                Toast.makeText(mcontext.get(), "注册成功", Toast.LENGTH_SHORT).show();
                mcontext.get().startActivity(new Intent(mcontext.get(),Login.class));
            }
        }
    }
}

Register

明天尝试将注册信息存入云服务器数据库。

 

李浩:网络请求数据(参数+文件)

效果图

        

 

 

 

具体功能

  1、显示博客的详细信息,如果有图片可以加载图片(包括用户头像,没有就使用默认头像);

  2、可以交互,如点赞、关注、收藏等(包括取消);

  3、可以评论,点击👍旁边的气泡即可(今天还没有写,准备明天彻底完善)

  4、可以显示用户的评论,格式就像最下方的一样;

 

总结:我以为今天可以彻底完成的,但是人生总是那么的充满意外,写这些小交互的时候后台函数调用错误,找错误废了不少时间,上述图中,除了不能写评论,其余功能都可以实现,对,包括展示评论,后台全部已经写好,明天写一下客户端就彻底🆗了,最后再说一句,Thread+Handler线程并发真好用。

 

posted @ 2020-04-17 14:23  史莱克三怪队  阅读(185)  评论(0编辑  收藏  举报