乱码三千 – 分享实用IT技术

乱码三千 – 码出一个新世界


  • 首页

  • 归档

  • 搜索

如何将python采集到的文章保存到wordpress

发表于 2020-09-11

前言

wordpress算是比较流行的博客网站框架, 我本人也一直在使用, 关于python采集文章的上传, 有以下几种方法:

  1. 直接操作数据库
  2. 使用wordpress的rest api
  3. 使用wordpress_xmlrpc第三方模块

其中第三种的体验最为舒适, 对新手友好, 推荐使用

好了 接下来挨个介绍一下这几种方法的使用

直接操作数据库

我们可以使用python的pymysql库进行mysql数据库的直连操作, 具体不过多介绍, 直接上示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import pymysql.cursors

# 连接数据库
connect = pymysql.Connect(
host='数据库IP',
port=3306,
user='root',
passwd='xxxx',
db='数据库名称',
charset='utf8mb4'
)

# 获取游标
cursor = connect.cursor()

# 插入数据
def insert(post_author, post_date, post_date_gmt,post_content,post_title,post_status,comment_status,ping_status,post_type,menu_order,post_excerpt,to_ping):
cursor.execute('INSERT INTO wp_posts (post_author, post_date, post_date_gmt,post_content,post_title,post_status,comment_status,ping_status,post_type,menu_order,post_excerpt)VALUES ( %d, %s,%s, %s,%s, %s,%s, %s,%s,%s, %s, %s)', (1, post_date, post_date_gmt,post_content,post_title,post_status,comment_status,ping_status,post_type,menu_order,post_excerpt,to_ping))

connect.commit()
print('成功插入', cursor.rowcount, '条数据')

使用wordpress的rest api

关于rest api官方文档如下:

https://developer.wordpress.org/rest-api/

我们先试一下api的威力 格式为:

1
http://{域名}/index.php/wp-json/wp/v2/posts

比如:

1
http://www.jhcms.net/index.php/wp-json/wp/v2/posts

我们能看到几乎大部分文章的信息

那么如何创建一个新文章

我们参考官方文档 https://developer.wordpress.org/rest-api/reference/posts/#create-a-post

得到重要信息如下:

参数

date The date the object was published, in the site’s timezone.
date_gmt The date the object was published, as GMT.
slug An alphanumeric identifier for the object unique to its type.
status A named status for the object. One of: publish, future, draft, pending, private
password A password to protect access to the content and excerpt.
title The title for the object.
content The content for the object.
author The ID for the author of the object.
excerpt The excerpt for the object.
featured_media The ID of the featured media for the object.
comment_status Whether or not comments are open on the object. One of: open, closed
ping_status Whether or not the object can be pinged. One of: open, closed
format The format for the object. One of: standard, aside, chat, gallery, link, image, quote, status, video, audio
meta Meta fields.
sticky Whether or not the object should be treated as sticky.
template The theme file to use to display the object. One of:``
categories The terms assigned to the object in the category taxonomy.
tags The terms assigned to the object in the post_tag taxonomy.

POST /wp/v2/posts 意为要用post方法提交到/wp/v2/posts这个地址

默认是只读api, 要实现提交数据需要安装插件jwt,安装了jwt后可以请求到token了,然后在rest api中传入token信息,系统就不会拒绝你的发布文章的操作了

操作步骤

  1. 第一步 在wordpress管理后台安装 JWT Auth 插件

  2. 第二部 在网站根目录 .htaccess 文件中添加如下内容

    1
    2
    3
    4
    5
    RewriteEngine on
    RewriteCond %{HTTP:Authorization} ^(.*)
    RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]

    SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
  3. 在 wp-config.php 文件中添加如下内容:

    1
    2
    define('JWT_AUTH_SECRET_KEY', 'your-top-secret-key');//随便填写一个密码
    define('JWT_AUTH_CORS_ENABLE', true);
  4. Post请求调用http://{你的域名}/wp-json/jwt-auth/v1/token接口获取token

  5. 根据token进行文章的发布

核心代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# -*- coding:utf-8 -*-

import re
import requests
import json
import time
from numpy import *




def get_token():
session = requests.Session()
url = 'http://sex.newban.cn/wp-json/jwt-auth/v1/token'
data = {
'username':"son3g",
'password':"123456"
}
headers = {'user-agent': 'Mozolla/5.0',
}
resp = session.post(url, data=data, headers=headers, timeout=3335) # 请求
r = json.loads(resp.content)
return r




