• 基于Http协议实现网络爬虫读取数据


    一什么是Http协议

            HTTP就是目前使用最广泛的Web应用程序使用的基础协议,例如,浏览器访问网站, 手机App访问后台服务器,都是通过HTTP 协议实现的。HTTP 是HyperText Transfer Protocol的缩写,翻译为超文本传输协议,它是基于TCP协议之上的一种请求-响应协议。

            当浏览器希望访问某个网站时,浏览器和网站服务器之间首先建立TCP连接,且服务器总是使用80端口和加密端口443 ,然后,浏览器向服 务器发送一个HTTP请求,服务器收到后,返回一一个HTTP响应,并且在响应中包含了HTML 的网页内容,浏览器解析HTML后就可以给用户显示网页了。一个完整的HTTP 请求响应如下:

    1. GET / HTTP/1.1
    2. Host: www.sina.com.cn
    3. User-Agent: Mozilla/5 MSIE
    4. Accept: */* ┌────────┐
    5. ┌─────────┐ Accept-Language: zh-CN,en │░░░░░░░░│
    6. │O ░░░░░░░│───────────────────────────>├────────┤
    7. ├─────────┤<───────────────────────────│░░░░░░░░│
    8. │ │ HTTP/1.1 200 OK ├────────┤
    9. │ │ Content-Type: text/html │░░░░░░░░│
    10. └─────────┘ Content-Length: 133251 └────────┘
    11. Browser html> Server
    12. <html><body>
    13. <h1>Helloh1>
    14. ...

    HTTP请求的格式是固定的,它由HTTP Header和HTTP Body 两部分构成。第一行总是请求方法 路径HTTP版本:例如,GET / HTTP/1.1表示使用GET请求,路径是/,版本是HTTP/1.1
    后续的每一行都是固定的Header: Value格式,我们称为HTTP Header ,服务器依靠某些特定的Header来识别客户端请求,例如:
    Host :表示请求的域名,因为一台服务器上可能有多个网站,因此有必要依靠Host 来识别请求是发日给哪个网站的。
    User-Agent :表示客户端自身标识信息,不同的浏览器有不同的标识,服务器依靠User-Agent 判 断客户端类型是IE还是Chrome,是Firefox还是一个Python 爬虫;
    Accept :表示客户端能处理的HTTP响应格式,*/* 表示任意格式,text/* 表示任意文本,image/png表示PNG格式的图片;
    Accept-Language :表示客户端接收的语言,多种语言按优先级排序,服务器依靠该字段给用户返回特定语言的网页版本。

    注意:
    如果是GET 请求,那么该HTTP请求只有HTTP Header,没有 HTTP Body 。如果是POST请求,那么该请求,那就带有HTTP Body。

    HTTP响应也是由Header和Body组成的。

    1. HTTP/1.1 200 OK
    2. Content-Type: text/html
    3. Content-Length: 133251
    4. html>
    5. <html><body>
    6. <h1>Helloh1>
    7. ...

    下面使用java模拟对服务器的请求以及服务器的响应

    1. //模拟服务器使用TCP连接处理客户端的HTTP请求
    2. try (ServerSocket server = new ServerSocket(8080)) {
    3. while(true) {
    4. //获取客户端浏览器连接
    5. Socket browserClient = server.accept();
    6. // //读取客户端请求(request)
    7. // BufferedReader reader = new BufferedReader(new InputStreamReader(browserClient.getInputStream()));
    8. // String line = null;
    9. //
    10. // while((line = reader.readLine()) != null) {
    11. // System.out.println(line);
    12. // }
    13. //模拟服务器的响应(response)
    14. try(BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(browserClient.getOutputStream()));) {
    15. //响应头
    16. writer.write("HTTP/1.1 200 OK");
    17. writer.newLine();
    18. writer.newLine();
    19. //响应内容
    20. writer.write(UUID.randomUUID().toString());
    21. } catch (Exception e) {
    22. // TODO Auto-generated catch block
    23. e.printStackTrace();
    24. }
    25. }
    26. } catch (IOException e) {
    27. e.printStackTrace();
    28. }
    29. }

    二、HTTP编程之利用网络爬虫读取数据

    1.利用爬虫读取单张图片

    我们模拟爬出读取数据时,需要使用统一资源定位符URL,然后使用openConnection(),来打开连接,打开连接需要模拟用户来访问服务器,不能让服务器端发现我们是爬虫来读取数据,因此我们在请求的时候需要设置请求头的属性,之后使用“流”来读取图片,并保存在本地。

    由于读取的是单张照片,读写操作时,直接使用字节流进行读取

    示例代码:

    1. try {
    2. //统一资源定位符
    3. URL url = new URL("https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2874262709.webp");
    4. //打开连接
    5. HttpsURLConnection connection = (HttpsURLConnection)url.openConnection();
    6. //设置请求方式(GET)
    7. connection.setRequestMethod("GET");
    8. //设置请求Header属性
    9. connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.62");
    10. try(
    11. //读取图片
    12. BufferedInputStream bis = new BufferedInputStream(connection.getInputStream());
    13. //存储图片(写入输出图片的字节内容)
    14. BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("d:\\test\\img\\" + System.currentTimeMillis() + ".webp"));){
    15. int len = -1;
    16. //边读边写
    17. byte[] buff = new byte[1024];
    18. while((len = bis.read(buff)) != -1) {
    19. bos.write(buff, 0, len);
    20. }
    21. }
    22. } catch (MalformedURLException e) {
    23. e.printStackTrace();
    24. } catch (ProtocolException e) {
    25. e.printStackTrace();
    26. } catch (FileNotFoundException e) {
    27. e.printStackTrace();
    28. } catch (IOException e) {
    29. e.printStackTrace();
    30. }

    2.利用爬虫读取网页全部图片

    步骤与读取单张图片的步骤大致相似,不同的是URL就是当前网页的网址,进行读取时,使用的是字符流进行读取当前网页的HTML源码,通过纯字符串形式进行去除,然后只留下与图片相关的HTML标签,进行读取以及保存到本地。

    示例代码:

    1. try {
    2. //统一资源定位符
    3. URL movieHomeURL = new URL("https://movie.douban.com/");
    4. //打开连接
    5. HttpsURLConnection connection = (HttpsURLConnection)movieHomeURL.openConnection();
    6. //设置请求方式(GET)
    7. connection.setRequestMethod("GET");
    8. //设置请求Header属性
    9. connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.62");
    10. //读取网站源码
    11. BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),StandardCharsets.UTF_8));
    12. String line = null;
    13. while((line = reader.readLine()) != null) {
    14. //去除空格
    15. line = line.trim();
    16. //判断当前行是否包含海报图片路径
    17. if(line.contains("https://img") && line.contains(".jpg") && line.startsWith(")) {
    18. //提取图片的路径src和电影名称alt
    19. //System.out.println(line);
    20. int beginIndex =line.indexOf("https://");
    21. int endIndex = line.indexOf(".jpg") + 4;
    22. String src = line.substring(beginIndex, endIndex);
    23. beginIndex = line.indexOf("alt=") + 5;
    24. endIndex = line.indexOf("\"",beginIndex);
    25. String alt = line.substring(beginIndex, endIndex);
    26. //读取图片
    27. URL imageUrL = new URL(src);
    28. HttpsURLConnection imageConnection = (HttpsURLConnection)imageUrL.openConnection();
    29. try(BufferedInputStream in = new BufferedInputStream(imageConnection.getInputStream());
    30. BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("d:\\test\\img\\" + alt + ".jpg"));){
    31. //边读边写
    32. int len = -1;
    33. byte[] buff = new byte[1024];
    34. while((len = in.read(buff)) != -1) {
    35. out.write(buff, 0, len);
    36. }
    37. }
    38. }
    39. }
    40. } catch (MalformedURLException e) {
    41. e.printStackTrace();
    42. } catch (ProtocolException e) {
    43. e.printStackTrace();
    44. } catch (IOException e) {
    45. e.printStackTrace();
    46. }

    使用纯字符串进行截取图片的html标签不太方便,这是我们就使用jsoup解析html。这是我们就需要手动导入jar包。

    1. // 使用jsoup解析html
    2. // JSOUP类:进行原始解析
    3. // Document类:网页文档(包含解析到的所有标签
    4. // Elements类:若干元素Element形成的集合(继承自ArrayList)
    5. // Element类:某一个html元素
    6. String src = "", alt="";
    7. // 解析成Document对象
    8. Document doc = Jsoup.parse(line);
    9. // 从Document中获取名称为img的所有标签元素(Elements)
    10. // 从所有代表img的Elements元素集合中获取第一个
    11. Element imgElement = doc.getElementsByTag("img").get(0);
    12. // 获取img标签元素src属性和alt属性
    13. src = imgElement.attr("src");
    14. alt = imgElement.attr("alt");
    15. URL imageUrL = new URL(src);
    16. HttpsURLConnection imageConnection = (HttpsURLConnection)imageUrL.openConnection();

  • 相关阅读:
    Transformer 估算 101
    Springboot 集成 RabbitMq 实现消息确认机制
    比 Bloom Filter 节省25%空间!Ribbon Filter 在 Lindorm中的应用
    8年思科C语言程序员转web独立开发者年收入超10万美元
    “Ubuntu终端闪退”的解决方法
    GaussDB OLTP 云数据库配套工具DAS
    Java 中的面向数据编程
    多线程技术的历史发展与简单使用
    bulldog 靶机
    MYSQL入门与进阶(七)
  • 原文地址:https://blog.csdn.net/qq_59616295/article/details/125879259