【网络爬虫】给关键字获取百度知道搜索数据的网络爬虫

简介: 转载请注明出处:http://blog.csdn.net/qq_26525215本文源自【大学之旅_谙忆的博客】简单的通过关键字,爬出百度知道的一些搜索数据。 例如:问题,提问时间;答案文本,答案时间,点赞数,拍砖数,回答人,回答人级别,搜索的关键字等。

转载请注明出处:http://blog.csdn.net/qq_26525215

本文源自大学之旅_谙忆的博客

简单的通过关键字,爬出百度知道的一些搜索数据。
例如:问题,提问时间;答案文本,答案时间,点赞数,拍砖数,回答人,回答人级别,搜索的关键字等。

答案可以有多个,每个问题有多个答案应都保存。保存数据在MySql中。

在这里需要用到一个牛人的爬虫框架:
WebMagic
网址:http://webmagic.io/docs/zh/

我用的是IEDA工具,建立的是Maven项目。

要搞爬虫,一些基础的学习是不可少的,比如HTML,JSP等前台知识,知道怎么解析xml文档(利用XPath),用开发工具(推荐Intellij IDEA),MySQL,Maven也可以学习等等。

下面就开始讲怎么抓取百度知道的数据了。

我们用百度知道搜索的时候,可以看地址栏:
https://zhidao.baidu.com/search?ct=17&pn=0&tn=ikaslist&rn=10&word=%E7%A4%BE%E4%BF%9D%E8%BD%AC%E7%A7%BB&fr=wwwt

这里关键词的变量名是word。那么其他变量与值可以不用管它。

缩减一下地址:
https://zhidao.baidu.com/search?word=社保迁移

还有重要的一点是,百度知道的html的编码是GBK的!注意编码不要搞错了。

这个时候我们就可以利用这个地址来进行一些事情了。

需要学会用浏览器查看网页源码哦。

通过这种方式,我们可以找出标题的规律,进而通过XPath解析,得到标题名!

这些数据(标题,问题描述,答案,时间等)都是可以通过上面方式得到的!

这里有个小问题,就是点赞数和拍砖数这样是找不到正确的方式的,因为那里是动态生成。

在这里做一个演示:

通过火狐浏览器的查看元素源码,是这样的。

通过在地址栏前面加: view-source: 可以看网页源码。
一般点击鼠标右键,可以直接看网页源码。

这个时候,我们并不可以在源码中看到刚刚的代码。

也就是说,我们抓取网页的源码的时候,获取到的html也是没有那个的,怎么办,这个时候,我们会发现,

<span 
        alog-action="qb-zan-btnbestbox" 
        class="iknow-qb_home_icons evaluate evaluate-32
                        " 
        id="evaluate-2225390772" 
        data-evaluate="7" 
        >
</span>

data-evaluate=”7”
正好与点赞数7一样!
继续对比一下其他页面,会发现这个属性的值就是点赞数!

那么好办了,通过XPath然后加工一下,一样可以获取此值。
拍砖数一样的分析,然后获取就行!

至于其他的数据,差不多都是这样分析的。

开始本来想做成Web应用,结果WebMagic爬虫框架只能在main线程才能运行,所以就只做了一个简单的用main函数启动的应用了。

用到了MyBatis和Spring。主要是为了操作数据库简单一点。
你可以不用框架的,主要代码只有这个类的代码:

package cn.hncu;

import cn.hncu.model.Answer;
import cn.hncu.model.Keyword;
import cn.hncu.model.KeywordProblemKey;
import cn.hncu.model.Problem;
import cn.hncu.service.KeywordService;
import cn.hncu.service.KeywordServiceImpl;
import cn.hncu.tool.*;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Controller;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.selector.Html;

import javax.xml.xpath.XPath;
import java.io.IOException;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * User: 陈浩翔.
 * Date: 2017/2/27.
 * Time: 下午 6:29.
 * Explain:
 */
public class Entrance implements PageProcessor {
    private Logger logger = LoggerFactory.getLogger(Entrance.class);
    private static ApplicationContext context;
    private static KeywordService keywordService;

    //搜索的关键字
    private static String keyword = "社保转移";
    //百度知道的搜索前缀
    private static String url = "https://zhidao.baidu.com/search?word=";
    //设置抓取页数
    private static Integer pages = 20;

