当前位置: 首页 > news >正文

网络爬虫--生成假数据

爬取网址中的数据。

下面3个分别是姓、女孩名字、男孩名字的网址。 

        String familyURLStr = "http://www.baijiaxing.net.cn/";String girlNameURLStr = "https://wannianli.tianqi.com/qiming/news/16536.html";String boyNameURLStr = "https://wannianli.tianqi.com/qiming/news/883.html";

如何爬取呢?

1、首先有一个网址

这是一个百家姓的网址。

String familyURLStr = "http://www.baijiaxing.net.cn/";

 2、爬取网址中的全部数据

注意注释中的细节。

    //爬取全部数据private static String webUrl(String URLStr) throws IOException {//先转换为url对象URL url = new URL(URLStr);//打开连接URLConnection conn = url.openConnection();//利用IO流进行读取//1.由于url对象提供字节流进行读取,无法读取中文,所以转换为字符流InputStreamReader isr = new InputStreamReader(conn.getInputStream());//使用一次read()方法只能读取一个字符//使用sb把读取出来的字符存起来StringBuilder sb = new StringBuilder();int b;while ((b = isr.read()) != -1) {sb.append((char)b);}return sb.toString();}

输出结果是以下html这种格式的,由服务器传过来的原本就是html,只不过平时被浏览器解析了而已。

 3、提取需要的信息

对我们有用的只有其中的姓氏而已,所以利用正则表达式进行匹配。

