├── .gitignore ├── README.md ├── img ├── .DS_Store └── maingui.jpg └── weiboPicDownloader ├── pom.xml └── src └── main └── java └── weibo ├── DateChooser.java ├── FileUtils.java ├── ImageDownloadTask.java ├── MainGui.java ├── WeiboDownloader.java └── WeiboUtils.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | .idea 3 | .settings 4 | .classpath 5 | .project 6 | target -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 免登录下载微博图片 2 | 3 | 批量下载特定用户的高清大图。 4 | 5 | ## 用法 6 | 7 | 编译,使用`MainGui`主类运行 8 | 9 | ![主页面](img/maingui.jpg) 10 | 1. ~~按照需求点入相应的信息~~ 由于微博接口变动 目前支持根据ID下载 11 | 2. 如果对账号类型有疑问的话,可以参考[我的博客](https://www.cnblogs.com/yanximin/p/10982235.html) 12 | 3. 等待下载完成即可. So Easy! 13 | 14 | ## 更新说明 15 | - 2017年9月18日 16 | - 修复显示文件下载目录时出现的ID重复问题 17 | - 优化代码 18 | - 服务器上没有后缀名的图片默认设置为`jpg`格式 19 | - 2017年9月17日 20 | - 重构代码 21 | - 增加了多线程下载,下图的速度更快了~ 22 | - 修复下载GIF图片时后缀不显示为`gif`的问题 23 | - 2018年3月8日 24 | - 根据[Issue#6](https://github.com/yAnXImIN/weiboPicDownloader/issues/6)的反馈,修正图片URL获取方式。感谢反馈者**idtolerate**!他发现了问题并且提出了修复代码 25 | - 重新编译了可执行JAR文件。注意该文件需要在JDK 1.7+上才能运行 26 | - 2019年10月24日 27 | - 增加GUI,操作更加人性化。 28 | - 新增时间选择 29 | - 修复几处BUG 30 | - 采用JDK8编译 31 | - 2019年12月26日 32 | - 修复微博数量过多导致的崩溃 33 | - 2021年7月31日 34 | - 去除不支持的下载类型,去除bin文件,执行需要自行编译 35 | 36 | ## Python移植版本 37 | [ningshu/weiboPicDownloader](https://github.com/ningshu/weiboPicDownloader) 38 | [nondanee/weiboPicDownloader](https://github.com/nondanee/weiboPicDownloader) 39 | 40 | 点个Star再走呗~ 41 | 欢迎Fork, 或者PR 42 | -------------------------------------------------------------------------------- /img/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yAnXImIN/weiboPicDownloader/25143a1ddaa4b6ab705869c0af5b31163a72e433/img/.DS_Store -------------------------------------------------------------------------------- /img/maingui.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yAnXImIN/weiboPicDownloader/25143a1ddaa4b6ab705869c0af5b31163a72e433/img/maingui.jpg -------------------------------------------------------------------------------- /weiboPicDownloader/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | yxm 5 | weiboPicDownloader 6 | 0.0.1-SNAPSHOT 7 | 8 | 9 | org.apache.httpcomponents 10 | httpmime 11 | 4.5.3 12 | 13 | 14 | com.google.code.gson 15 | gson 16 | 2.8.1 17 | 18 | 19 | commons-io 20 | commons-io 21 | 2.7 22 | 23 | 24 | 25 | 26 | 27 | org.apache.maven.plugins 28 | maven-compiler-plugin 29 | 30 | 1.8 31 | 1.8 32 | utf-8 33 | 34 | 35 | 36 | 37 | 38 | 39 | 1.8 40 | 1.8 41 | 42 | -------------------------------------------------------------------------------- /weiboPicDownloader/src/main/java/weibo/DateChooser.java: -------------------------------------------------------------------------------- 1 | package weibo; 2 | 3 | /** 4 | 5 | * ClassName:DateChooser 6 | 7 | * Copyright: copyright (c)2012 8 | 9 | * @author Deng Zhiguang 10 | 11 | * http://zgdeng.iteye.com 12 | 13 | * @Date 2012-2-7 14 | 15 | * Modification History: 16 | 17 | * Date Author Version Reason 18 | 19 | * ------------------------------------------ 20 | 21 | */ 22 | 23 | import java.awt.BasicStroke; 24 | 25 | import java.awt.BorderLayout; 26 | 27 | import java.awt.Color; 28 | 29 | import java.awt.Component; 30 | 31 | import java.awt.Cursor; 32 | 33 | import java.awt.Dimension; 34 | 35 | import java.awt.Font; 36 | 37 | import java.awt.Graphics; 38 | 39 | import java.awt.Graphics2D; 40 | 41 | import java.awt.GridLayout; 42 | 43 | import java.awt.Point; 44 | 45 | import java.awt.Polygon; 46 | 47 | import java.awt.Stroke; 48 | 49 | import java.awt.Toolkit; 50 | 51 | import java.awt.event.FocusEvent; 52 | 53 | import java.awt.event.FocusListener; 54 | 55 | import java.awt.event.MouseAdapter; 56 | 57 | import java.awt.event.MouseEvent; 58 | 59 | import java.awt.event.MouseListener; 60 | 61 | import java.awt.event.MouseMotionListener; 62 | 63 | import java.text.SimpleDateFormat; 64 | 65 | import java.util.ArrayList; 66 | 67 | import java.util.Calendar; 68 | 69 | import java.util.Comparator; 70 | 71 | import java.util.Date; 72 | 73 | import java.util.List; 74 | 75 | 76 | 77 | import javax.swing.BorderFactory; 78 | 79 | import javax.swing.JComponent; 80 | 81 | 82 | import javax.swing.JLabel; 83 | 84 | import javax.swing.JPanel; 85 | 86 | import javax.swing.JTextField; 87 | 88 | import javax.swing.Popup; 89 | 90 | import javax.swing.PopupFactory; 91 | 92 | import javax.swing.SwingUtilities; 93 | 94 | import javax.swing.event.AncestorEvent; 95 | 96 | import javax.swing.event.AncestorListener; 97 | 98 | 99 | 100 | /** 101 | 102 | * 日期选择器,可以指定日期的显示格式 103 | 104 | */ 105 | 106 | public class DateChooser extends JPanel { 107 | 108 | 109 | 110 | private static final long serialVersionUID = 4529266044762990227L; 111 | 112 | 113 | 114 | private Date initDate; 115 | 116 | private Calendar now = Calendar.getInstance(); 117 | 118 | private Calendar select; 119 | 120 | private JPanel monthPanel;//月历 121 | 122 | private JP1 jp1;//四块面板,组成 123 | 124 | private JP2 jp2; 125 | 126 | private JP3 jp3; 127 | 128 | private JP4 jp4; 129 | 130 | private Font font = new Font("宋体", Font.PLAIN, 12); 131 | 132 | private final LabelManager lm = new LabelManager(); 133 | 134 | private SimpleDateFormat sdf; 135 | 136 | private boolean isShow = false; 137 | 138 | private Popup pop; 139 | 140 | 141 | 142 | private JComponent showDate; 143 | 144 | 145 | 146 | public static DateChooser getInstance() { 147 | 148 | return new DateChooser(); 149 | 150 | } 151 | 152 | 153 | 154 | public static DateChooser getInstance(Date date) { 155 | 156 | return new DateChooser(date); 157 | 158 | } 159 | 160 | 161 | 162 | public static DateChooser getInstance(String format) { 163 | 164 | return new DateChooser(format); 165 | 166 | } 167 | 168 | 169 | 170 | public static DateChooser getInstance(Date date, String format) { 171 | 172 | return new DateChooser(date, format); 173 | 174 | } 175 | 176 | 177 | 178 | /** 179 | 180 | * Creates a new instance of DateChooser 181 | 182 | */ 183 | 184 | private DateChooser() { 185 | 186 | this(new Date()); 187 | 188 | } 189 | 190 | 191 | 192 | private DateChooser(Date date) { 193 | 194 | this(date, "yyyy年MM月dd日"); 195 | 196 | } 197 | 198 | 199 | 200 | private DateChooser(String format) { 201 | 202 | this(new Date(), format); 203 | 204 | } 205 | 206 | 207 | 208 | private DateChooser(Date date, String format) { 209 | 210 | initDate = date; 211 | 212 | sdf = new SimpleDateFormat(format); 213 | 214 | select = Calendar.getInstance(); 215 | 216 | select.setTime(initDate); 217 | 218 | initPanel(); 219 | 220 | } 221 | 222 | 223 | 224 | /** 225 | 226 | * 是否允许用户选择 227 | 228 | */ 229 | 230 | public void setEnabled(boolean b) { 231 | 232 | super.setEnabled(b); 233 | 234 | showDate.setEnabled(b); 235 | 236 | } 237 | 238 | 239 | 240 | /** 241 | 242 | *得到当前选择框的日期 243 | 244 | */ 245 | 246 | public Date getDate() { 247 | 248 | return select.getTime(); 249 | 250 | } 251 | 252 | 253 | 254 | public String getStrDate() { 255 | 256 | return sdf.format(select.getTime()); 257 | 258 | } 259 | 260 | 261 | 262 | public String getStrDate(String format) { 263 | 264 | sdf = new SimpleDateFormat(format); 265 | 266 | return sdf.format(select.getTime()); 267 | 268 | } 269 | 270 | 271 | 272 | //根据初始化的日期,初始化面板 273 | 274 | private void initPanel() { 275 | 276 | monthPanel = new JPanel(new BorderLayout()); 277 | 278 | monthPanel.setBorder(BorderFactory.createLineBorder(Color.BLUE)); 279 | 280 | JPanel up = new JPanel(new BorderLayout()); 281 | 282 | up.add(jp1 = new JP1(), BorderLayout.NORTH); 283 | 284 | up.add(jp2 = new JP2(), BorderLayout.CENTER); 285 | 286 | monthPanel.add(jp3 = new JP3(), BorderLayout.CENTER); 287 | 288 | monthPanel.add(up, BorderLayout.NORTH); 289 | 290 | monthPanel.add(jp4 = new JP4(), BorderLayout.SOUTH); 291 | 292 | this.addAncestorListener(new AncestorListener() { 293 | 294 | public void ancestorAdded(AncestorEvent event) { 295 | 296 | 297 | 298 | } 299 | 300 | 301 | 302 | public void ancestorRemoved(AncestorEvent event) { 303 | 304 | 305 | 306 | } 307 | 308 | 309 | 310 | //只要祖先组件一移动,马上就让popup消失 311 | 312 | public void ancestorMoved(AncestorEvent event) { 313 | 314 | hidePanel(); 315 | 316 | } 317 | 318 | }); 319 | 320 | } 321 | 322 | 323 | 324 | public void register(final JComponent showDate) { 325 | 326 | this.showDate = showDate; 327 | 328 | 329 | 330 | showDate.setRequestFocusEnabled(true); 331 | 332 | showDate.addMouseListener(new MouseAdapter() { 333 | 334 | public void mousePressed(MouseEvent me) { 335 | 336 | showDate.requestFocusInWindow(); 337 | 338 | } 339 | 340 | }); 341 | 342 | this.setBackground(Color.WHITE); 343 | 344 | this.add(showDate, BorderLayout.CENTER); 345 | 346 | this.setPreferredSize(new Dimension(90, 25)); 347 | 348 | this.setBorder(BorderFactory.createLineBorder(Color.GRAY)); 349 | 350 | showDate.addMouseListener(new MouseAdapter() { 351 | 352 | public void mouseEntered(MouseEvent me) { 353 | 354 | if (showDate.isEnabled()) { 355 | 356 | showDate.setCursor(new Cursor(Cursor.HAND_CURSOR)); 357 | 358 | showDate.setForeground(Color.RED); 359 | 360 | } 361 | 362 | } 363 | 364 | 365 | 366 | public void mouseExited(MouseEvent me) { 367 | 368 | if (showDate.isEnabled()) { 369 | 370 | showDate.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 371 | 372 | showDate.setForeground(Color.BLACK); 373 | 374 | } 375 | 376 | } 377 | 378 | 379 | 380 | public void mousePressed(MouseEvent me) { 381 | 382 | if (showDate.isEnabled()) { 383 | 384 | showDate.setForeground(Color.CYAN); 385 | 386 | if (isShow) { 387 | 388 | hidePanel(); 389 | 390 | } else { 391 | 392 | showPanel(showDate); 393 | 394 | } 395 | 396 | } 397 | 398 | } 399 | 400 | 401 | 402 | public void mouseReleased(MouseEvent me) { 403 | 404 | if (showDate.isEnabled()) { 405 | 406 | showDate.setForeground(Color.BLACK); 407 | 408 | } 409 | 410 | } 411 | 412 | }); 413 | 414 | showDate.addFocusListener(new FocusListener() { 415 | 416 | public void focusLost(FocusEvent e) { 417 | 418 | hidePanel(); 419 | 420 | } 421 | 422 | 423 | 424 | public void focusGained(FocusEvent e) { 425 | 426 | 427 | 428 | } 429 | 430 | }); 431 | 432 | } 433 | 434 | 435 | 436 | //根据新的日期刷新 437 | 438 | private void refresh() { 439 | 440 | jp1.updateDate(); 441 | 442 | jp2.updateDate(); 443 | 444 | jp3.updateDate(); 445 | 446 | jp4.updateDate(); 447 | 448 | SwingUtilities.updateComponentTreeUI(this); 449 | 450 | } 451 | 452 | 453 | 454 | //提交日期 455 | 456 | private void commit() { 457 | 458 | if (showDate instanceof JTextField) { 459 | 460 | ((JTextField) showDate).setText(sdf.format(select.getTime())); 461 | 462 | }else if (showDate instanceof JLabel) { 463 | 464 | ((JLabel) showDate).setText(sdf.format(select.getTime())); 465 | 466 | } 467 | 468 | 469 | 470 | hidePanel(); 471 | 472 | } 473 | 474 | 475 | 476 | //隐藏日期选择面板 477 | 478 | private void hidePanel() { 479 | 480 | if (pop != null) { 481 | 482 | isShow = false; 483 | 484 | pop.hide(); 485 | 486 | pop = null; 487 | 488 | } 489 | 490 | } 491 | 492 | 493 | 494 | //显示日期选择面板 495 | 496 | private void showPanel(Component owner) { 497 | 498 | if (pop != null) { 499 | 500 | pop.hide(); 501 | 502 | } 503 | 504 | Point show = new Point(0, showDate.getHeight()); 505 | 506 | SwingUtilities.convertPointToScreen(show, showDate); 507 | 508 | Dimension size = Toolkit.getDefaultToolkit().getScreenSize(); 509 | 510 | int x = show.x; 511 | 512 | int y = show.y; 513 | 514 | if (x < 0) { 515 | 516 | x = 0; 517 | 518 | } 519 | 520 | if (x > size.width - 295) { 521 | 522 | x = size.width - 295; 523 | 524 | } 525 | 526 | if (y < size.height - 170) { 527 | 528 | } else { 529 | 530 | y -= 188; 531 | 532 | } 533 | 534 | pop = PopupFactory.getSharedInstance().getPopup(owner, monthPanel, x, y); 535 | 536 | pop.show(); 537 | 538 | isShow = true; 539 | 540 | } 541 | 542 | 543 | 544 | /** 545 | 546 | * 最上面的面板用来显示月份的增减 547 | 548 | */ 549 | 550 | private class JP1 extends JPanel { 551 | 552 | private static final long serialVersionUID = -5638853772805561174L; 553 | 554 | JLabel yearleft, yearright, monthleft, monthright, center, centercontainer; 555 | 556 | 557 | 558 | public JP1() { 559 | 560 | super(new BorderLayout()); 561 | 562 | this.setBackground(new Color(160, 185, 215)); 563 | 564 | initJP1(); 565 | 566 | } 567 | 568 | 569 | 570 | private void initJP1() { 571 | 572 | yearleft = new JLabel(" <<", JLabel.CENTER); 573 | 574 | yearleft.setToolTipText("上一年"); 575 | 576 | yearright = new JLabel(">> ", JLabel.CENTER); 577 | 578 | yearright.setToolTipText("下一年"); 579 | 580 | yearleft.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0)); 581 | 582 | yearright.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0)); 583 | 584 | 585 | 586 | monthleft = new JLabel(" <", JLabel.RIGHT); 587 | 588 | monthleft.setToolTipText("上一月"); 589 | 590 | monthright = new JLabel("> ", JLabel.LEFT); 591 | 592 | monthright.setToolTipText("下一月"); 593 | 594 | monthleft.setBorder(BorderFactory.createEmptyBorder(2, 30, 0, 0)); 595 | 596 | monthright.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 30)); 597 | 598 | 599 | 600 | centercontainer = new JLabel("", JLabel.CENTER); 601 | 602 | centercontainer.setLayout(new BorderLayout()); 603 | 604 | center = new JLabel("", JLabel.CENTER); 605 | 606 | 607 | 608 | centercontainer.add(monthleft, BorderLayout.WEST); 609 | 610 | centercontainer.add(center, BorderLayout.CENTER); 611 | 612 | centercontainer.add(monthright, BorderLayout.EAST); 613 | 614 | 615 | 616 | this.add(yearleft, BorderLayout.WEST); 617 | 618 | this.add(centercontainer, BorderLayout.CENTER); 619 | 620 | this.add(yearright, BorderLayout.EAST); 621 | 622 | this.setPreferredSize(new Dimension(295, 25)); 623 | 624 | 625 | 626 | updateDate(); 627 | 628 | 629 | 630 | yearleft.addMouseListener(new MouseAdapter() { 631 | 632 | public void mouseEntered(MouseEvent me) { 633 | 634 | yearleft.setCursor(new Cursor(Cursor.HAND_CURSOR)); 635 | 636 | yearleft.setForeground(Color.RED); 637 | 638 | } 639 | 640 | 641 | 642 | public void mouseExited(MouseEvent me) { 643 | 644 | yearleft.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 645 | 646 | yearleft.setForeground(Color.BLACK); 647 | 648 | } 649 | 650 | 651 | 652 | public void mousePressed(MouseEvent me) { 653 | 654 | select.add(Calendar.YEAR, -1); 655 | 656 | yearleft.setForeground(Color.WHITE); 657 | 658 | refresh(); 659 | 660 | } 661 | 662 | 663 | 664 | public void mouseReleased(MouseEvent me) { 665 | 666 | yearleft.setForeground(Color.BLACK); 667 | 668 | } 669 | 670 | }); 671 | 672 | yearright.addMouseListener(new MouseAdapter() { 673 | 674 | public void mouseEntered(MouseEvent me) { 675 | 676 | yearright.setCursor(new Cursor(Cursor.HAND_CURSOR)); 677 | 678 | yearright.setForeground(Color.RED); 679 | 680 | } 681 | 682 | 683 | 684 | public void mouseExited(MouseEvent me) { 685 | 686 | yearright.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 687 | 688 | yearright.setForeground(Color.BLACK); 689 | 690 | } 691 | 692 | 693 | 694 | public void mousePressed(MouseEvent me) { 695 | 696 | select.add(Calendar.YEAR, 1); 697 | 698 | yearright.setForeground(Color.WHITE); 699 | 700 | refresh(); 701 | 702 | } 703 | 704 | 705 | 706 | public void mouseReleased(MouseEvent me) { 707 | 708 | yearright.setForeground(Color.BLACK); 709 | 710 | } 711 | 712 | }); 713 | 714 | monthleft.addMouseListener(new MouseAdapter() { 715 | 716 | public void mouseEntered(MouseEvent me) { 717 | 718 | monthleft.setCursor(new Cursor(Cursor.HAND_CURSOR)); 719 | 720 | monthleft.setForeground(Color.RED); 721 | 722 | } 723 | 724 | 725 | 726 | public void mouseExited(MouseEvent me) { 727 | 728 | monthleft.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 729 | 730 | monthleft.setForeground(Color.BLACK); 731 | 732 | } 733 | 734 | 735 | 736 | public void mousePressed(MouseEvent me) { 737 | 738 | select.add(Calendar.MONTH, -1); 739 | 740 | monthleft.setForeground(Color.WHITE); 741 | 742 | refresh(); 743 | 744 | } 745 | 746 | 747 | 748 | public void mouseReleased(MouseEvent me) { 749 | 750 | monthleft.setForeground(Color.BLACK); 751 | 752 | } 753 | 754 | }); 755 | 756 | monthright.addMouseListener(new MouseAdapter() { 757 | 758 | public void mouseEntered(MouseEvent me) { 759 | 760 | monthright.setCursor(new Cursor(Cursor.HAND_CURSOR)); 761 | 762 | monthright.setForeground(Color.RED); 763 | 764 | } 765 | 766 | 767 | 768 | public void mouseExited(MouseEvent me) { 769 | 770 | monthright.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 771 | 772 | monthright.setForeground(Color.BLACK); 773 | 774 | } 775 | 776 | 777 | 778 | public void mousePressed(MouseEvent me) { 779 | 780 | select.add(Calendar.MONTH, 1); 781 | 782 | monthright.setForeground(Color.WHITE); 783 | 784 | refresh(); 785 | 786 | } 787 | 788 | 789 | 790 | public void mouseReleased(MouseEvent me) { 791 | 792 | monthright.setForeground(Color.BLACK); 793 | 794 | } 795 | 796 | }); 797 | 798 | } 799 | 800 | 801 | 802 | private void updateDate() { 803 | 804 | center.setText(select.get(Calendar.YEAR) + "年" + (select.get(Calendar.MONTH) + 1) + "月"); 805 | 806 | } 807 | 808 | } 809 | 810 | 811 | 812 | private class JP2 extends JPanel { 813 | 814 | private static final long serialVersionUID = -8176264838786175724L; 815 | 816 | 817 | 818 | public JP2() { 819 | 820 | this.setPreferredSize(new Dimension(295, 20)); 821 | 822 | } 823 | 824 | 825 | 826 | protected void paintComponent(Graphics g) { 827 | 828 | g.setFont(font); 829 | 830 | g.drawString("星期日 星期一 星期二 星期三 星期四 星期五 星期六", 5, 10); 831 | 832 | g.drawLine(0, 15, getWidth(), 15); 833 | 834 | } 835 | 836 | 837 | 838 | private void updateDate() { 839 | 840 | 841 | 842 | } 843 | 844 | } 845 | 846 | 847 | 848 | private class JP3 extends JPanel { 849 | 850 | private static final long serialVersionUID = 43157272447522985L; 851 | 852 | 853 | 854 | public JP3() { 855 | 856 | super(new GridLayout(6, 7)); 857 | 858 | this.setPreferredSize(new Dimension(295, 100)); 859 | 860 | initJP3(); 861 | 862 | } 863 | 864 | 865 | 866 | private void initJP3() { 867 | 868 | updateDate(); 869 | 870 | } 871 | 872 | 873 | 874 | public void updateDate() { 875 | 876 | this.removeAll(); 877 | 878 | lm.clear(); 879 | 880 | Date temp = select.getTime(); 881 | 882 | Calendar select = Calendar.getInstance(); 883 | 884 | select.setTime(temp); 885 | 886 | select.set(Calendar.DAY_OF_MONTH, 1); 887 | 888 | int index = select.get(Calendar.DAY_OF_WEEK); 889 | 890 | int sum = (index == 1 ? 8 : index); 891 | 892 | select.add(Calendar.DAY_OF_MONTH, 0 - sum); 893 | 894 | for (int i = 0; i < 42; i++) { 895 | 896 | select.add(Calendar.DAY_OF_MONTH, 1); 897 | 898 | lm.addLabel(new MyLabel(select.get(Calendar.YEAR), select.get(Calendar.MONTH), select.get(Calendar.DAY_OF_MONTH))); 899 | 900 | } 901 | 902 | for (MyLabel my : lm.getLabels()) { 903 | 904 | this.add(my); 905 | 906 | } 907 | 908 | select.setTime(temp); 909 | 910 | } 911 | 912 | } 913 | 914 | 915 | 916 | private class MyLabel extends JLabel implements Comparator, MouseListener, MouseMotionListener { 917 | 918 | private static final long serialVersionUID = 3668734399227577214L; 919 | 920 | private int year, month, day; 921 | 922 | private boolean isSelected; 923 | 924 | 925 | 926 | public MyLabel(int year, int month, int day) { 927 | 928 | super("" + day, JLabel.CENTER); 929 | 930 | this.year = year; 931 | 932 | this.day = day; 933 | 934 | this.month = month; 935 | 936 | this.addMouseListener(this); 937 | 938 | this.addMouseMotionListener(this); 939 | 940 | this.setFont(font); 941 | 942 | if (month == select.get(Calendar.MONTH)) { 943 | 944 | this.setForeground(Color.BLACK); 945 | 946 | } else { 947 | 948 | this.setForeground(Color.LIGHT_GRAY); 949 | 950 | } 951 | 952 | if (day == select.get(Calendar.DAY_OF_MONTH)) { 953 | 954 | this.setBackground(new Color(160, 185, 215)); 955 | 956 | } else { 957 | 958 | this.setBackground(Color.WHITE); 959 | 960 | } 961 | 962 | } 963 | 964 | 965 | 966 | public boolean getIsSelected() { 967 | 968 | return isSelected; 969 | 970 | } 971 | 972 | 973 | 974 | public void setSelected(boolean b, boolean isDrag) { 975 | 976 | isSelected = b; 977 | 978 | if (b && !isDrag) { 979 | 980 | int temp = select.get(Calendar.MONTH); 981 | 982 | select.set(year, month, day); 983 | 984 | if (temp == month) { 985 | 986 | SwingUtilities.updateComponentTreeUI(jp3); 987 | 988 | } else { 989 | 990 | refresh(); 991 | 992 | } 993 | 994 | } 995 | 996 | this.repaint(); 997 | 998 | } 999 | 1000 | 1001 | 1002 | protected void paintComponent(Graphics g) { 1003 | 1004 | if (day == select.get(Calendar.DAY_OF_MONTH) && month == select.get(Calendar.MONTH)) { 1005 | 1006 | //如果当前日期是选择日期,则高亮显示 1007 | 1008 | g.setColor(new Color(160, 185, 215)); 1009 | 1010 | g.fillRect(0, 0, getWidth(), getHeight()); 1011 | 1012 | } 1013 | 1014 | if (year == now.get(Calendar.YEAR) && month == now.get(Calendar.MONTH) && day == now.get(Calendar.DAY_OF_MONTH)) { 1015 | 1016 | //如果日期和当前日期一样,则用红框 1017 | 1018 | Graphics2D gd = (Graphics2D) g; 1019 | 1020 | gd.setColor(Color.RED); 1021 | 1022 | Polygon p = new Polygon(); 1023 | 1024 | p.addPoint(0, 0); 1025 | 1026 | p.addPoint(getWidth() - 1, 0); 1027 | 1028 | p.addPoint(getWidth() - 1, getHeight() - 1); 1029 | 1030 | p.addPoint(0, getHeight() - 1); 1031 | 1032 | gd.drawPolygon(p); 1033 | 1034 | } 1035 | 1036 | if (isSelected) {//如果被选中了就画出一个虚线框出来 1037 | 1038 | Stroke s = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL, 1.0f, new float[] { 2.0f, 2.0f }, 1.0f); 1039 | 1040 | Graphics2D gd = (Graphics2D) g; 1041 | 1042 | gd.setStroke(s); 1043 | 1044 | gd.setColor(Color.BLACK); 1045 | 1046 | Polygon p = new Polygon(); 1047 | 1048 | p.addPoint(0, 0); 1049 | 1050 | p.addPoint(getWidth() - 1, 0); 1051 | 1052 | p.addPoint(getWidth() - 1, getHeight() - 1); 1053 | 1054 | p.addPoint(0, getHeight() - 1); 1055 | 1056 | gd.drawPolygon(p); 1057 | 1058 | } 1059 | 1060 | super.paintComponent(g); 1061 | 1062 | } 1063 | 1064 | 1065 | 1066 | public boolean contains(Point p) { 1067 | 1068 | return this.getBounds().contains(p); 1069 | 1070 | } 1071 | 1072 | 1073 | 1074 | private void update() { 1075 | 1076 | repaint(); 1077 | 1078 | } 1079 | 1080 | 1081 | 1082 | public void mouseClicked(MouseEvent e) { 1083 | 1084 | } 1085 | 1086 | 1087 | 1088 | public void mousePressed(MouseEvent e) { 1089 | 1090 | isSelected = true; 1091 | 1092 | update(); 1093 | 1094 | } 1095 | 1096 | 1097 | 1098 | public void mouseReleased(MouseEvent e) { 1099 | 1100 | Point p = SwingUtilities.convertPoint(this, e.getPoint(), jp3); 1101 | 1102 | lm.setSelect(p, false); 1103 | 1104 | commit(); 1105 | 1106 | } 1107 | 1108 | 1109 | 1110 | public void mouseEntered(MouseEvent e) { 1111 | 1112 | } 1113 | 1114 | 1115 | 1116 | public void mouseExited(MouseEvent e) { 1117 | 1118 | } 1119 | 1120 | 1121 | 1122 | public void mouseDragged(MouseEvent e) { 1123 | 1124 | Point p = SwingUtilities.convertPoint(this, e.getPoint(), jp3); 1125 | 1126 | lm.setSelect(p, true); 1127 | 1128 | } 1129 | 1130 | 1131 | 1132 | public void mouseMoved(MouseEvent e) { 1133 | 1134 | } 1135 | 1136 | 1137 | 1138 | public int compare(MyLabel o1, MyLabel o2) { 1139 | 1140 | Calendar c1 = Calendar.getInstance(); 1141 | 1142 | c1.set(o1.year, o2.month, o1.day); 1143 | 1144 | Calendar c2 = Calendar.getInstance(); 1145 | 1146 | c2.set(o2.year, o2.month, o2.day); 1147 | 1148 | return c1.compareTo(c2); 1149 | 1150 | } 1151 | 1152 | } 1153 | 1154 | 1155 | 1156 | private class LabelManager { 1157 | 1158 | private List list; 1159 | 1160 | 1161 | 1162 | public LabelManager() { 1163 | 1164 | list = new ArrayList(); 1165 | 1166 | } 1167 | 1168 | 1169 | 1170 | public List getLabels() { 1171 | 1172 | return list; 1173 | 1174 | } 1175 | 1176 | 1177 | 1178 | public void addLabel(MyLabel my) { 1179 | 1180 | list.add(my); 1181 | 1182 | } 1183 | 1184 | 1185 | 1186 | public void clear() { 1187 | 1188 | list.clear(); 1189 | 1190 | } 1191 | 1192 | 1193 | 1194 | @SuppressWarnings("unused") 1195 | 1196 | public void setSelect(MyLabel my, boolean b) { 1197 | 1198 | for (MyLabel m : list) { 1199 | 1200 | if (m.equals(my)) { 1201 | 1202 | m.setSelected(true, b); 1203 | 1204 | } else { 1205 | 1206 | m.setSelected(false, b); 1207 | 1208 | } 1209 | 1210 | } 1211 | 1212 | } 1213 | 1214 | 1215 | 1216 | public void setSelect(Point p, boolean b) { 1217 | 1218 | //如果是拖动,则要优化一下,以提高效率 1219 | 1220 | if (b) { 1221 | 1222 | //表示是否能返回,不用比较完所有的标签,能返回的标志就是把上一个标签和 1223 | 1224 | //将要显示的标签找到了就可以了 1225 | 1226 | boolean findPrevious = false, findNext = false; 1227 | 1228 | for (MyLabel m : list) { 1229 | 1230 | if (m.contains(p)) { 1231 | 1232 | findNext = true; 1233 | 1234 | if (m.getIsSelected()) { 1235 | 1236 | findPrevious = true; 1237 | 1238 | } else { 1239 | 1240 | m.setSelected(true, b); 1241 | 1242 | } 1243 | 1244 | } else if (m.getIsSelected()) { 1245 | 1246 | findPrevious = true; 1247 | 1248 | m.setSelected(false, b); 1249 | 1250 | } 1251 | 1252 | if (findPrevious && findNext) { 1253 | 1254 | return; 1255 | 1256 | } 1257 | 1258 | } 1259 | 1260 | } else { 1261 | 1262 | MyLabel temp = null; 1263 | 1264 | for (MyLabel m : list) { 1265 | 1266 | if (m.contains(p)) { 1267 | 1268 | temp = m; 1269 | 1270 | } else if (m.getIsSelected()) { 1271 | 1272 | m.setSelected(false, b); 1273 | 1274 | } 1275 | 1276 | } 1277 | 1278 | if (temp != null) { 1279 | 1280 | temp.setSelected(true, b); 1281 | 1282 | } 1283 | 1284 | } 1285 | 1286 | } 1287 | 1288 | 1289 | 1290 | } 1291 | 1292 | 1293 | 1294 | private class JP4 extends JPanel { 1295 | 1296 | private static final long serialVersionUID = -6391305687575714469L; 1297 | 1298 | 1299 | 1300 | public JP4() { 1301 | 1302 | super(new BorderLayout()); 1303 | 1304 | this.setPreferredSize(new Dimension(295, 20)); 1305 | 1306 | this.setBackground(new Color(160, 185, 215)); 1307 | 1308 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); 1309 | 1310 | final JLabel jl = new JLabel("今天: " + sdf.format(new Date())); 1311 | 1312 | jl.setToolTipText("点击选择今天日期"); 1313 | 1314 | this.add(jl, BorderLayout.CENTER); 1315 | 1316 | jl.addMouseListener(new MouseAdapter() { 1317 | 1318 | public void mouseEntered(MouseEvent me) { 1319 | 1320 | jl.setCursor(new Cursor(Cursor.HAND_CURSOR)); 1321 | 1322 | jl.setForeground(Color.RED); 1323 | 1324 | } 1325 | 1326 | 1327 | 1328 | public void mouseExited(MouseEvent me) { 1329 | 1330 | jl.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 1331 | 1332 | jl.setForeground(Color.BLACK); 1333 | 1334 | } 1335 | 1336 | 1337 | 1338 | public void mousePressed(MouseEvent me) { 1339 | 1340 | jl.setForeground(Color.WHITE); 1341 | 1342 | select.setTime(new Date()); 1343 | 1344 | refresh(); 1345 | 1346 | commit(); 1347 | 1348 | } 1349 | 1350 | 1351 | 1352 | public void mouseReleased(MouseEvent me) { 1353 | 1354 | jl.setForeground(Color.BLACK); 1355 | 1356 | } 1357 | 1358 | }); 1359 | 1360 | } 1361 | 1362 | 1363 | 1364 | private void updateDate() { 1365 | 1366 | 1367 | 1368 | } 1369 | 1370 | } 1371 | } -------------------------------------------------------------------------------- /weiboPicDownloader/src/main/java/weibo/FileUtils.java: -------------------------------------------------------------------------------- 1 | package weibo; 2 | 3 | import java.io.BufferedOutputStream; 4 | import java.io.File; 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.net.HttpURLConnection; 9 | import java.net.URL; 10 | 11 | import org.apache.commons.io.IOUtils; 12 | 13 | public class FileUtils { 14 | /** 15 | * 最大图片大小40M 16 | * */ 17 | private static final long MAX_DOWNLOAD_SIZE = 40L * 1024 * 1024; 18 | 19 | /** 20 | * UA 21 | * */ 22 | static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36"; 23 | 24 | public static void byte2File(byte[] buf, String path, String fileName) { 25 | BufferedOutputStream bos = null; 26 | FileOutputStream fos = null; 27 | File file = null; 28 | File pathF = new File(path); 29 | if (!pathF.exists()) { 30 | pathF.mkdirs(); 31 | } 32 | try { 33 | file = new File(pathF, fileName); 34 | fos = new FileOutputStream(file); 35 | bos = new BufferedOutputStream(fos); 36 | bos.write(buf); 37 | } catch (Exception e) { 38 | e.printStackTrace(); 39 | } finally { 40 | if (bos != null) { 41 | try { 42 | bos.close(); 43 | } catch (IOException e) { 44 | e.printStackTrace(); 45 | } 46 | } 47 | if (fos != null) { 48 | try { 49 | fos.close(); 50 | } catch (IOException e) { 51 | e.printStackTrace(); 52 | } 53 | } 54 | } 55 | } 56 | /** 57 | * 下载指定文件到内存 58 | * 59 | * @param webUrl 60 | * @return byte 61 | * 62 | * 63 | */ 64 | public static byte[] download(String webUrl, int timeOut) { 65 | HttpURLConnection connection = null; 66 | long start = System.currentTimeMillis(); 67 | try { 68 | URL url = new URL(webUrl); 69 | connection = (HttpURLConnection) url.openConnection(); 70 | connection.setConnectTimeout(timeOut); 71 | connection.setReadTimeout(timeOut); 72 | connection.setRequestProperty("User-Agent", USER_AGENT); 73 | int len = connection.getContentLength(); 74 | if (len >= MAX_DOWNLOAD_SIZE) { 75 | return null; 76 | } 77 | if (len == -1) { 78 | try (InputStream in = connection.getInputStream()) { 79 | return IOUtils.toByteArray(connection.getInputStream()); 80 | } 81 | } else { 82 | byte[] data = new byte[len]; 83 | byte[] buffer = new byte[4096 * 2]; 84 | int count = 0, sum = 0; 85 | try (InputStream in = connection.getInputStream()) { 86 | while ((count = in.read(buffer)) > 0) { 87 | long elapse = System.currentTimeMillis() - start; 88 | if (elapse >= timeOut) { 89 | data = null; 90 | break; 91 | } 92 | System.arraycopy(buffer, 0, data, sum, count); 93 | sum += count; 94 | } 95 | } 96 | return data; 97 | } 98 | } catch (Exception e) { 99 | return null; 100 | } finally { 101 | if (connection != null) { 102 | connection.disconnect(); 103 | } 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /weiboPicDownloader/src/main/java/weibo/ImageDownloadTask.java: -------------------------------------------------------------------------------- 1 | package weibo; 2 | 3 | import java.util.concurrent.CountDownLatch; 4 | 5 | public class ImageDownloadTask implements Runnable{ 6 | private CountDownLatch downLatch; 7 | private int imageIndex; 8 | private String imageUrl; 9 | 10 | public int getImageIndex() { 11 | return imageIndex; 12 | } 13 | public void setImageIndex(int imageIndex) { 14 | this.imageIndex = imageIndex; 15 | } 16 | public String getImageUrl() { 17 | return imageUrl; 18 | } 19 | public void setImageUrl(String imageUrl) { 20 | this.imageUrl = imageUrl; 21 | } 22 | 23 | public ImageDownloadTask(CountDownLatch downLatch, int imageIndex, String imageUrl) { 24 | super(); 25 | this.downLatch = downLatch; 26 | this.imageIndex = imageIndex; 27 | this.imageUrl = imageUrl; 28 | } 29 | 30 | @Override 31 | public void run() { 32 | try{ 33 | System.out.println("下载图片: " + ( imageIndex + 1)); 34 | byte[] imgBytes = FileUtils.download(imageUrl, 100_000); 35 | FileUtils.byte2File(imgBytes, WeiboDownloader.IMG_LOCATION, imageIndex+1+getSuffix(imageUrl)); 36 | }catch (Exception e) { 37 | }finally { 38 | downLatch.countDown(); 39 | } 40 | } 41 | private String getSuffix(String url){ 42 | if(!url.substring(url.lastIndexOf("/")).contains(".")){ 43 | return ".jpg"; 44 | } 45 | try{ 46 | return url.substring(url.lastIndexOf(".")); 47 | }catch(Exception e){ 48 | e.printStackTrace(); 49 | } 50 | return ".jpg"; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /weiboPicDownloader/src/main/java/weibo/MainGui.java: -------------------------------------------------------------------------------- 1 | package weibo; 2 | 3 | import javax.swing.*; 4 | import java.awt.*; 5 | import java.awt.event.ActionEvent; 6 | import java.awt.event.ActionListener; 7 | 8 | 9 | public class MainGui extends JFrame { 10 | private static final long serialVersionUID = -8161981948004677531L; 11 | int DEFAULT_WIDTH = 300; 12 | int DEFAULT_HEIGHT = 200; 13 | private JLabel label; 14 | private JComboBox faceCombo; 15 | private static TextField tf; 16 | private static JButton filePathButton; 17 | private static DateChooser startTimeChooser; 18 | private static DateChooser endTimeChooser; 19 | private static JLabel endShowDate; 20 | private static JLabel startShowDate; 21 | private static Button button; 22 | private static String type; 23 | private static String name; 24 | private static String startTime ; 25 | private static String endTime; 26 | private static String filePath; 27 | 28 | public MainGui() { 29 | this.setTitle("微博图片下载"); 30 | this.setSize(this.DEFAULT_WIDTH, this.DEFAULT_HEIGHT); 31 | this.setLayout(new GridLayout(6, 2,3,3)); 32 | // 第一行内容 33 | label = new JLabel("账号类型:"); 34 | label.setSize(200,10000); 35 | 36 | faceCombo = new JComboBox<>(); 37 | faceCombo.setEditable(false); 38 | faceCombo.setEnabled(true); 39 | // faceCombo.addItem("用户昵称"); 40 | // faceCombo.addItem("用户名"); 41 | faceCombo.addItem("用户ID"); 42 | this.add(label); 43 | this.add(faceCombo); 44 | label.setHorizontalAlignment(SwingConstants.RIGHT); 45 | 46 | // 第二行内容 47 | JLabel label2 = new JLabel("昵称"); 48 | label2.setHorizontalAlignment(SwingConstants.RIGHT); 49 | tf = new TextField(20); 50 | this.add(label2); 51 | this.add(tf); 52 | 53 | // 第三行内容 54 | JLabel label3 = new JLabel("开始时间"); 55 | label3.setHorizontalAlignment(SwingConstants.RIGHT); 56 | this.add(label3); 57 | 58 | startTimeChooser = DateChooser.getInstance("yyyy-MM-dd"); 59 | startShowDate = new JLabel("单击选择日期"); 60 | startTimeChooser.register(startShowDate); 61 | this.add(startShowDate); 62 | 63 | // 第四行内容 64 | JLabel label4 = new JLabel("结束时间"); 65 | label4.setHorizontalAlignment(SwingConstants.RIGHT); 66 | this.add(label4); 67 | 68 | endTimeChooser = DateChooser.getInstance("yyyy-MM-dd"); 69 | endShowDate = new JLabel("单击选择日期"); 70 | endTimeChooser.register(endShowDate); 71 | this.add(endShowDate); 72 | 73 | button = new Button("Start"); 74 | button.addActionListener(new ActionListener() { 75 | @Override 76 | public void actionPerformed(ActionEvent e) { 77 | type = (String)faceCombo.getSelectedItem(); 78 | name = tf.getText(); 79 | System.out.println(startShowDate.getText()); 80 | System.out.println(endShowDate.getText()); 81 | if (startShowDate.getText() != "单击选择日期") { 82 | startTime = startTimeChooser.getStrDate(); 83 | } 84 | if (endShowDate.getText() != "单击选择日期") { 85 | endTime = endTimeChooser.getStrDate(); 86 | } 87 | if ((startTime == null && endTime != null) || (startTime != null && endTime == null)) { 88 | JOptionPane.showMessageDialog(null, "输入完整的起止时间或不输入时间","错误", JOptionPane.ERROR_MESSAGE); 89 | return; 90 | } else { 91 | if (startTime != null && endTime != null) { 92 | WeiboUtils.needFilterDate = true; 93 | WeiboUtils.startTime = startTime; 94 | WeiboUtils.endTime = endTime; 95 | } 96 | } 97 | filePath = filePathButton.getText(); 98 | if (type == null || "".equals(type) || name == null || "".equals(name) 99 | || filePath == null || "".equals(filePath) || "选择".equals(filePath)) { 100 | JOptionPane.showMessageDialog(null, "请输入正确的名称,以及图片保存地址","错误", JOptionPane.ERROR_MESSAGE); 101 | return; 102 | } 103 | System.out.println("type is " + type); 104 | System.out.println("name is " + name); 105 | System.out.println("startTime is " + startTime); 106 | System.out.println("end is " + endTime); 107 | System.out.println("filePath is " + filePath); 108 | Thread th = new Thread(new Runnable() { 109 | @Override 110 | public void run() { 111 | try{ 112 | button.setEnabled(false); 113 | WeiboDownloader.downloadCli(type, name, filePath, startTime, endTime); 114 | } catch (Exception err) { 115 | button.setEnabled(true); 116 | System.out.println("出错了。 详细错误信息: "); 117 | err.printStackTrace(); 118 | } finally { 119 | button.setEnabled(true); 120 | WeiboUtils.needFilterDate = false; 121 | WeiboUtils.startTime = null; 122 | WeiboUtils.endTime = null; 123 | } 124 | } 125 | }); 126 | th.start(); 127 | } 128 | }); 129 | // 第五行内容 130 | JLabel label5 = new JLabel("文件保存地址"); 131 | label5.setHorizontalAlignment(SwingConstants.RIGHT); 132 | this.add(label5); 133 | filePathButton = new JButton("选择"); 134 | filePathButton.addActionListener(new ActionListener() { 135 | @Override 136 | public void actionPerformed(ActionEvent e) { 137 | JFileChooser jfc=new JFileChooser(); 138 | jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY ); 139 | jfc.showDialog(new JLabel(), "选择"); 140 | if (jfc.getSelectedFile() != null) { 141 | filePathButton.setText(jfc.getSelectedFile().getAbsolutePath()); 142 | } 143 | } 144 | }); 145 | this.add(filePathButton); 146 | this.add(button); 147 | 148 | } 149 | public static void main(String[] args){ 150 | MainGui mainGui = new MainGui(); 151 | mainGui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 152 | mainGui.setLocationRelativeTo(null); 153 | mainGui.setVisible(true); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /weiboPicDownloader/src/main/java/weibo/WeiboDownloader.java: -------------------------------------------------------------------------------- 1 | package weibo; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.concurrent.CountDownLatch; 9 | import java.util.concurrent.ExecutorService; 10 | import java.util.concurrent.Executors; 11 | 12 | import org.apache.http.ParseException; 13 | 14 | public class WeiboDownloader { 15 | public static final int TYPE_USER_ID = 1; 16 | public static final int TYPE_USER_NAME = 2; 17 | public static final int TYPE_USER_NICKNAME = 3; 18 | 19 | /** 20 | * UA 21 | * */ 22 | static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36"; 23 | 24 | /** 25 | * 路径 26 | * */ 27 | public static String IMG_LOCATION = "E:\\img\\"; 28 | 29 | public static void downloadCli(String selectType, String inputName, String filePath, String startTime, String endTime) throws ParseException, IOException, InterruptedException { 30 | IMG_LOCATION = filePath; 31 | Map map = new HashMap<>(); 32 | // 目前失效 先注释 33 | // map.put("用户昵称", TYPE_USER_NICKNAME); 34 | // map.put("用户名", TYPE_USER_NAME); 35 | map.put("用户ID", TYPE_USER_ID); 36 | int type = map.get(selectType); 37 | String containerId = ""; 38 | if(type == TYPE_USER_ID){ 39 | String uid = inputName; 40 | containerId = WeiboUtils.uidToContainerId(uid); 41 | }else if(type == TYPE_USER_NAME){ 42 | String name = inputName; 43 | containerId = WeiboUtils.usernameToContainerId(name); 44 | }else if(type == TYPE_USER_NICKNAME){ 45 | String nickname = inputName; 46 | containerId = WeiboUtils.nicknameToContainerId(nickname); 47 | } 48 | if (containerId == null) { 49 | System.out.println("未找到用户, 请检查账户名"); 50 | return; 51 | } 52 | List imgUrls; 53 | try { 54 | imgUrls = WeiboUtils.getAllImgURL(containerId); 55 | } catch (Exception e1) { 56 | e1.printStackTrace(); 57 | System.out.println("解析出现异常, 请稍候再试!"); 58 | return; 59 | } 60 | System.out.println("分析完毕"); 61 | System.out.println("图片数量: " + imgUrls.size()); 62 | 63 | if(!IMG_LOCATION.endsWith("/")&&!IMG_LOCATION.endsWith("\\")){ 64 | if(IMG_LOCATION.contains("/")) 65 | IMG_LOCATION = IMG_LOCATION + "/" + containerId.substring(6) + "/"; 66 | else 67 | IMG_LOCATION = IMG_LOCATION + "\\" + containerId.substring(6) + "\\"; 68 | } 69 | 70 | if(!new File(IMG_LOCATION).exists()){ 71 | try{ 72 | new File(IMG_LOCATION).mkdirs(); 73 | System.out.println("创建 " + IMG_LOCATION + "成功"); 74 | }catch (Exception e) { 75 | System.out.println("无法创建目录,请手动创建"); 76 | } 77 | } 78 | CountDownLatch downLatch = new CountDownLatch(imgUrls.size()); 79 | ExecutorService executor = Executors.newFixedThreadPool(4); 80 | for(int i=0;i getAllImgURL(String containerid) throws Exception { 89 | List urls = new ArrayList(); 90 | int i = 1; 91 | while (getImgURL(containerid, i, urls) > 0) { 92 | System.out.println("分析微博中: " + i); 93 | i++; 94 | // 防封,分析一次页面休息+1S 95 | Thread.sleep(1000); 96 | } 97 | return urls; 98 | } 99 | 100 | private static int getImgURL(String containerid, int page, List urls) throws ParseException, IOException { 101 | String url = "https://m.weibo.cn/api/container/getIndex?count=25&page=" + page + "&containerid=" + containerid; 102 | System.out.println(url); 103 | HttpClient httpClient = getHttpClient(); 104 | HttpGet get = new HttpGet(url); 105 | get.setHeader("User-Agent", USER_AGENT); 106 | HttpResponse response = httpClient.execute(get); 107 | String ret = EntityUtils.toString(response.getEntity(), "utf-8"); 108 | JsonObject root; 109 | try { 110 | // 防封 111 | root = new JsonParser().parse(ret).getAsJsonObject(); 112 | } catch (Exception e) { 113 | try { 114 | Thread.sleep(60000); 115 | } catch (Exception e1) { 116 | 117 | } 118 | return 1; 119 | } 120 | JsonObject asJsonObject = root.getAsJsonObject("data"); 121 | JsonArray array = asJsonObject.getAsJsonArray("cards"); 122 | for (int i = 0; i < array.size(); i++) { 123 | JsonObject mblog = array.get(i).getAsJsonObject().getAsJsonObject("mblog"); 124 | if (mblog != null) { 125 | if (WeiboUtils.needFilterDate) { 126 | String createAt = mblog.get("created_at").getAsString(); 127 | String date = WeiboUtils.getDate(createAt); 128 | if (date.compareTo(WeiboUtils.startTime) < 0 || date.compareTo(WeiboUtils.endTime) > 0){ 129 | continue; 130 | } 131 | } 132 | JsonArray pics = mblog.getAsJsonArray("pics"); 133 | if (pics != null) { 134 | for (int j = 0; j < pics.size(); j++) { 135 | JsonObject o = pics.get(j).getAsJsonObject(); 136 | JsonObject large = o.getAsJsonObject("large"); 137 | if (large != null) { 138 | urls.add(large.get("url").getAsString()); 139 | } 140 | } 141 | } 142 | } 143 | } 144 | return array.size(); 145 | } 146 | 147 | /** 148 | * 初始HttpClient 149 | * 150 | * @author yanximin 151 | */ 152 | public static HttpClient getHttpClient() { 153 | DefaultHttpClient httpClient = new DefaultHttpClient(); 154 | httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 30000); 155 | httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 30000); 156 | return httpClient; 157 | } 158 | 159 | public static long transWeiboDateStrToTimeStamp(String weiboDateStr) { 160 | if (weiboDateStr == null || "".equals(weiboDateStr)) { 161 | return 0; 162 | } 163 | if (weiboDateStr.contains("秒前")) { 164 | weiboDateStr = weiboDateStr.replace("秒前", ""); 165 | int second = Integer.valueOf(weiboDateStr); 166 | return System.currentTimeMillis() - second * 1000; 167 | } 168 | if (weiboDateStr.contains("分钟前")) { 169 | weiboDateStr = weiboDateStr.replace("分钟前", ""); 170 | int second = Integer.valueOf(weiboDateStr); 171 | return System.currentTimeMillis() - second * 1000 * 60; 172 | } 173 | if (weiboDateStr.contains("小时前")) { 174 | weiboDateStr = weiboDateStr.replace("小时前", ""); 175 | int second = Integer.valueOf(weiboDateStr); 176 | return System.currentTimeMillis() - second * 1000 * 3600; 177 | } 178 | if (weiboDateStr.contains("昨天")) { 179 | Date yesterdayTimestamp = new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24); 180 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd"); 181 | String yesterday = simpleDateFormat.format(yesterdayTimestamp); 182 | weiboDateStr = weiboDateStr.replace("昨天", yesterday); 183 | SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyyMMdd HH:mm"); 184 | try { 185 | Date date = sDateFormat.parse(weiboDateStr); 186 | return date.getTime(); 187 | } catch (Exception e) { 188 | return 0; 189 | } 190 | } 191 | if (weiboDateStr.contains("-")) { 192 | if (!weiboDateStr.startsWith("20")) { 193 | int year = new Date().getYear() + 1900; 194 | weiboDateStr = year + "-" + weiboDateStr; 195 | } 196 | SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd"); 197 | try { 198 | Date date = sDateFormat.parse(weiboDateStr); 199 | return date.getTime(); 200 | } catch (Exception e) { 201 | return 0; 202 | } 203 | } 204 | return 0; 205 | } 206 | public static String getDate(String weiboDateStr) { 207 | long time; 208 | try { 209 | time = WeiboUtils.transWeiboDateStrToTimeStamp(weiboDateStr); 210 | } catch (Exception e) { 211 | time = 0; 212 | } 213 | 214 | SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd"); 215 | return sDateFormat.format(new Date(time)); 216 | } 217 | } 218 | --------------------------------------------------------------------------------