    private Site site = Site.me().setCharset("gbk").setRetrySleepTime(4).setSleepTime(100);
    private static String keywordId ;
    private List<Map<String,String>> lists;

    @Override
    public void process(Page page) {
        Html html = page.getHtml();
        //问题
        String problem = html.xpath("//span[@class='ask-title']/text()").toString();
        logger.info("问题:"+problem);
        //提问者
        String problemAnthor = html.xpath("//a[@alog-action='qb-ask-uname']/text()").toString();
        //logger.info("提问者:"+problemAnthor);
        //问题描述
        String problemDescribe = html.xpath("//span[@class='con']/text()").toString();
        //logger.info("问题描述:"+problemDescribe);
        //提问时间
        if(problem==null) {
            lists = new ArrayList<Map<String, String>>();
            List<String> strs = html.xpath("//dd/span[@class='mr-8']/text()").all();
            List<String> quizTimes = new ArrayList<String>();
            for (int i=0;i<strs.size();i++) {
                //logger.info(strs.get(i)+"  "+strs.get(i).matches("[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]"));
                if(strs.get(i).matches("[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]")){
                    quizTimes.add(strs.get(i));
                }
            }
            List<String> portionProblems = html.xpath("//a[@class='ti']/text()").all();
            //logger.info("quizTimes.size():" + quizTimes.size());
            //logger.info("portionProblems.size():" + portionProblems.size());
            if(quizTimes.size()==portionProblems.size()) {
                for (int i=0;i<quizTimes.size();i++) {
                    Map<String,String> map = new HashMap<String,String>();
                    map.put("quizTimes",quizTimes.get(i));
                    map.put("portionProblems",portionProblems.get(i));
                    lists.add(map);
                    //logger.info("部分问题:" + lists.get(i).get("portionProblems"));
                    //logger.info("时间:" + lists.get(i).get("quizTimes"));
                }
            }
        }

        //最佳回答
        String bestAnswer =html.xpath("//pre[@class='best-text mb-10']").toString();//图片文字无法处理
        if(bestAnswer==null){
            bestAnswer =html.xpath("//div[@class='best-text mb-10']").toString();
        }
        //logger.info("最佳回答:"+bestAnswer);
        //回答者
        String answerAuthor = html.xpath("//a[@class='mavin-name f-14 mr-10']/text()").toString();
        //如果回答者为NULL-有可能是其他的没有认证的人回答的
        if(answerAuthor==null){
            answerAuthor = html.xpath("//div[@class='grid f-aid ff-arial']/p/a[@class='user-name']/text()").toString();
        }
        //如果回答者还是为NULL-有可能是网上的人贡献的
        if(answerAuthor==null){
            answerAuthor = html.xpath("//div[@class='grid f-aid ff-arial']/p[@class='mb-5']/span/text()").toString();
        }
        //logger.info("回答者:"+answerAuthor);

        //回答者等级
        String anthorGrade = html.xpath("//a[@class='mavin-reply-icon f-orange']/text()").toString();
        //如果回答者等级为NULL-有可能是其他的没有认证的人回答的
        if(anthorGrade==null){
            anthorGrade = html.xpath("//div[@class='grid f-aid ff-arial']/p[@class='mb-5']/a[@class='i-gradeIndex']").toString();
            if(anthorGrade!=null){
                anthorGrade = "LV"+anthorGrade.substring(anthorGrade.lastIndexOf("Index-")+6,anthorGrade.lastIndexOf(" mr-10"));
            }
        }
        if(answerAuthor!=null&&anthorGrade==null){
            anthorGrade ="0";
        }
        //logger.info("回答者等级:"+anthorGrade);

        //推荐时间
        String answerTime = html.xpath("//span[@class='grid-r f-aid pos-time answer-time f-pening']/text()").toString();
        //logger.info("推荐时间:"+answerTime);

        //最佳回答点赞数
        String pointPraise =html.xpath("//span[@alog-action='qb-zan-btnbestbox']").toString();
        if(pointPraise!=null) {
            pointPraise = pointPraise.substring(pointPraise.lastIndexOf("evaluate"))
                    .replaceAll("evaluate=\"", "")
                    .replaceAll("\"> </span>", "");
        }
        //logger.info("最佳回答点赞数:"+pointPraise);
        //最佳回答拍砖数
        String contemptNumber =html.xpath("//span[@alog-action='qb-evaluate-outer']").toString();
        if(contemptNumber!=null) {
            contemptNumber = contemptNumber.substring(contemptNumber.lastIndexOf("evaluate"))
                    .replaceAll("evaluate=\"", "")
                    .replaceAll("\"> </span>", "");
        }
        //logger.info("最佳回答拍砖数:"+contemptNumber);

        //将发布时间和问题放到一块去,这里需要匹配
        String quizTimes = null;//这个判断有漏洞的!!!
        if(problem!=null) {
            for (int i = 0; i < lists.size(); i++) {
                String portionProblem = lists.get(i).get("portionProblems");
                String time = lists.get(i).get("quizTimes");
                boolean isThisProblem = true;
                for (int j = 0; j < portionProblem.length(); j++) {
                    if(problem.indexOf(portionProblem.charAt(j))==-1){
                        isThisProblem = false;
                    }
                }
                if(isThisProblem){
                    quizTimes = time;
                    continue;
                }
            }
        }
        //发表时间
        //logger.info("发表时间:"+quizTimes);

        //其他回答答案
        List<String> otherAnswers =html.xpath("//div[@class='answer-text']/span").all();
        //logger.info("其他回答答案:"+otherAnswers);
        //其他回答的回答时间
        List<String> otherAnswerTime =html.xpath("//div[@class='grid pt-5']/span[@class='pos-time']/text()").all();
        //logger.info("其他回答的回答时间:"+otherAnswerTime);
        //其他回答的回答者
        List<String> otherAnswerAnthors =html.xpath("//a[@alog-action='qb-username' and @class='user-name']/text()").all();
        //logger.info("其他回答的回答者:"+otherAnswerAnthors);
        //其他回答的回答者等级
        List<String> otherAnswerAnthorGradesLists =html.xpath("//div[@class='grid pt-5']/span[@class='i-gradeIndex']").all();
        List<String> otherAnswerAnthorGrades = new ArrayList<String>();
        if(otherAnswerAnthorGradesLists!=null){
            for(int i=0;i<otherAnswerAnthorGradesLists.size();i++){
                otherAnswerAnthorGrades.add("LV"+otherAnswerAnthorGradesLists.get(i).substring(otherAnswerAnthorGradesLists.get(i).lastIndexOf("Index-")+6,otherAnswerAnthorGradesLists.get(i).lastIndexOf("\"></span>")));
            }
        }
        //logger.info("其他回答的回答者等级:"+otherAnswerAnthorGrades);
        //其他回答的点赞数
        List<String> otherAnswerPointPraiseLists =html.xpath("//span[@alog-action='qb-zan-btn']").all();
        List<String> otherAnswerPointPraises = new ArrayList<String>();
        if(otherAnswerPointPraiseLists!=null) {
            for(int i=0;i<otherAnswerPointPraiseLists.size();i++) {
                otherAnswerPointPraises.add(otherAnswerPointPraiseLists.get(i).substring(otherAnswerPointPraiseLists.get(i).lastIndexOf("evaluate"))
                        .replaceAll("evaluate=\"", "")
                        .replaceAll("\"> </span>", ""));
            }
        }
        //logger.info("其他回答的点赞数:"+otherAnswerPointPraises);
        //其他回答的拍砖数
        List<String> otherAnswerContemptNumberLists =html.xpath("//div[@class='pos-relative']/div[@class='qb-zan-eva']/span[@alog-action='qb-evaluate-outer']").all();
        List<String> otherAnswerContemptNumbers = new ArrayList<String>();
        if(otherAnswerContemptNumberLists!=null) {
            for(int i=0;i<otherAnswerContemptNumberLists.size();i++) {
                otherAnswerContemptNumbers.add( otherAnswerContemptNumberLists.get(i).substring(otherAnswerContemptNumberLists.get(i).lastIndexOf("evaluate"))
                        .replaceAll("evaluate=\"", "")
                        .replaceAll("\"> </span>", ""));
            }
        }
        //logger.info("其他回答的拍砖数:"+otherAnswerContemptNumbers);

        //如果为了效率,可以开线程去存数据的
        if(answerAuthor!=null || otherAnswers.size()!=0){
            //问题表数据
            Problem p = new Problem();
            String problemId = cn.hncu.tool.UUID.getId();
            p.setId(problemId);
            p.setProblem(problem);
            p.setQuizTime(quizTimes);
            p.setProblemAnthor(problemAnthor);
            p.setProblemDescribe(problemDescribe);
            //关键字—问题关系表数据
            KeywordProblemKey keywordProblemKey = new KeywordProblemKey();
            keywordProblemKey.setKeywordId(keywordId);
            keywordProblemKey.setProblemId(problemId);
            //最佳答案数据
            List<Answer> answers = new ArrayList<Answer>();

            Answer answer = new Answer();
            answer.setId(cn.hncu.tool.UUID.getId());
            answer.setProblemId(problemId);
            answer.setAnswerAnthor(answerAuthor);
            answer.setAnswer(bestAnswer);
            answer.setAnthorGrade(anthorGrade);
            answer.setPointPraise(pointPraise);
            answer.setAnswerTime(answerTime);
            answer.setContemptNumber(contemptNumber);
            answers.add(answer);

            //其他答案数据
            Integer otherAnswersSize = otherAnswers.size();
            for(int i=0;i<otherAnswersSize;i++){
                answer = new Answer();
                answer.setId(cn.hncu.tool.UUID.getId());
                answer.setProblemId(problemId);
                if(otherAnswerAnthors.size()>i)
                    answer.setAnswerAnthor(otherAnswerAnthors.get(i));
                if(otherAnswers.size()>i)
                    answer.setAnswer(otherAnswers.get(i));
                if(otherAnswerAnthorGrades.size()>i)
                    answer.setAnthorGrade(otherAnswerAnthorGrades.get(i));
                if(otherAnswerPointPraises.size()>i)
                    answer.setPointPraise(otherAnswerPointPraises.get(i));
                if(otherAnswerTime.size()>i)
                    answer.setAnswerTime(otherAnswerTime.get(i));
                if(otherAnswerContemptNumbers.size()>i)
                    answer.setContemptNumber(otherAnswerContemptNumbers.get(i));
                answers.add(answer);
            }
            keywordService.insertAll(p,keywordProblemKey,answers);

        }
//        if (page.getResultItems().get("name") == null) {
//            //skip this page
//            page.setSkip(true);
//        }

        // 从搜索页面发现后续的url地址来抓取
//        List<String> urls = html.links().regex("(http://zhidao.baidu.com/question/.+"+"\\?"+".+[^\"])").all();
//        for(String url:urls){
//            logger.info(url);
//        }
        if(problem==null) {
            page.addTargetRequests(html.links().regex("(http://zhidao.baidu.com/question/.+"+"\\?"+".+[^\"])").all());
            for(int i=1;i<pages;i++){
                List<String> lists = new ArrayList<String>();
                lists.add(url+keyword+"&site=-1&sites=0&date=0&pn="+(i*10));
                page.addTargetRequests(lists);
            }
            pages=0;//只加一次进队列!
        }
    }