def _do_post( token =''):
session = requests.Session()
url = 'http://sex.newban.cn/wp-json/wp/v2/posts'
data = {
'date': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()),
'date_gmt': time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime()),
'slug': 'xx',
'status': 'publish',
'password': '',
'title': 'rest api发布post测试',
'content': '系统测试我想我是海冬天的大海',
'author ': '121852835@qq.com',
'excerpt': '',
'featured_media': '0',
'comment_status': 'open',
'ping_status': 'closed',
'format': 'standard',
'meta': [],
'sticky': False, # 置顶
'template': '',
'categories': '1', # 1 未分类
'tags': ''
}
headers = {'user-agent': 'Mozolla/5.0',
'Authorization': 'Bearer ' + token
}
resp = session.post(url, data=data, headers=headers, timeout=3335) # 请求
print (resp.text)
# r = json.loads(resp.content, 'utf-8')

# if r["code"] == 400:
# print r["code"]
# print r["message"]
# print r["data"]
# print r["data"]["status"]
#
#
# # print r["data"]["params"]
# for key in r["data"]["params"]:
# print ("%s=> %s" % (key, r["data"]["params"][key]))
# # print 'resp.text=>' + resp.text
#
# # print time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
# # print time.strftime('%a, %d %b %Y %H:%M:%S GMT+0800 (CST)',time.localtime(time.time())),
# dt = formatdate(None, usegmt=True)
# dt1 = formatdate(None, usegmt=False)
# dt3 = formatdate()
# print(dt)
# print(dt1)
# else:
# print r["code"]
# print r["message"]
# print resp.status_code


if __name__=='__main__':
r = get_token()
print (r)
_do_post(r["data"]['token'])

使用wordpress_xmlrpc第三方模块

操作步骤如下:

  1. 安装wordpress_xmlrpc

    1
    pip install python-wordpress-xmlrpc
  2. 模块引入

    1
    2
    from wordpress_xmlrpc import Client, WordPressPost
    from wordpress_xmlrpc.methods.posts import GetPosts,NewPost
  3. 发布新文章

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    def push_article(post_title,post_content_html):
    post = WordPressPost()
    post.title = post_title
    post.slug = post_title
    post.content = post_content_html
    post.terms_names = {
    'post_tag': post_title.split(" "),
    'category': ["itarticle"]
    }
    post.post_status = 'publish'
    wp.call(NewPost(post))

    if __name__ == '__main__':
    push_article("文章标题","文章内容")

    属性介绍:

    • title: 文章标题
    • content: 文章正文
    • post_status: 文章状态,不写默认是草稿,private表示私密的,draft表示草稿,publish表示发布
    • terms_names: 设置文章的标签 tag等
    • slug: 文章别名

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# -*- coding:utf-8 -*-
from wordpress_xmlrpc import Client, WordPressPost
from wordpress_xmlrpc.methods.posts import GetPosts,NewPost

def push_article(post_title,post_content_html):
post = WordPressPost()
post.title = post_title
post.slug = post_title
post.content = post_content_html
post.terms_names = {
'post_tag': post_title.split(" "),
'category': ["itarticle"]
}
post.post_status = 'publish'
wp.call(NewPost(post))

if __name__ == '__main__':
push_article("文章标题","文章内容")

是不是很简单呢, 如果是批量上传的话, 直接一个循环调用即可

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Django创建数据库常用字段及参数

发表于 2020-09-10

常用字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
1、models.AutoField  自增列= int(11)
  如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
  
  
2、models.CharField  字符串字段
  必须 max_length 参数
  
3、models.BooleanField  布尔类型=tinyint(1)
  不能为空,Blank=True
  
4、models.ComaSeparatedIntegerField  用逗号分割的数字=varchar
  继承CharField,所以必须 max_lenght 参数
  
5、models.DateField  日期类型 date
  对于参数,auto_now =True则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。
  
6、models.DateTimeField  日期类型 datetime
  同DateField的参数
  
7、models.Decimal  十进制小数类型= decimal
  必须指定整数位max_digits和小数位decimal_places
  
8、models.EmailField  字符串类型(正则表达式邮箱)=varchar
  对字符串进行正则表达式
  
9、models.FloatField  浮点类型= double

10、models.IntegerField  整形

11、models.BigIntegerField  长整形
  integer_field_ranges ={
    'SmallIntegerField':(-32768,32767),
    'IntegerField':(-2147483648,2147483647),
    'BigIntegerField':(-9223372036854775808,9223372036854775807),
    'PositiveSmallIntegerField':(0,32767),
    'PositiveIntegerField':(0,2147483647),
  }
  
12、models.IPAddressField  字符串类型(ip4正则表达式)

13、models.GenericIPAddressField  字符串类型(ip4和ip6是可选的)
  参数protocol可以是:both、ipv4、ipv6
  验证时,会根据设置报错
  
14、models.NullBooleanField  允许为空的布尔类型

15、models.PositiveIntegerFiel  正Integer

16、models.PositiveSmallIntegerField  正smallInteger

17、models.SlugField  减号、下划线、字母、数字

18、models.SmallIntegerField  数字
  数据库中的字段有:tinyint、smallint、int、bigint
  
19、models.TextField  字符串=longtext

