关闭HtmlUnit日志信息 屏蔽报错信息

对于htmlunit控制台报错信息不能关闭的情况,将下列代码加入报错代码前即可,例如可加在代码最前面LogManager.getLogManager().reset();其它方法可参考:https://blog.csdn.net/gyxscnbs/article/details/51357407对于纯java项目(未引入其它日志系统)的警告信息,可在classpath中加入logging.properties文件解决,文件内容:java.util.logging.ConsoleHandler.level = FINEjava.util.logging.ConsoleHandler.encoding = UTF-8

Maven固定jdk版本 将依赖包都打进jar包教程

很简单,pom中加入这两个插件即可,第一个插件指定要编译的jdk版本、编码等信息,第二个插件mainClass中填入jar启动类的全限定类名。 <build> <plugins> <!--强制maven以jdk8编译--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <!--打包时包将所有依赖打进去--> <plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <archive> <manifest> <mainClass>Main</mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> </plugin> </plugins> </build>对于第一个插件,其它设置有<plugin> <!-- 指定maven编译的jdk版本,如果不指定,maven3默认用jdk 1.5 maven2默认用jdk1.3 --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <!-- 一般而言,target与source是保持一致的,但是,有时候为了让程序能在其他版本的jdk中运行(对于低版本目标jdk,源代码中不能使用低版本jdk中不支持的语法),会存在target不同于source的情况 --> <source>1.8</source> <!-- 源代码使用的JDK版本 --> <target>1.8</target> <!-- 需要生成的目标class文件的编译版本 --> <encoding>UTF-8</encoding><!-- 字符集编码 --> <skipTests>true</skipTests><!-- 跳过测试 --> <verbose>true</verbose> <showWarnings>true</showWarnings> <fork>true</fork><!-- 要使compilerVersion标签生效,还需要将fork设为true,用于明确表示编译版本配置的可用 --> <executable><!-- path-to-javac --></executable><!-- 使用指定的javac命令,例如:<executable>${JAVA_1_4_HOME}/bin/javac</executable> --> <compilerVersion>1.3</compilerVersion><!-- 指定插件将使用的编译器的版本 --> <meminitial>128m</meminitial><!-- 编译器使用的初始内存 --> <maxmem>512m</maxmem><!-- 编译器使用的最大内存 --> <compilerArgument>-verbose -bootclasspath ${java.home}\lib\rt.jar </compilerArgument><!-- 这个选项用来传递编译器自身不包含但是却支持的参数选项 --> </configuration></plugin>第二个插件执行打包,点击idea右侧 Maven -> 项目名 -> Plugins-> assembly -> assembly:assembly 执行即可,如图:

Maven固定jdk版本 将依赖包都打进jar包教程

Java获取js渲染后的html页面源码实战(获取金价)

