java爬虫爬取新冠肺炎搜狗问答对

因为java课程设计需要设计一个新冠肺炎智能问答系统,需要从互联网上爬去有关的问答信息,经过尝试,发现百度知道与悟空问答的反爬机制较为全面,所以选择搜狗问答进行问答对爬取。

导入java爬虫包

使用java的HttpClient子项目进行爬虫,使用Jsoup进行网页解析。所以需要导入相应的java依赖。
maven:

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4.13</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.8</version>
        </dependency>

        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.12.1</version>
        </dependency>

这里注意如果是web项目,需要httpcore和httpclient依赖都是最高版本,否则会报HttpRquest错误。

分析网页

1、使用搜狗搜索关键词“新冠肺炎",分析URL:

https://www.sogou.com/sogou?query=%E6%96%B0%E5%86%A0%E8%82%BA%E7%82%8E&insite=wenwen.sogou.com&pid=sogou-wsse-a9e18cb5dd9d3ab4&rcer=&page=2&ie=utf8

可以发现page=""表示页数,所以可以通过改变page后的参数来设置爬取的页数。
2、F12查看网页源代码
在这里插入图片描述
这些a标签中的href就是每个问答对的链接,通过Jsoup的

select("a[target='_blank']");

可以爬去到这些href具体代码见下文。
3、分析具体问答网页
获取到上述链接后,对每一个链接进行访问,进入到详细的问答页面,同样F12查看网页源代码,找到问题和答案部分。
在这里插入图片描述
在这里插入图片描述
同样对他们的标签进行分析,使用Jsoup进行解析,代码见下文。
4、字符处理
可以看到网页源代码中的答案有许多无效字符,使用正则表达式进行无效字符的剔除即可。
问题字数较少,所以仅保留中文字符即可,正则表达式:

replaceAll("[^\\u4E00-\\u9FA5]","")

针对答案的特殊字符,使用如下正则表达式:

replaceAll("[\\u25c6~\\u25c7]|[\\——]|[\\▲]|[\\△]]","")

replaceAll是java的一个函数。

完整代码

public class Spider {
    //爬取搜狗问问页面的问答连接
    private static ArrayList<String> hrefList=new ArrayList();
    private static ArrayList<ArrayList<String>>questionAndAnswer=new ArrayList<>();
    public static ArrayList<ArrayList<String>> getQuestionAndAnswer() {
        return questionAndAnswer;
    }
    public static void getHref(int page){
        CloseableHttpClient httpClient=HttpClients.createDefault();
        CloseableHttpResponse response=null;
        //悟空问答,搜索新冠肺炎url
        HttpGet request=new HttpGet("https://www.sogou.com/sogou?query=%E6%96%B0%E5%86%A0%E8%82%BA%E7%82%8E&insite=wenwen.sogou.com&pid=sogou-wsse-a9e18cb5dd9d3ab4&rcer=&page="+page+"&ie=utf8");
        //模拟浏览器请求头
        request.setHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/74.0.3729.169 Safari/537.36");
        try{
            response=httpClient.execute(request);
            if(response.getStatusLine().getStatusCode()==HttpStatus.SC_OK){
                HttpEntity httpEntity = response.getEntity();
                String html = EntityUtils.toString(httpEntity, "utf-8");
                //System.out.println(html);
                Document document=Jsoup.parse(html);
                Elements postItems=document.getElementsByClass("fb");
                for(Element postItem:postItems){
                    Elements link=postItem.select( );
                    //System.out.println(link.attr("href"));
                    hrefList.add(link.attr("href"));
                }
            }else {
                System.out.println("返回状态不是200");
                System.out.println(EntityUtils.toString(response.getEntity(), "utf-8"));
            }
        }catch (ClientProtocolException e){System.out.print("客户端协议异常:"+e);}
        catch (IOException e){System.out.print("IO异常:"+e);}
        finally {
            HttpClientUtils.closeQuietly(response);
            HttpClientUtils.closeQuietly(httpClient);
        }
    }
    //返回一个数组,第一个元素为问题,第二个元素为答案
    public static ArrayList<String> getQuestionAndAnswer(String url){
        ArrayList<String>temp=new ArrayList<>();
        CloseableHttpClient httpClient=HttpClients.createDefault();
        CloseableHttpResponse response=null;
        //搜狗问问,搜索新冠肺炎url
        HttpGet request=new HttpGet(url);
        request.setHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/74.0.3729.169 Safari/537.36");
        try{
            response=httpClient.execute(request);
            if(response.getStatusLine().getStatusCode()==HttpStatus.SC_OK){
                HttpEntity httpEntity = response.getEntity();
                String html = EntityUtils.toString(httpEntity, "utf-8");
                //System.out.println(html);
                Document document=Jsoup.parse(html);
                Element title=document.getElementById("question_title");
                //System.out.print(title.text());
                temp.add(title.text().replaceAll("[^\\u4E00-\\u9FA5]",""));
                Elements preTag=document.getElementsByTag("pre");
                //System.out.print(preTag.get(0).text());
                temp.add(preTag.get(0).text().replaceAll("[\\u25c6~\\u25c7]|[\\——]|[\\▲]|[\\△]]",""));
            }else {
                System.out.println("返回状态不是200");
                System.out.println(EntityUtils.toString(response.getEntity(), "utf-8"));
            }
        }catch (ClientProtocolException e){System.out.print("客户端协议异常:"+e);}
        catch (IOException e){System.out.print("IO异常:"+e);}
        finally {
            HttpClientUtils.closeQuietly(response);
            HttpClientUtils.closeQuietly(httpClient);
        }
        return temp;
    }
    //爬取前maxPage页的问题与答案
    public static void spiderQuestionAndAnswer(int maxPage){
        for(int i=1;i<=maxPage;i++){
            getHref(i);
        }
        for(String href:hrefList){
            questionAndAnswer.add(getQuestionAndAnswer(href));
        }
    }
  public static void main(String[] args){
      int maxPage=3;
        spiderQuestionAndAnswer(maxPage);
        for(ArrayList<String>temp:questionAndAnswer){
            for(String qa:temp){
                System.out.println(qa);
            }
            System.out.println();
        }
        //正则表达式字符处理测试
        /*String temp="为阴性达到出院标准】,,,,▲◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇——————————";
        System.out.print(temp.replaceAll("[^\\u4E00-\\u9FA5]",""));*/
   }
}

新冠肺炎国内外疫情数据爬取见我的另一篇博客:
https://blog.csdn.net/NiZjiTouA/article/details/107094808

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

K_K_Chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值