20、models.TimeField  时间 HH:MM[:ss[.uuuuuu]]

21、models.URLField  字符串,地址正则表达式

22、models.BinaryField  二进制

23、models.ImageField 图片

24、models.FilePathField 文件

常用参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
1、null=True
  数据库中字段是否可以为空
  
2、blank=True
  django的Admin中添加数据时是否可允许空值
  
3、primary_key =False
  主键,对AutoField设置主键后,就会代替原来的自增 id 列
  
4、auto_now 和 auto_now_add
  auto_now 自动创建---无论添加或修改,都是当前操作的时间
  auto_now_add 自动创建---永远是创建时的时间
  
5、choices
GENDER_CHOICE =(
(u'M', u'Male'),
(u'F', u'Female'),
)
gender = models.CharField(max_length=2,choices = GENDER_CHOICE) #字段模板展示

6、max_length 最大长度

7、default  默认值

8、verbose_name  Admin中字段的显示名称

9、name|db_column  数据库中的字段名称

10、unique=True  不允许重复

11、db_index =True  数据库索引

12、editable=True  在Admin里是否可编辑

13、error_messages=None  错误提示

14、auto_created=False  自动创建

15、help_text  在Admin中提示帮助信息

16、validators=[] 验证器

17、upload-to 重定义上传文件的路径前缀

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Mac平台下使用Charles进行抓包

发表于 2020-09-08

前言

某天,突然产生了对手机访问进行抓包的想法,google了一下,发现在mac下使用charles进行手机访问的抓包比较容易,就进行了一次手机抓包的尝试(安卓手机)。

这里强调一下 安卓应用抓包建议使用Android7.0以下的模拟器进行操作, 否则HTTPS协议的请求可能存在443无法抓取情况

mac安装charles

对于mac下安装charles,网上教程很多,这里不再进行说明,如果有条件的话,最好进行购买。

charles捕获http请求

1、Proxy – macOS Proxy 先打开代理,使得mac上所有请求都通过charles进行代理。

2、Proxy – Proxy Settings 设置监听端口号为8888。

3、此时,用电脑访问百度,就已经可以获取访问的包了,如果我们需要监听手机的访问,就还得在手机上进行设置。

4、先获取电脑的ip地址,Help – Local Ip Address

5、然后在手机连接wifi,此时手机和电脑连接的必须是同一个wifi,然后在手机设置代理。

6、设置完成后,在手机打开一个网址,此时chartles就可以获取到手机访问的包了。

charles捕获https请求

http的请求我们已经可以获取,但是有些网站是https的,如果我们需要解析https的包,就需要安装证书了。

1、Help – SSL Proxying – install Charles Root Certificate,首先在mac安装CA证书。

2、然后要始终信任该证书。

3、Help – SSL Proxying – Install Charles Root Certificate On …,然后生成手机上的证书。

4、Help – SSL Proxying – Save …,然后保存该证书,它会生成一个类似charles-ssl-proxying.pem的文件,把该文件的后缀改为.crt,然后发送到你的安卓手机,进行安装即可。

5、Proxy – SSL Proxying setting,设置你要监听的https请求的网址

6、手机再访问该网址,即可以抓到https的包了。

APP安装报错解决

1. 如果出现打开时提示:xxx.app已损坏,无法打开,那么输入以下指令解决:

1
sudo xattr -d com.apple.quarantine /Applications/xxx.app

其中xxx.app是出问题的APP名称,如名称中有空格,可用“\”加空格代替

2.如果报错

Charles cannot configure your proxy settings while it is on a read-only volume. Perhaps you are running Charles from the disk image? If so, please copy Charles to the Applications folder and run it again. Otherwise please ensure that Charles is running on a volume that is read-write and try again.

解决办法

1
2
sudo chown -R root "/Applications/Charles.app/Contents/Resources"
sudo chmod -R u+s "/Applications/Charles.app/Contents/Resources"

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Ajax 跨域问题及其解决方案

发表于 2020-09-08

什么是 ajax 跨域

主流的前后端分离模式下,当前端调用后台接口时,由于是在非同一个域下的请求,从而会引发浏览器的自我安全保护机制,最终结果是接口成功请求并响应,但前端不能正常处理该返回数据。

Access-Control-Allow-Origin

因此,当同时满足以下三个条件的情况下,就会出现跨域问题:

  1. 浏览器限制
  2. 非同源请求(跨域)
  3. 发送的是 XHR ( XMLHttpRequest ) 请求

跨域问题

解决方案

想要彻底解决跨域问题,只需要破坏以上三个条件的任一即可:

1. 修改浏览器(不推荐)

添加浏览器启动参数:chrome --disable-web-security,但是极不推荐这种解决方式。

2. JSONP请求(不常用)

Jsonp,全称 JSON with Padding,一种非官方的协议,而是一种约定;前端通过向后台发送 script 类型请求解决跨域,此时接口响应的 application/javascript 类型的数据会作为 callback 函数的参数进行处理。