①下面是利用正则表达式读取数据的代码:

    private static ArrayList<String> getData(String str, String regex) {ArrayList<String> list = new ArrayList<>();//转换为正则表达式对象Pattern pattern = Pattern.compile(regex);//将字符串与正则表达式进行匹配Matcher matcher = pattern.matcher(str);//是否有与正则表达式匹配的值,有则返回true,无则返回falsewhile (matcher.find()){//将匹配到的值进行返回list.add(matcher.group());}return list;}

②正则表达式如何书写?

观察百家姓可以看到都是4个汉字一组,并且后面跟着中文的","或者中文的"。",所以正则表达式可写为

".{4},|。"

输出结果如下:

输出为什么是这种格式?

因为这种情况下,把".{4},"看作一个逻辑,"。"看作一个逻辑,所以应该把,|。括起来,正确的是

.{4}(,|。)

但是又出现一个问题,返回结果我们只想要前面的4个汉字,不想要后面中文的","或者中文的"。",这种情况下有两种解决办法。

(1)这种需求很常见,所以专门提出了一个符号去解决这个问题,就是?=,将匹配结果进行返回时忽略?=后面的东西,但是匹配的时候还是参与的,因此正则表达式可写为

".{4}(?=,|。)"

(2)将正则表达式使用括号进行分组,然后在使用matcher.group()将匹配结果进行返回时,可以选择返回哪些组。

正则表达式可写为

"(.{4})(,|。)"

这种情况下,提取需要的数据的方法就需要额外加上一个参数,就是要返回的组号。

关于组号有一些说明:组号从1开始编,也存在一个特殊的0,表示全部数据。

    private static ArrayList<String> getData(String str, String regex, int index ) {ArrayList<String> list = new ArrayList<>();//转换为正则表达式对象Pattern pattern = Pattern.compile(regex);//将字符串与正则表达式进行匹配Matcher matcher = pattern.matcher(str);//是否有与正则表达式匹配的值,有则返回true,无则返回falsewhile (matcher.find()){//将匹配到的值进行返回list.add(matcher.group(index));}return list;}

返回结果:

错误1:在与网址建立连接时抛错:Server returned HTTP response code: 403 for URL,如下图:

解决办法:在建立完连接之后加上

conn.setRequestProperty("User-Agent", "Mozilla/4.76");
        //打开连接URLConnection conn = url.openConnection();conn.setRequestProperty("User-Agent", "Mozilla/4.76");

如何写女生名字的正则表达式呢? 

首先看到2个汉字一组,并且后面跟着中文的"、"或者中文的"。",所以正则表达式可写为

".{2}(?=、|。)"

返回结果如下:

可以看到把一些不是名字的汉字也给返回了,原因就是也符合正则表达式。那怎么解决呢?

把"露怡、琦倩、澜蕾、思琳、"看作一组进行匹配,正则表达式可写为

"(.{2}(、|。)){4}"

返回结果如下:

如何写男生名字的正则表达式呢? 

下面是一个男生名字的网址:

100个好听的男孩名字,古风儒雅、洒脱大气的好名字! - 知乎 (zhihu.com)

网址中的数据如下:

如果依旧按照前面的把4个看作一组进行匹配,会把前面的序号也进行匹配,这不是我们想要的,所以要限定为中文。

有一个插件AnyRule,可以搜索常见需求的正则表达式,鼠标右键一下可看到:

打开之后搜索中文的正则表达式:

复制:[\u4E00-\u9FA5]

因此正则表达式写为

"([\\u4E00-\\u9FA5]{2}(、|\\n)){4}"

输出结果一直为空,刚开始以为是正则表达式有问题,后面怀疑知乎是不是有反爬啊。

测试一下,输出爬取的全部数据:

答案确实是这样,知乎将数据处理成密文了,所以无法匹配到与正则表达式相符的数据,导致输出一直为空。

只能换个网址了。

换成这个:【男孩名字】好听的男孩名字大全_男孩独特少见的名字_男孩简单大气的名字_亲子百科_太平洋亲子网 (pcbaby.com.cn)

结果还是有问题,爬取的中文无法解析,是乱码的。 

又接连试了好几个网址,都是同样的问题,都怀疑是不是代码有问题了,于是又回去测试了一下姓的爬取,也没有问题啊。

只能不断寻找不乱码的网址,终于找到一个:

男宝宝起名大全 100个好听的男孩名字 - 万年历 (tianqi.com)

输出结果如下:

下面对爬取的数据再次进行处理:

首先对姓进行处理,对于集合中的一个元素来说是有4个姓的,所以现在要拆开。

代码如下:

可以看到有错误提示: 

使用强制类型转换无法将char转为String, 那怎么办呢?

解决办法就是使用+将字符和空字符串""进行拼接就可以转换了。

正确的代码如下:

    private static ArrayList<String> processData(ArrayList<String> familyNameTempList) {ArrayList<String> familyNameList = new ArrayList<>();for (String s : familyNameTempList) {for (int i = 0; i < s.length(); i++) {familyNameList.add("" + s.charAt(i));}}return familyNameList;}

对名字进行处理,代码如下:

    //由于男孩和女孩的格式差不多,由一个方法进行处理private static ArrayList<String> processName(ArrayList<String> nameTempList) {ArrayList<String> nameList = new ArrayList<>();for (String s : nameTempList) {String[] ss = s.split("、");for (String name : ss) {nameList.add(name);}}return nameList;}

姓和名处理之后的结果如下:

下面将姓和名进行拼接,生成姓名,代码如下:

    private static HashSet<String> getFullName(ArrayList<String> familyNameList, ArrayList<String> nameList, int number) {//由于名字不能重复,所以选用HashSet存HashSet<String> fullNamehs = new HashSet<>();for (int i = 0; i < number; i++) {//1.首先随机选取姓和名//没有使用随机数的方式,而是集合工具类的shuffle()方法Collections.shuffle(familyNameList);Collections.shuffle(nameList);//选取索引0处的元素String familyName = familyNameList.get(0);String name = nameList.get(0);//将姓和名进行拼接并添加到集合中fullNamehs.add(familyName + name);}return fullNamehs;}

生成指定格式的数据,代码如下:

     //生成男生信息private static HashSet<String> getBoyInfo(HashSet<String> fullBoyNamehs) {HashSet<String> infohs = new HashSet<>();//生成年龄Random r = new Random();for (String fullName : fullBoyNamehs) {int age = r.nextInt(10) + 18;infohs.add(fullName + "-男-" + age);}return infohs;}//生成女生信息private static HashSet<String> getGirlInfo(HashSet<String> fullGirlNamehs) {HashSet<String> infohs = new HashSet<>();//生成年龄Random r = new Random();for (String fullName : fullGirlNamehs) {int age = r.nextInt(8) + 18;infohs.add(fullName + "-女-" + age);}return infohs;}

 将其写入到外部设备中,代码如下:

    //写到外部设备中private static void writeInfo(HashSet<String> girlInfo, HashSet<String> boyInfo) throws IOException {ArrayList<String> infoList = new ArrayList<>();infoList.addAll(girlInfo);infoList.addAll(boyInfo);Collections.shuffle(infoList);BufferedWriter bw = new BufferedWriter(new FileWriter("name.txt"));for (String info : infoList) {bw.write(info);bw.newLine();}bw.close();}

可以看到已写入到文件中:

总结一下全部过程就是:爬取数据--对数据进行处理--写入文件。 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【零知识证明】构建第一个zk
  • python-带空格的数字层三角形
  • SQL视图:简化复杂查询的利器
  • 详细说一下MVCC
  • 电脑强制退出程序快捷键
  • redis内存数据库的专业术语雪崩、击穿、穿透的名词解释
  • 二分法介绍
  • Python生成指定数量的随机XML文件
  • 572. 另一棵树的子树
  • Python自动化:Excel根据IP匹配网段获取所属源端口
  • 探索OpenCV:图像处理基础与实践
  • 如何解决“Intel (R) Wireless-AC 9560 160MHz 设备无法启动“?
  • SpringBoot下调用kettle脚本
  • Linux--数据链路层(macarp)
  • 实战演练:利用京东API一键抓取商品详情
  • @angular/forms 源码解析之双向绑定
  • 【跃迁之路】【641天】程序员高效学习方法论探索系列(实验阶段398-2018.11.14)...
  • 0基础学习移动端适配
  • angular2开源库收集
  • CSS 提示工具(Tooltip)
  • CSS中外联样式表代表的含义
  • JavaScript学习总结——原型
  • JS 面试题总结
  • JS笔记四:作用域、变量(函数)提升
  • js递归,无限分级树形折叠菜单
  • laravel5.5 视图共享数据
  • Python中eval与exec的使用及区别
  • -- 查询加强-- 使用如何where子句进行筛选,% _ like的使用
  • 动态规划入门(以爬楼梯为例)
  • 回流、重绘及其优化
  • 深入 Nginx 之配置篇
  • 一、python与pycharm的安装
  • 一份游戏开发学习路线
  • 一起参Ember.js讨论、问答社区。
  • 我们雇佣了一只大猴子...
  • ​​​​​​​GitLab 之 GitLab-Runner 安装,配置与问题汇总
  • ​linux启动进程的方式
  • (17)Hive ——MR任务的map与reduce个数由什么决定?
  • (PADS学习)第二章:原理图绘制 第一部分
  • (Redis使用系列) SpringBoot中Redis的RedisConfig 二
  • (六)什么是Vite——热更新时vite、webpack做了什么
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (转)一些感悟
  • ***通过什么方式***网吧
  • .NET Core 2.1路线图
  • .Net MVC4 上传大文件,并保存表单
  • .NET 读取 JSON格式的数据
  • .NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接
  • .NET开源项目介绍及资源推荐:数据持久层
  • .sh文件怎么运行_创建优化的Go镜像文件以及踩过的坑
  • /usr/bin/perl:bad interpreter:No such file or directory 的解决办法
  • :not(:first-child)和:not(:last-child)的用法
  • @Repository 注解
  • @transaction 提交事务_【读源码】剖析TCCTransaction事务提交实现细节
  • [ CTF ] WriteUp- 2022年第三届“网鼎杯”网络安全大赛(朱雀组)