    @Override
    public Site getSite() {
        return site;
    }

    public static void main(String[] args) throws IOException {
        //使用"spring.xml""spring-mybatis.xml"这两个配置文件创建Spring上下文
        context = new ClassPathXmlApplicationContext("spring.xml", "spring-mybatis.xml");
        keywordService = (KeywordService) context.getBean("keywordService");

        //存储关键字表
        Date searchTime = new Date();//搜索的时间
        keywordId = cn.hncu.tool.UUID.getId();
        Keyword keyword = new Keyword();
        keyword.setId(keywordId);
        keyword.setKeyword(Entrance.keyword);
        keyword.setSearchTime(searchTime);
        keywordService.insertKeyword(keyword);

        Spider.create(new Entrance()).addUrl(url+Entrance.keyword)
                //.addPipeline(new JsonFilePipeline("D:\\test\\"))
                //开启 *个线程抓取
                .thread(50)
                //同步启动爬虫
                .run();
    }
}

数据库很简单,看你自己需要哪些数据,就建立哪些字段和表就行。

建立MySQL数据表的文件在项目的src/main/resources/sql/1.sql

本篇博客涉及到的源码链接:

->点击访问源码-©CHX


本文章由[谙忆]编写, 所有权利保留。
欢迎转载,分享是进步的源泉。