Jsonp Request

所以,后台也需要做相应的处理。以 Java 为例,添加如下配置即可:

1
2
3
4
5
6
7
8
9
@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {

public JsonpAdvice() {
// 前后端约定的jsonp参数名,默认值是callback
super("callback");
}

}

注意,Spring 4.1 版本之后,官方已不再推荐使用上述允许 jsonp 请求的配置,建议使用 CROS 配置来解决跨域问题,详情可查看这里

综上,jsonp 请求存在以下几个弊端:

  1. 服务端需要改动代码进行支持;
  2. 只支持发送 Get 请求,请求头中更改其它类型的请求方式是无效的;
  3. 发送的不是 XHR 请求,而是 script 类型,无法享受到相关的特性。

3. 调用方隐藏跨域

用 Nginx 或 Apache 来代理调用方的请求(客户端变更为相对路径请求,而非绝对路径),此时对于浏览器来说,由于请求是同源的,因此就不存在跨域问题。

4. 被调用方允许跨域(最常用)

  • 服务端配置

以 Java 应用为例,添加如下全局配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Configuration
public class CorsConfig implements WebMvcConfigurer {

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 允许跨域的接口
.allowedOrigins("*") // 允许跨域的请求源
.allowedMethods("*") // 允许跨域的请求方式
.allowedHeaders("*") // 允许跨域的请求头
.allowCredentials(true) // 带cookie请求的时候需要开启,且allowedOrigins需要指定为具体的请求源(最好是动态配置)
.maxAge(60 * 60 * 24); // 设定options请求预检命令的缓存时长
}

}

如果只想针对某个类下的接口,或者是某个具体的接口配置允许跨域,只需要在相应的地方添加注解 @CrossOrigin 即可。

  • Nginx 配置

如果配置了 nginx 作为代理服务器,那么只需要为 nginx 添加支持跨域请求即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server {
listen 80;
server_name xxx.com;

location / {
proxy_pass http://localhost:8080/;

# 配置允许跨域
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Methods *;
add_header Access-Control-Allow-Headers $http_access_control_request_headers;
add_header Access-Control-Max-Age 3600;
add_header Access-Control-Allow-Credentials true;

# 对于options预检请求,直接响应200
if ($request_method = OPTIONS) {
return 200;
}
}
}

扩展思考

Q1:浏览器在执行跨域请求时,是先执行后判断,还是先判断后执行?
A1:都有可能,这需要根据所发送的请求是简单请求还是非简单请求来判断;如果是非简单请求,浏览器每次在执行真正的请求之前,还会先发送一个 options 请求方式的预检命令【 可设定缓存时长,取消每次请求都要预检,提高效率,参考上面的服务端配置 】。关于两种请求的区分及定义,参考下图说明:

简单请求 VS 非简单请求

Q2:如果是允许带(被调用方) cookie 的跨域请求,此时服务端同样配置为 Access-Control-Allow-Origin 等于 *,前端是否还可以请求成功?
A2:不可以,此时要将 Access-Control-Allow-Origin 指定为调用方具体的域【 可以先取得调用方的域再动态配置,这样就不存在多个域请求的限制问题 】,并且添加配置 Access-Control-Allow-Credentials 为 true。

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

向谷歌搜索引擎主动推送网页的教程 Google Indexing API 接口实现

发表于 2020-09-08

谷歌搜索引擎作为全球第一的搜索引擎早就支持了站长主动推送的功能,只不过不是面向普通用户的可视化界面,而是通过编程API接口实现的,有很多站长并不是专业的开发者,但由于谷歌需要验证网站所有权,所以我不能直接做一个可视化界面让站长自己填写自己的秘钥,所以只能对谷歌的接口进行二次封装,以降低使用的难度。

源码项目地址:https://github.com/NeilRen/GoogleIndexing

环境要求

首先,我是以Java为平台进行的封装,JDK版本为1.8,其他程序可能需要中间层才能打通,还不如自己实现,其他编程语言的同学我也没有办法,这个世界上编程语言太多了。

其次,谷歌的Google Indexing API接口在中国大陆无法访问,所以程序需要运行在可以访问谷歌的网络环境中。

前提条件

首先,你需要一个谷歌账号。你的项目是Java的,并且JDK为1.8以上。

创建 Google API 项目

然后在向 Indexing API 发送请求之前,您需要告知 Google 您的客户端并激活对 Indexing API 的访问权限。谷歌为我们提供了一个设置向导,设置向导会引导您在 Google API 控制台中创建项目、启用 Indexing API 以及创建凭据。

首先先跟着向导创建一个项目

Google Indexing API 设置向导

然后转到凭据,添加凭据

Google Indexing API 添加凭证

添加的凭据选择Indexing API、网页服务器(例如 node.js、Tomecat),选择应用数据,点击“我需要哪些凭据?”到下一页

