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

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

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

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

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

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

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

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

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

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

我们用百度知道搜索的时候可以看地址栏
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天前
|
数据可视化 数据挖掘
【视频】复杂网络分析CNA简介与R语言对婚礼数据聚类社区检测和可视化|数据分享
【视频】复杂网络分析CNA简介与R语言对婚礼数据聚类社区检测和可视化|数据分享
|
1天前
|
机器学习/深度学习 存储 监控
数据分享|Python卷积神经网络CNN身份识别图像处理在疫情防控下口罩识别、人脸识别
数据分享|Python卷积神经网络CNN身份识别图像处理在疫情防控下口罩识别、人脸识别
|
2天前
|
存储 SQL 安全
网络安全与信息安全:保护数据的关键策略
【4月更文挑战第24天】 在数字化时代,数据成为了新的货币。然而,随着网络攻击的日益猖獗,如何确保信息的安全和隐私成为了一个亟待解决的问题。本文将深入探讨网络安全漏洞的概念、加密技术的重要性以及提升安全意识的必要性,旨在为读者提供一套综合性的网络安全防护策略。通过对这些关键知识点的分享,我们希望能够增强个人和组织在面对网络威胁时的防御能力。
|
3天前
|
安全 JavaScript 前端开发
第十六届山东省职业院校技能大赛中职组 “网络安全”赛项竞赛试题—B模块安全事件响应/网络安全数据取证/应用安全
该内容描述了一次网络安全演练,包括七个部分:Linux渗透提权、内存取证、页面信息发现、数字取证调查、网络安全应急响应、Python代码分析和逆向分析。参与者需在模拟环境中收集Flag值,涉及任务如获取服务器信息、提权、解析内存片段、分析网络数据包、处理代码漏洞、解码逆向操作等。每个部分都列出了若干具体任务,要求提取或生成特定信息作为Flag提交。
6 0
|
3天前
|
安全 测试技术 网络安全
2024年山东省职业院校技能大赛中职组 “网络安全”赛项竞赛试题-C安全事件响应/网络安全数据取证/应用安全
B模块涵盖安全事件响应和应用安全,包括Windows渗透测试、页面信息发现、Linux系统提权及网络安全应急响应。在Windows渗透测试中,涉及系统服务扫描、DNS信息提取、管理员密码、.docx文件名及内容、图片中单词等Flag值。页面信息发现任务包括服务器端口、主页Flag、脚本信息、登录成功信息等。Linux系统渗透需收集SSH端口号、主机名、内核版本,并实现提权获取root目录内容和密码。网络安全应急响应涉及删除后门用户、找出ssh后门时间、恢复环境变量文件、识别修改的bin文件格式及定位挖矿病毒钱包地址。
9 0
|
3天前
|
安全 测试技术 Linux
2024年山东省职业院校技能大赛中职组 “网络安全”赛项竞赛试题-A模块安全事件响应/网络安全数据取证/应用安全
该内容描述了一个网络安全挑战,涉及Windows和Linux系统的渗透测试以及隐藏信息探索和内存取证。挑战包括使用Kali Linux对Windows Server进行服务扫描、DNS信息提取、密码获取、文件名和内容查找等。对于Linux系统,任务包括收集服务器信息、提权并查找特定文件内容和密码。此外,还有对Server2007网站的多步骤渗透,寻找登录界面和页面中的隐藏FLAG。最后,需要通过FTP获取win20230306服务器的内存片段,从中提取密码、地址、主机名、挖矿程序信息和浏览器搜索关键词。
6 0
|
3天前
|
安全 测试技术 网络安全
2024年甘肃省职业院校技能大赛中职组 “网络安全”赛项竞赛样题-C模块安全事件响应/网络安全数据取证/应用安全
涉及安全事件响应和应用安全测试。需使用Kali对Windows Server2105进行渗透测试,包括服务扫描、DNS信息提取、管理员密码、文件名与内容、图片中单词等。另外,需收集win20230305的服务器端口、页面信息、脚本、登录后信息等。在Linux Server2214上,要获取SSH端口、主机名、内核版本并进行提权操作。网络安全响应针对Server2228,涉及删除后门用户、查找SSH后门时间、恢复环境变量、识别篡改文件格式和矿池钱包地址。最后,对lin20230509进行网站渗透,获取端口号、数据库服务版本、脚本创建时间、页面路径、内核版本和root目录下的flag文件内容
6 0
|
14天前
|
数据采集 存储 API
网络爬虫与数据采集:使用Python自动化获取网页数据
【4月更文挑战第12天】本文介绍了Python网络爬虫的基础知识,包括网络爬虫概念(请求网页、解析、存储数据和处理异常)和Python常用的爬虫库requests(发送HTTP请求)与BeautifulSoup(解析HTML)。通过基本流程示例展示了如何导入库、发送请求、解析网页、提取数据、存储数据及处理异常。还提到了Python爬虫的实际应用,如获取新闻数据和商品信息。
|
18天前
|
数据采集 Python
【python】爬虫-西安医学院-校长信箱
本文以西安医学院-校长信箱为基础来展示爬虫案例。来介绍python爬虫。
【python】爬虫-西安医学院-校长信箱
|
1月前
|
数据采集 Python
爬虫实战-Python爬取百度当天热搜内容
爬虫实战-Python爬取百度当天热搜内容
72 0