以下代码获取京东积存金实时价格,并高于预期卖出价或低于预期买入价时弹窗或微信提醒。依赖依赖htmlunit、jsoup两个包,htmlunit用于获取页面,jsoup用于解析html获取指定值。<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>goldNotice</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <properties> <maven.compiler.resource>1.8</maven.compiler.resource> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>net.sourceforge.htmlunit</groupId> <artifactId>htmlunit</artifactId> <version>2.45.0</version> </dependency> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.12.1</version> </dependency> </dependencies> <build> <plugins> <!--强制maven以jdk8编译--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <!--打包时包将所有依赖打进去--> <plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <archive> <manifest> <mainClass>Main</mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> </plugin> </plugins> </build></project>代码import com.gargoylesoftware.htmlunit.BrowserVersion;import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;import com.gargoylesoftware.htmlunit.WebClient;import com.gargoylesoftware.htmlunit.html.HtmlPage;import org.jsoup.Jsoup;import org.jsoup.nodes.Document;import org.jsoup.select.Elements;import javax.swing.*;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.net.URLConnection;import java.util.Date;import java.util.logging.LogManager;public class Main { public static void main(String[] args) { LogManager.getLogManager().reset();// 预期卖出价 float expectPrice = 399;// 预期买入价 float lowPrice = 390;// 间隔时间 默认2s long sec = 2000;// 请求等待时间 long reqSec = 5000; for (int i = 0; i <= 3; i++) { if (args.length > 0 && i == 0) expectPrice = Float.parseFloat(args[0]); if (args.length > 1 && i == 1) lowPrice = Float.parseFloat(args[1]); if (args.length > 2 && i == 2) sec = Long.parseLong(args[2]); if (args.length > 3 && i == 3) reqSec = Long.parseLong(args[3]); } System.out.println("数据加载中请稍候……"); WebClient webClient = new WebClient(BrowserVersion.CHROME);//模拟CHROME浏览器 try { webClient.setJavaScriptTimeout(5000); webClient.getOptions().setUseInsecureSSL(true);//接受任何主机连接 无论是否有有效证书 webClient.getOptions().setJavaScriptEnabled(true);//设置支持javascript脚本 webClient.getOptions().setCssEnabled(false);//禁用css支持 webClient.getOptions().setThrowExceptionOnScriptError(false);//js运行错误时不抛出异常 webClient.getOptions().setTimeout(100000);//设置连接超时时间 webClient.getOptions().setDoNotTrackEnabled(false); HtmlPage page = webClient.getPage("https://m.jdjygold.com/finance-gold/newgold/index/?ordersource=2&jrcontainer=h5&jrlogin=true&utm_source=Android_url_1609033920704&utm_medium=jrappshare&utm_term=wxfriends");// 加载js需要时间故延迟默认5s Thread.sleep(reqSec); while (true) {// 使用Jsoup解析html Document document = Jsoup.parse(page.asXml()); Elements span01 = document.getElementsByClass("price_span01"); String price = span01.text(); String localeString = new Date().toLocaleString(); System.out.println(localeString + " " + price); String msg = localeString + "价格已达到预定值:" + price; String lowMsg = localeString + "价格已低于预定值:" + price; float goldPrice = Float.parseFloat(price); if (msg != null && goldPrice >= expectPrice) { JOptionPane.showConfirmDialog(null, msg, "达到预期卖出价提示", JOptionPane.CLOSED_OPTION);// 若部署在服务器上则使用Server酱提醒// getUrl("https://sc.ftqq.com/xxxxxxxxxxxxxx.send?text="+msg); return; } if (msg != null && goldPrice <= lowPrice) { JOptionPane.showConfirmDialog(null, lowMsg, "低于预期买入价提示", JOptionPane.CLOSED_OPTION);// getUrl("https://sc.ftqq.com/xxxxxxxxxxxxxx.send?text="+lowMsg); return; } Thread.sleep(sec); } } catch (FailingHttpStatusCodeException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } catch (MalformedURLException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } catch (IOException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } finally { webClient.close(); } } public static void getUrl(String toUrl) throws IOException { URL url = new URL(toUrl); //建立连接 URLConnection urlConnection = url.openConnection(); //连接对象类型转换 HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection; //设定请求方法 httpURLConnection.setRequestMethod("GET"); //获取字节输入流信息 InputStream inputStream = httpURLConnection.getInputStream(); //字节流转换成字符流 InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); //把字符流写入到字符流缓存中 BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String line = null; //读取缓存中的数据 while ((line = bufferedReader.readLine()) != null) { System.out.println(line); } //关闭流 inputStream.close(); }}使用方法打包后直接执行命令java -jar xxx.jar 390 360第一个数字为预期卖出价;第二个为预期买入价,即当价格高于390或低于360提醒并关闭程序。第三个参数设置间隔时间,单位毫秒;第四个参数设置请求等待时间,即启动时加载数据的等待时间,有时候网络不好时间短可能加载不出来,代码不填时默认5s,一般足矣无需带第四个参数。例如:java -jar goldNotice-1.0-SNAPSHOT-jar-with-dependencies.jar 400 391.6 2500 3000在服务器上部署请配置Server酱key并将弹窗代码注释。更多拓展可自行修改代码。

Firefox火狐手机版安装插件及PC端书签整理插件

Firefox火狐国际版(安卓)安装插件Firefox Nightly(ARM64版) https://firefox-ci-tc.services.mozilla.com/api/index/v1/task/mobile.v2.fenix.nightly.latest.arm64-v8a/artifacts/public/build/arm64-v8a/target.apk其它版本见官方库:https://firefox-ci-tc.services.mozilla.com/tasks/index/mobile.v2.fenix下载Nightly版,设置里找到关于,多次点击Nightly图标,回到设置界面,然后点击「自定义附加组件收藏集」,输入收藏集所有者:15434003,收藏集名称:1(值任意,中文可能会添加失败),重启浏览器即可。你也可以添加自己的应用集然后使用自己的应用集ID。参考酷安@hana_shirosakiFirefox书签整理插件(适合PC端)Bookmark Dupes:检测重复书签、空文件夹并删除Bookmarks clean up:检测重复书签、空文件夹并删除、合并同名文件夹,并且提供检测失效链接,功能与上一个插件互补Bookmarks Organizer:检测404、403等无效链接,一键删除或手动处理,也能检测重复链接、无标题链接Auto-Sort Bookmarks:让书签根据标题字母、URL、创建时间、访问次数等条件排序,让书签更加井井有条floccus:书签同步工具,支持webdav

IntelliJ IDEA常用统一设置(Linux/Mac/Windows)

说明:除了以下说明的配置地方外,其它尽量保持默认,这样有利于团队代码风格的统一。运行VM配置:推荐高内存机器配置,8G内存保持默认即可。参考:https://github.com/judasn/IntelliJ-IDEA-Tutorial/blob/master/installation-directory-introduce.md一、文件编码IDE的编码默认修改为UTF-8,Project Encoding修改为UTF-8;注意:Linux默认编码为UTF-8,而Windows默认是GBK,所以从Windows新建的文件转到Linux会变成乱码,而通过这样的修改之后,就能保持多平台统一的编码,Mac下默认也是UTF-8。二、换行符换行符统一修改为Linux和Mac下用的\n三、Tab键使用4个空格缩进注意:是不选择!四、代码提示不区分大小写五、设置自动import包(可选,对于不能import *的要求的,建议不要用这个)如果非要用这个自动导入却不想导入*的,可以通过配置这个来解决调整import包导入的顺序,保持和Eclipse一致:空行import java.*空行import javax.*空行import com.*空行import all other imports空行import static all other imports六、右下角显示内存点击右下角可以回收内存。七、显示行数和方法线八、新建类时加入标准的Javadoc注释(即:@author、@date) 说明:@date可能不是标准的Javadoc,但是在业界标准来说,这个已经成为Javadoc必备的注释,因为大多数人都用这个来标注日期。建议:注释不要太个性,比如自定义类说明,日期时间字段等等;尽量保持统一的代码风格,建议参考阿里巴巴Java开发手册。四个文件都加上这个说明:/** * This is Description * * @author ${USER} * @date ${YEAR}/${MONTH}/${DAY} */注意:Javadoc的关键字与说明要隔开一行。日期格式:年/月/日(参考阿里巴巴Java开发手册),作者可以用系统默认也可以写死。九、Google代码风格(可选)注意:Google代码风格为2个空格缩进,根据需要修改为4个空格缩进。官网:https://github.com/google/styleguide下载:修改为4个空格:上面只是针对Java文件的设置,比如CSS这些都是需要手动修改的。参考:https://github.com/judasn/IntelliJ-IDEA-Tutorial/blob/master/theme-settings.mdhttps://www.cnblogs.com/wangmingshun/p/6427088.html

IntelliJ IDEA常用统一设置(Linux/Mac/Windows)

谷歌Chrome浏览器小恐龙游戏刷分

当电脑断网用谷歌浏览器浏览网页时会出现一只萌萌哒小恐龙,按空格键即可开始游戏,是继蜘蛛纸牌之后又一上班划水神奇,但是看似简单的游戏跑高分倒是有点困难,下面分享下可以跑高分的方法(或称为作弊码也行)以下需在F12->console中输入:满分Runner.instance_.setSpeed(99999);无敌Runner.instance_.gameOver = function(){}

基于 SpringBoot+VUE 的开源 blog (helloblog)

基于 SpringBoot 实现零配置让系统的配置更简单,使用了 Mybatis-Plus 快速开发框架,在不是复杂的查询操作下,无需写 sql 就可以快速完成接口编写。 后台管理系统使用了 vue 中流行的 ant,另外前后交互使用了 JWT 作为令牌,进行权限、登录校验。项目下载地址后端 API https://github.com/byteblogs168/hello-blog后端管理系统 https://github.com/byteblogs168/hello-blog-admin前端主题地址: https://github.com/byteblogs168/theme-default3/helloblog 博客功能1、接入 GitHub 登录,游客可使用 GitHub 登录后进行评论等2、文章管理:新增、编辑、删除,支持 MD 语法3、文章可设置是否允许评论、设置标签、分类、支持博客搬家、自定义排序4、仪表盘:服务器状态、博客浏览量、最热文章一览无余5、分类管理:分类列表、分类增删查改6、标签管理:标签列表、标签增删查改7、友链管理:友链排序、友链简介8、用户管理:锁定用户、删除用户9、日志管理:对指定的接口进行监控10、菜单管理:自定义首页菜单项11、社交管理:自定义个人社交项12、系统配置-站点信息:自定义网站信息、版权信息、关键词等13、系统配置-歌单配置:配置网易云歌单信息(站点播放器)14、系统配置-存储配置:接入阿里云 OSS、七牛云、腾讯云 COS、服务器 OSS15、个人设置-定义个人信息、个性签名等信息16、文章归档:按照月份查询博客文章并进行分类

常用工具集合 basic-tool

常用工具集合 basic-tool网上看到的,觉得还不错的工具包,可以来学习学习,以下是作者的文档项目地址:https://github.com/AAA-AA/basic-tools文档地址见:https://aaa-aa.github.io/basic-tools/超大文本极速读取工具类使用说明public static void main(String[] args) { AtomicLong counter = new AtomicLong(0); String bigFilePath = "/Users/renhongqiang/Downloads/work-doc/2000W/test.csv"; BigFileReader.Builder builder = new BigFileReader.Builder(bigFilePath, line -> System.out.println(String.format("total record: %s,line is: %s", counter.incrementAndGet(), line))); BigFileReader bigFileReader = builder .threadPoolSize(100) .charset(StandardCharsets.UTF_8) .bufferSize(1024 * 1024).build(); bigFileReader.start();}实际效果见博客多线程极速读取超大文件校验工具类使用说明支持集合、字符串、对象判空,注解类判定,以及各类综合操作日期工具类使用说明获取当天零点Date today = Dates.today();将日期类型格式化为字符串Date date = Dates.addDays(custDate, 32);String format = Dates.format(date);将字符串类型parse为日期类型Date custDate = Dates.parse("2020-04-23 25", Dates.DATE_FORMAT);对日期时间的各类操作Date date = Dates.addDays(custDate, 32);Date addM = Dates.addMinutes(date,5);拓展集合使用说明list转mapOrder order = new Order("Carli","12112");Order order2 = new Order("Michale","11223");Order order3 = new Order("Marry","642321");List<Order> list = new ArrayList<>();list.add(order);list.add(order2);list.add(order3);Map<String, Order> kvFieldBean = ExtCollections.kvFieldBean(Order::getOwner, list);list中key相同合并操作Order order = new Order("Carli","12112");Order order2 = new Order("Carli","11223");Order order3 = new Order("Marry","642321");List<Order> list = new ArrayList<>();list.add(order);list.add(order2);list.add(order3);Map<String, List<Order>> kvFieldBeans = ExtCollections.kvFieldBeans(Order::getOwner, list);System.out.println(kvFieldBeans);list中任选k,v字段,重组为mapOrder order = new Order("Carli","12112");Order order2 = new Order("Carli","11223");Order order3 = new Order("Marry","642321");List<Order> list = new ArrayList<>();list.add(order);list.add(order2);list.add(order3);Map<String, String> map = ExtCollections.kv(Order::getId, Order::getOwner, list);身份证工具类说明有效身份证号自动生成@Testpublic void testGenerate() { System.out.println(IdCards.generate()); System.out.println(IdCards.generateByAreaName("东城区"));}年龄提取IdCards.parseAge("420102199401015244")出生年月提取IdCards.parseBirthday("420102199401015244")身份证合法性校验boolean checkCardId = IdCards.checkCardId("420102199401015244");15到18位身份证转换String idCard = IdCards.trans15To18("420102199401015")日志格式化工具说明敏感或超长字符串截断在需要的字段上加 @HideImg@Test public void testHide() { Person person = new Person(); System.out.println(LogFormats.formatLog(person)); } @Data public static class Person { @HideImg private String img = "/9jhfsdhajfksjdfhuhiuwbjbdfoasuhrttttttthhhhhhhhhhhhhhhhhhdfuf"; @HideAnn private String password = "128397287827802hhfashfkjhasfh"; @HideCollection private List<String> cellphones = new ArrayList<>(); }˂a name=敏感信息直接置为** href="#"˃敏感信息直接置为**直接在字段上加@HideAnn注解敏感字段集合直接过滤直接在集合字段上加@HideCollection注解随机工具类说明指定概率命中@Testpublic void testHit() { int count = 1; for (int i = 0; i < 1000000; i++) { boolean hit = Randoms.isScoreAHit(1, 1000); if (hit) { System.out.println(count++); } }}随机生成指定长度数字、字符串或数字字符串混合@Testpublic void testRandomNumOrA() { for (int i = 0; i < 10; i++) { //指定5-8位长度字符串 System.out.println(Randoms.randomOfA(5, 8)); //指定4-7位长度数字 System.out.println(Randoms.randomOfD(4,7)); //指定4个长度的数字和字母混合字符串 System.out.println(Randoms.randomOfDA(4)); }}生成8-16位含数字、小写和大写字母的随机密码,有校验@Testpublic void testRandomRegStr() { System.out.println(Randoms.checkAndGetResultString());}字符串工具类说明下划线变驼峰(LineToHump)@Testpublic void testLineToHump() { String authUser = "auth_user"; System.out.println(Strings.lineToHump(authUser));}驼峰变下划线(HumpToLine)@Testpublic void testHumpToLine() { String authUser = "authUser"; System.out.println(Strings.humpToLine(authUser));}截取字符串(Cut string)@Testpublic void testSubString() { String demoString = "demo_string_123"; System.out.println(Strings.substring(demoString,1,3));}

常用工具集合 basic-tool

Katalon Recorder浏览器插件

适合火狐与谷歌浏览器,可在各自的浏览器应用商店下载。这是一款可以录制浏览器操作的工具,并且可以用Export导出成webDriver的各种语言的代码,例如以下是录制在百度搜索java关键词动作生成的脚本package com.example.tests;import java.util.regex.Pattern;import java.util.concurrent.TimeUnit;import org.junit.*;import static org.junit.Assert.*;import static org.hamcrest.CoreMatchers.*;import org.openqa.selenium.*;import org.openqa.selenium.firefox.FirefoxDriver;import org.openqa.selenium.support.ui.Select;public class UntitledTestCase { private WebDriver driver; private String baseUrl; private boolean acceptNextAlert = true; private StringBuffer verificationErrors = new StringBuffer(); @Before public void setUp() throws Exception { driver = new FirefoxDriver(); baseUrl = "https://www.google.com/"; driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); } @Test public void testUntitledTestCase() throws Exception { driver.get("https://www.baidu.com/"); driver.findElement(By.id("kw")).click(); driver.findElement(By.id("kw")).clear(); driver.findElement(By.id("kw")).sendKeys("java"); driver.findElement(By.id("form")).submit(); } @After public void tearDown() throws Exception { driver.quit(); String verificationErrorString = verificationErrors.toString(); if (!"".equals(verificationErrorString)) { fail(verificationErrorString); } } private boolean isElementPresent(By by) { try { driver.findElement(by); return true; } catch (NoSuchElementException e) { return false; } } private boolean isAlertPresent() { try { driver.switchTo().alert(); return true; } catch (NoAlertPresentException e) { return false; } } private String closeAlertAndGetItsText() { try { Alert alert = driver.switchTo().alert(); String alertText = alert.getText(); if (acceptNextAlert) { alert.accept(); } else { alert.dismiss(); } return alertText; } finally { acceptNextAlert = true; } }}

Playwright实现多端发帖

Playwright实现多端发帖一直想做,但是抓包太麻烦了,刚好接触到这个工具,一想其实用途还挺多,可以自己录个多平台发文脚本。例如写篇文章,想同步在简书、zblog、hu60、v2ex等平台发布,这几个平台刚好都支持markdown。那么我先根据路径读取md文件,以文件名为标题,文本为内容再执行各个发布方法,但在此之前,我们先获取登陆后的浏览器信息并保存吧from playwright import sync_playwrightdef hu60(playwright, name, pwd): browser = playwright.chromium.launch(headless=False) context = browser.newContext() page = context.newPage() page.goto("https://hu60.cn/q.php/user.login.html?u=index.index.html") page.fill("input[name=\"name\"]", name) page.fill("input[name=\"pass\"]", pwd) page.click("input[name=\"go\"]") page.close() # 保存浏览器数据至hu60文件 方便发布脚本读取 context.storageState(path="hu60") context.close() browser.close()def zblog(playwright, name, pwd): browser = playwright.chromium.launch(headless=False) context = browser.newContext() page = context.newPage() page.goto("https://cway.top/zb_system/login.php") page.fill("input[name=\"edtUserName\"]", name) page.fill("input[name=\"edtPassWord\"]", pwd) page.close() context.storageState(path="cway") context.close() browser.close()with sync_playwright() as playwright: hu60(playwright, '帐号', '密码') zblog(playwright, '帐号', '密码')接着我们可以直接执行发布脚本了,键入文本路径即可from playwright import sync_playwrightdef zblog(playwright, title, content, id): import time browser = playwright.chromium.launch(headless=False) context = browser.newContext(storageState="cway") page = context.newPage() page.goto("https://cway.top/") page.click("text=\"新建文章\"") page.click("input[name=\"Title\"]") page.fill("input[name=\"Title\"]", title) page.fill("//div[normalize-space(.)='Enjoy Markdown! coding now...​x 1​']/div[1]/textarea", content) time.sleep(1) page.selectOption("select[id=\"cmbCateID\"]", id) page.click("input[type=\"submit\"]") page.goto("https://cway.top/") text = page.innerText("body") assert title in text page.close() context.close() browser.close()def hu60(playwright, title, content, id): browser = playwright.chromium.launch(headless=False) context = browser.newContext(storageState="hu60") page = context.newPage() page.goto("https://hu60.cn/q.php/index.index.html") page.click("text=\"发帖\"") page.click("text=/.*" + id + ".*/") page.click("input[name=\"title\"]") page.fill("input[name=\"title\"]", title) page.fill("textarea[name=\"content\"]", content) page.click("input[name=\"go\"]") context.close() browser.close()def jianshu(playwright, title, content, id): import time browser = playwright.chromium.launch(headless=False) context = browser.newContext(storageState="jianshu") page = context.newPage() page.goto("https://www.jianshu.com/writer#/") page.click("text=\"" + id + "\"") with page.expect_navigation(): page.click("text=\"" + id + "\"") page.click("//span[normalize-space(.)='新建文章']") page.click("//div[normalize-space(.)='发布文章']/input[normalize-space(@type)='text']") page.fill("//div[normalize-space(.)='发布文章']/input[normalize-space(@type)='text']", title) page.click("textarea[id=\"arthur-editor\"]") page.fill("textarea[id=\"arthur-editor\"]", content) time.sleep(2) page.click("//a[normalize-space(.)='发布文章']") page.close() context.close() browser.close()with sync_playwright() as playwright: path = input('请输入md或txt文件路径或在控制台拖入文件:') file = open(path, 'r') fn = file.name.split('/') # 获取标题 title = fn[len(fn) - 1].split('.')[0] # 获取内容 content = file.read() # 分类处理 由于每个平台文章分类不一样 酌情修改 # 指定分类 cata = 'py' zbcata, hu60cata, jscata = '7', 'Java', 'Java' if cata == 'java': zbcata, hu60cata, jscata = '7', 'Java', 'Java' if cata == 'py': zbcata, hu60cata, jscata = '18', 'Python', 'Python' zblog(playwright, title, content, zbcata) hu60(playwright, title, content, hu60cata) # jianshu(playwright, title, content, jscate)