Google Indexing API 为项目添加凭证

创建一个服务账号,名称可以自己起一个名字,秘钥类型选择JSON,点击继续

Google Indexing API 创建服务账号

选择创建无角色账号即可

Google Indexing API 创建无角色账号

这时就会自动下载一个json文件,这个就是我们的私钥,要保存好

Google Indexing API 秘钥

在 Search Console 中验证网站所有权

我们还需要到 Search Console 添加我们的网站,验证所有权,验证成功以后,注意我们要去旧版的控制台,不要去新版的控制台!然后添加所有者

Google 旧版控制台]

所有者的邮箱填写我们上一步获得的私钥JSON文件中的邮箱地址。

Google Indexing API 秘钥JSONGoogle 添加网站所有者

在自己的项目中安装依赖

如果您使用Apache Maven来管理Java项目,只需在项目的pom.xml文件加入相应的依赖项即可。您只需在pom.xml中声明以下依赖:

1
2
3
4
5
<dependency>
<groupId>net.renfei</groupId>
<artifactId>googleindexing</artifactId>
<version>1.0.0</version>
</dependency>

编写代码调用服务,在实例化GoogleIndexing的时候,需要传一个String参数,这个参数是私钥JSON文件所在的文件地址:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import com.alibaba.fastjson.JSON;
import com.google.api.services.indexing.v3.model.UrlNotificationMetadata;
import net.renfei.googleindexing.GoogleIndexing;
import net.renfei.googleindexing.entity.UrlNotification;
import net.renfei.googleindexing.entity.UrlNotificationType;