转载请注明出处:http://blog.csdn.net/qq_26525215

本文源自大学之旅_谙忆的博客

目录
相关文章
|
1月前
|
监控 安全 网络安全
云计算与网络安全:保护数据的关键策略
【9月更文挑战第34天】在数字化时代,云计算已成为企业和个人存储、处理数据的优选方式。然而,随着云服务的普及,网络安全问题也日益凸显。本文将探讨云计算环境中的网络安全挑战,并提供一系列策略来加强信息安全。从基础的数据加密到复杂的访问控制机制,我们将一探究竟如何在享受云服务便利的同时,确保数据的安全性和隐私性不被侵犯。
65 10
|
14天前
|
存储 安全 网络安全
云计算与网络安全:保护数据的新策略
【10月更文挑战第28天】随着云计算的广泛应用,网络安全问题日益突出。本文将深入探讨云计算环境下的网络安全挑战,并提出有效的安全策略和措施。我们将分析云服务中的安全风险,探讨如何通过技术和管理措施来提升信息安全水平,包括加密技术、访问控制、安全审计等。此外,文章还将分享一些实用的代码示例,帮助读者更好地理解和应用这些安全策略。
|
18天前
|
安全 网络安全 数据安全/隐私保护
网络安全与信息安全:从漏洞到加密,保护数据的关键步骤
【10月更文挑战第24天】在数字化时代,网络安全和信息安全是维护个人隐私和企业资产的前线防线。本文将探讨网络安全中的常见漏洞、加密技术的重要性以及如何通过提高安全意识来防范潜在的网络威胁。我们将深入理解网络安全的基本概念,学习如何识别和应对安全威胁,并掌握保护信息不被非法访问的策略。无论你是IT专业人士还是日常互联网用户,这篇文章都将为你提供宝贵的知识和技能,帮助你在网络世界中更安全地航行。
|
21天前
|
存储 安全 网络安全
云计算与网络安全:如何保护您的数据
【10月更文挑战第21天】在这篇文章中,我们将探讨云计算和网络安全的关系。随着云计算的普及,网络安全问题日益突出。我们将介绍云服务的基本概念,以及如何通过网络安全措施来保护您的数据。最后,我们将提供一些代码示例,帮助您更好地理解这些概念。
|
1月前
|
SQL 安全 测试技术
网络安全与信息安全:保护数据的艺术
【9月更文挑战第36天】在数字化时代,网络安全和信息安全已成为维护个人隐私和企业资产的基石。本文深入探讨了网络安全漏洞、加密技术以及安全意识的重要性,旨在为读者提供一份知识宝典,帮助他们在网络世界中航行而不触礁。我们将从网络安全的基本概念出发,逐步深入到复杂的加密算法,最后强调培养安全意识的必要性。无论你是IT专业人士还是日常互联网用户,这篇文章都将为你打开一扇了解和实践网络安全的大门。
37 2
|
6月前
|
存储 Kubernetes 容器
百度搜索:蓝易云【Kubernetes使用helm部署NFS Provisioner】
现在,你已经成功使用Helm部署了NFS Provisioner,并且可以在Kubernetes中创建使用NFS存储的PersistentVolumeClaim。
205 10
|
6月前
百度搜索:蓝易云【什么是HTTP长轮询?】
现在,HTTP长轮询逐渐被WebSocket等更高效的实时通信技术所替代,但了解HTTP长轮询仍然有助于理解实时数据推送的基本原理。
128 9
|
6月前
|
移动开发 Shell Linux
百度搜索:蓝易云【Shell错误:/bin/bash^M: bad interpreter: No such file or directory】
将 `your_script.sh`替换为你的脚本文件名。运行此命令后,脚本文件的换行符将被转换为Linux格式,然后就可以在Linux系统上正常执行脚本了。
74 8
|
6月前
百度搜索:蓝易云【ipmitool配置BMC的ip】
以上操作将配置BMC的IP地址为新的值。请注意,操作BMC需要谨慎,确保你对服务器有足够的权限,并且仔细检查新的IP地址、子网掩码和默认网关,以免导致服务器网络失联。
102 7
|
6月前
|
Kubernetes 应用服务中间件 nginx
百度搜索:蓝易云【使用Kubernetes部署Nginx应用教程】
现在,你已经成功在Kubernetes集群上部署了Nginx应用。通过访问Service的外部IP地址,你可以访问Nginx服务。
84 4