public class Demo {
public static void main(String[] args) {
try {
GoogleIndexing googleIndexing = new GoogleIndexing("/Users/renfei/Google/Ren-Fei-5a8df7c2b912.json");
UrlNotification urlNotification = new UrlNotification();
urlNotification.setUrl("https://www.renfei.net");
urlNotification.setType(UrlNotificationType.URL_UPDATED);
UrlNotificationMetadata urlNotificationMetadata = googleIndexing.publish(urlNotification);
System.out.printf(JSON.toJSONString(urlNotificationMetadata));
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Hugo博客百度SEO优化 自动提交

发表于 2020-09-08

在切换到Hugo平台之后,比较头疼的是之前hexo很多seo的插件不能使用了. 下面跟大家说一下我的seo优化方案.

Meta标签优化

Description

meta description,被认为是最有用的meta标签,是网站的简介信息。 content控制在100个字符以内比较好。

1
<meta name='description' itemprop="description" content="{{ if .Description }}{{ .Description }}{{ else }}{{if .IsPage}}{{substr .Summary 0 100}}{{ end }}{{ end }}">

Keywords

1
2
3
4
5
{{ if .Keywords }} 
<meta name="keywords" content="{{ delimit .Keywords ", " }}" >
{{else}}
<meta name="keywords" content="{{ delimit .Site.Params.Keywords ", " }}" >
{{ end }}

百度熊掌号推送

说到seo熊掌号是必不可少的了,他可以做到24小时之内收录.所以这个必须不能放过.

gulp

在这里我要使用gulp来做我的自动化任务管理工具

安装gulp需要的模块

1
2
3
4
npm init
npm install gulp --save
npm install xml2js --save
npm install xmlhttprequest --save

在项目根目录创建一个gulpfile.js文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// 导入相关依赖
const gulp = require("gulp");
const fs = require('fs');
const xml2js = require('xml2js')
const parser = new xml2js.Parser();
const XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;


// 注册百度站长与熊掌号,百度会提供下面的数据给你
var xz_appid = '1623792852327580';
var xz_token = 'bbd1f589b763b7fb40e52628c176ae27';
var baidu_token= '79IKQsDuvZSdXwd9'

//熊掌号每天需要提交的url数量
// 注意这个数字必须要跟百度允许提交的url数量一致,如果多了会提交失败.
const xzCount = 2000


// 创建一个任务
gulp.task('baiduSeo', () => {
// 读取sitemap.xml文件并且转换成json
fs.readFile(__dirname + '/public/sitemap.xml', function(err, data) {
parser.parseString(data, function (err, result) {
// 把读取的数据传入这个函数
urlSubmit(result.urlset.url)
console.log('Done');
});
});
});

// 提交url的方法
function urlSubmit(urls) {
// 最新内容提交
var new_target = "http://data.zz.baidu.com/urls?appid="+xz_appid+"&token="+xz_token+"&type=realtime"

// 历史提交
var history_target = "http://data.zz.baidu.com/urls?appid="+xz_appid+"&token="+xz_token+"&type=batch"

// 百度站长
var baidu_target = "http://data.zz.baidu.com/urls?site=https://zaina.newban.cn&token="+baidu_token

// MIP
var MIP_target = "http://data.zz.baidu.com/urls?site=https://zaina.newban.cn&token="+baidu_token+"&type=mip"

// AMP
var AMP_target = "http://data.zz.baidu.com/urls?site=https://zaina.newban.cn&token="+baidu_token+"&type=amp"

// 最新url,看熊掌号情况而定
urls = urls.map(item=>item.loc[0])
allUrls = urls.join('\n')

var new_urls_Arr = urls.slice(0,xzCount)
new_urls= new_urls_Arr.join('\n');

console.info('百度站长开始提交',new_urls)
sendData(baidu_target,new_urls,'百度站长提交成功')

console.info('熊掌号开始提交')
//sendData(new_target,new_urls,'熊掌号提交完成')

// 提交历史url 每天最多500w条
console.info("历史数据开始提交")
//sendData(history_target,allUrls,"历史数据提交完成")

console.info("MIP 开始提交")
//sendData(MIP_target,allUrls,"MIP提交成功")

console.info("AMP 开始提交")
//sendData(AMP_target,allUrls,"AMP提交成功")

// 提交数据
function sendData(target,urls,message){
var xhr = new XMLHttpRequest();
xhr.open('POST', target, false);
xhr.setRequestHeader('Content-type', 'text/plain');
xhr.onload = function () {
console.log(this.responseText);
if(message){console.info(message)}
};
xhr.send(urls);
}

};

gulp.task("default",gulp.series( 'baiduSeo',function(){}))

配置好以上都文件之后

推送

1
2
3
4
# 博客生成
hugo
# url推送
gulp

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Python的.sort()方法和sorted()比较总结

发表于 2020-09-07

1,.sort()方法

  使用方式是:列表.sort(),作用是将原来的列表正序排序,所以它是对原来的列表进行的操作,不会产生一个新列表,例如:

1
2
3
4
5
6
7
8
9
10
11
12
import  random
numList=[]
print(numList)
for i in range(10):
numList.append(random.randrange(1,10))# 不包括10
print("未排序的列表:",numList)
# numList.sort()执行过程是将列表拍完序后又赋值给了原列表
numList.sort()
print("排序后列表:",numList)
# 无法将numList.sort()赋值给一个新列表,以为它并不返回一个新列表
numList=numList.sort()
print("无法赋值给新列表的的结果:",numList)

执行结果:

1
2
3
未排序的列表: [7, 2, 2, 4, 5, 6, 7, 9, 4, 8]
排序后列表: [2, 2, 4, 4, 5, 6, 7, 7, 8, 9]
无法赋值给新列表的的结果: None

2,sorted(列表),是Python内置函数,该函数对原列表不会产生影响,只是在原来列表的基础上,产生一个有序的新列表,可以复制一个列表名

1
2
3
4
5
6
7
8
9
10
11
import  random
numList=[]
print(numList)
for i in range(10):
numList.append(random.randrange(1,10))# 不包括10
print("未排序的列表:",numList)

sorted(numList)
print("sorted排序后的数组,不会对原列表有任何影响:",numList)
getList=sorted(numList)
print("sorted获得的新的列表:",getList)

执行结果:

1
2
3
未排序的列表: [1, 4, 3, 4, 3, 9, 5, 4, 4, 9]
sorted排序后的数组,不会对原列表有任何影响: [1, 4, 3, 4, 3, 9, 5, 4, 4, 9]
sorted获得的新的列表: [1, 3, 3, 4, 4, 4, 4, 5, 9, 9]

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

App自动化之Appium入门

发表于 2020-09-07

像Selenium可以操控Web浏览器,手机APP平台也有类似的自动化测试工具:Appium;
全文分基础介绍、环境搭建和案例演示三部分介绍Appium,以帮助Learner快速的上手。

基础介绍

Appium是一个开源的自动化测试框架,用于原生,混合和移动Web应用程序。 它使用WebDriver协议驱动iOS,Android和Windows应用程序。关于它的运作流程,用图来介绍会更加生动形象一些:

Appium运行流程、原理

在上图中,左边这部分是Appium-Client,通俗点来说,是用于间接驱动最右边的设备执行预定的自动化测试流程,支持使用多种主流的编程语言进行编写,这也是测试开发人员需要关注的核心部分;中间的Appium-Server是衔接左边客户端以及右边APP设备端的重要桥梁,一般仅需要配置好环境及启动运行;右边这块,当然就是实际执行自动化测试的终端,如IOS真机、Android真机,或者是模拟器。

环境搭建

  • NodeJS

Appium是使用nodejs实现的,因此Node是解释器,首先要确认安装好

  • Appium-Server
    • nodejs
    • appium-desktop

上述的两种方式都可以搭建Appium-Server环境,后面演示会基于Appium-Desktop。(PS:下载太慢了?分享个百度网盘)

  • Andrioid SDK
    • android sdk
    • android studio

上述方式可以直接和间接搭建安装Android环境,因为后面要用到adb这个工具,所以需要配置好ANDROID_HOME这个环境变量。(PS:下载太慢了?分享个百度网盘)

  • Appium-Python-Client

后面会用到Python来编写Appium客户端:pip install Appium-Python-Client

okay,准备好以上几个环境后,启动Appium测试一下:

Appium Desktop Server

Appium Desktop Server

案例演示

下面演示在安卓真机上的自动登录Keep(APP)。

  1. 获取设备名称。操作流程:开启手机的开发和调试模式,连接电脑授权认证,Window + R输入并运行cmd,用adb devices -l查看:

获取设备号

  1. 启动Appium Server进行调试:

Inspector Session

Desired Capabilities

从上图可以看到,启动App Session需要有以下几个参数(点击了解更详细的Appium Desired Capabilities):

  • platformName,如Android、iOS等
  • deviceName,参考前面是如何获取的
  • appPackage和appActivity,获取参考这里

综上所述,这里对应Keep的信息如下:

1
2
3
4
5
6
{
"platformName": "Android",
"deviceName": "WAS_AL00",
"appPackage": "com.gotokeep.keep",
"appActivity": "com.gotokeep.keep.splash.SplashActivity"
}

点击Start Session,之后可以看到手机端启动了Keep,并且在Appium Server端中同步展示:

Start Session

Keep

上述的操作通常只是用来方便获取控件id及定位的,下面基于Python编写完整的Appium-Client以实现自动登录操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

server = 'http://localhost:4723/wd/hub' # Appium Server, 端口默认为4723
desired_capabilities = {
'platformName': 'Android',
'deviceName': 'WAS_AL00', # 需替换成你的deviceName
'appPackage': 'com.gotokeep.keep',
'appActivity': 'com.gotokeep.keep.splash.SplashActivity'
}

driver = webdriver.Remote(server, desired_capabilities)
wait = WebDriverWait(driver, 10) # 最大查找等待超时时间:10s


def get_permission():
"""允许APP获取的某些权限"""

try:
ask = wait.until(EC.presence_of_element_located((By.ID, 'com.android.packageinstaller:id/do_not_ask_checkbox')))
ask.click()
allow = wait.until(
EC.presence_of_element_located((By.ID, 'com.android.packageinstaller:id/permission_allow_button')))
allow.click()
except:
pass


# 允许两项授权
get_permission()
get_permission()

# 点击“立即使用”
welcome = wait.until(EC.presence_of_element_located((By.ID, 'com.gotokeep.keep:id/btn_bottom_in_video_welcome')))
welcome.click()

# 切换“密码登录”(同样可以使用第三方进行授权登录)
driver.tap([(900, 110)])

# 输入“手机号”
phone = driver.find_element_by_accessibility_id('Phone Number In Login')
phone.send_keys('13988888888') # 替换成实际的账号

# 输入“密码”
password = driver.find_element_by_accessibility_id('Password In Login')
password.send_keys('123456') # 替换成实际的密码

# 点击“登录”
login = driver.find_element_by_id('com.gotokeep.keep:id/btn_action')
login.click()

最后,附上运行效果图:

效果图

本文转载自;https://blog.mariojd.cn/get-started-with-appium.html

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Python跨平台之将Python 程序打包成Windows和Linux可执行文件

发表于 2020-09-07

通常执行 python 程序要有相应的 Python 环境,但某些特定场景下,我们可能并不愿意这么麻烦的去配置这些环境(比如将写好的脚本发给客户进行操作),如果可以提前将程序打包成 Windows平台的 .exe 文件或者是Linux下的 .sh 脚本,那么使用起来就会方便很多,py2exe 和 PyInstaller 这两款工具都是干这么个事的,下面以 hello.py 脚本(代码内容如下)为例进行介绍。

1
2
age = input("How old are you?\n")
print("A: " + age)

提示:PyInstaller 可以在 Windows 和 Linux 下使用,更推荐使用,而 py2exe 暂不支持 Linux 平台 而且只支持python低版本环境

PyInstaller

  1. 安装
1
pip install pyinstaller
  1. 使用

常见的用法有:

  • 生成单个可执行文件:pyinstaller -F hello.py
  • 生成指定icon的可执行文件:pyinstaller -i xxx.ico hello.py

在当前目录下的 dist 文件夹内可以找到生成后的可执行文件(脚本),更多用法请参考说明

py2exe

  1. 安装
1
pip install py2exe
  1. 使用

如上图,打包失败了,留意到这里说不支持 python3.6,果断放弃,有兴趣的可以自行降低到 python3.4 或 python3.5 进行尝试。

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

wireshark怎么抓包、wireshark抓包详细图文教程

发表于 2020-09-07

wireshark是非常流行的网络封包分析软件,功能十分强大。可以截取各种网络封包,显示网络封包的详细信息。使用wireshark的人必须了解网络协议,否则就看不懂wireshark了。
为了安全考虑,wireshark只能查看封包,而不能修改封包的内容,或者发送封包。

wireshark能获取HTTP,也能获取HTTPS,但是不能解密HTTPS,所以wireshark看不懂HTTPS中的内容,总结,如果是处理HTTP,HTTPS 还是用Fiddler, 其他协议比如TCP,UDP 就用wireshark.

wireshark 开始抓包

开始界面

img

wireshark是捕获机器上的某一块网卡的网络包,当你的机器上有多块网卡的时候,你需要选择一个网卡。

点击Caputre->Interfaces.. 出现下面对话框,选择正确的网卡。然后点击”Start”按钮, 开始抓包

img

Wireshark 窗口介绍

img

WireShark 主要分为这几个界面

\1. Display Filter(显示过滤器), 用于过滤

\2. Packet List Pane(封包列表), 显示捕获到的封包, 有源地址和目标地址,端口号。 颜色不同,代表

\3. Packet Details Pane(封包详细信息), 显示封包中的字段

\4. Dissector Pane(16进制数据)

\5. Miscellanous(地址栏,杂项)

img

使用过滤是非常重要的, 初学者使用wireshark时,将会得到大量的冗余信息,在几千甚至几万条记录中,以至于很难找到自己需要的部分。搞得晕头转向。

过滤器会帮助我们在大量的数据中迅速找到我们需要的信息。

过滤器有两种,

一种是显示过滤器,就是主界面上那个,用来在捕获的记录中找到所需要的记录

一种是捕获过滤器,用来过滤捕获的封包,以免捕获太多的记录。 在Capture -> Capture Filters 中设置

保存过滤

在Filter栏上,填好Filter的表达式后,点击Save按钮, 取个名字。比如”Filter 102”,

img

Filter栏上就多了个”Filter 102” 的按钮。

img

过滤表达式的规则

表达式规则

\1. 协议过滤

比如TCP,只显示TCP协议。

\2. IP 过滤

比如 ip.src ==192.168.1.102 显示源地址为192.168.1.102,

ip.dst==192.168.1.102, 目标地址为192.168.1.102

\3. 端口过滤

tcp.port ==80, 端口为80的

tcp.srcport == 80, 只显示TCP协议的愿端口为80的。

\4. Http模式过滤

http.request.method==”GET”, 只显示HTTP GET方法的。

\5. 逻辑运算符为 AND/ OR

常用的过滤表达式

过滤表达式 用途
http 只查看HTTP协议的记录
ip.src ==192.168.1.102 or ip.dst==192.168.1.102 源地址或者目标地址是192.168.1.102
snmp && udp.dstport == 162 抓取SNMP Trap包

封包列表(Packet List Pane)

封包列表的面板中显示,编号,时间戳,源地址,目标地址,协议,长度,以及封包信息。 你可以看到不同的协议用了不同的颜色显示。

你也可以修改这些显示颜色的规则, View ->Coloring Rules.

img

封包详细信息 (Packet Details Pane)

这个面板是我们最重要的,用来查看协议中的每一个字段。

各行信息分别为

Frame: 物理层的数据帧概况

Ethernet II: 数据链路层以太网帧头部信息

Internet Protocol Version 4: 互联网层IP包头部信息

Transmission Control Protocol: 传输层T的数据段头部信息,此处是TCP

Hypertext Transfer Protocol: 应用层的信息,此处是HTTP协议

img

TCP包的具体内容

从下图可以看到wireshark捕获到的TCP包中的每个字段。

img

看到这, 基本上对wireshak有了初步了解, 现在我们看一个TCP三次握手的实例

三次握手过程为

img

这图我都看过很多遍了, 这次我们用wireshark实际分析下三次握手的过程。

打开wireshark, 打开浏览器输入 http://www.cr173.com

在wireshark中输入http过滤, 然后选中GET /tankxiao HTTP/1.1的那条记录,右键然后点击”Follow TCP Stream”,

这样做的目的是为了得到与浏览器打开网站相关的数据包,将得到如下图

img

图中可以看到wireshark截获到了三次握手的三个数据包。第四个包才是HTTP的, 这说明HTTP的确是使用TCP建立连接的。

第一次握手数据包

客户端发送一个TCP,标志位为SYN,序列号为0, 代表客户端请求建立连接。 如下图

第二次握手的数据包

服务器发回确认包, 标志位为 SYN,ACK. 将确认序号(Acknowledgement Number)设置为客户的I S N加1以.即0+1=1, 如下图

第三次握手的数据包

客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1.并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写ISN的+1, 如下图:

就这样通过了TCP三次握手,建立了连接

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

1…373839…48

乱码三千

android程序员一枚,擅长java,kotlin,python,金融投资,欢迎交流~

479 日志
139 标签
RSS
© 2024 乱码三千
本站总访问量次
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4
0%