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

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


  • 首页

  • 归档

  • 搜索

Clash for Android使用教程

发表于 2021-12-24

简介

Clash for Android是安卓系统上的一款综合FQ软件,支持v2ray/vmess、SS和SSR协议。

特性:

  • 可随时切换DL模式及节点
  • 支持节点批量延迟测试
  • 通过订阅链接一键配置
  • 规则命中分析
  • 日志输出

系统要求:

  • Android 5.0+ (minimum)
  • Android 7.0+ (recommend)
  • armeabi-v7a , arm64-v8a, x86 or x86_64 Architecture

下载安装

Clash for Android为免费 app ,已于 2019.12.10 上架 Google Play 。

Clash for Android下载:本站下载 、Google Play 国内快速下载通道(访问密码:312306)

安卓手机使用 Chrome 浏览器可能遇到无法下载的情况,可复制教程链接到其它浏览器尝试下载。

语言设置路径:Settings → Interface → Language → Simplified Chinese
设置 👉 界面 👉 语言 👉 简体中文

快速上手

Clash for Android支持两种导入节点及配置文档的方式:

  • URL (订阅)
  • 本地导入

快速订阅

以下面这个订阅链接为例, 给大家做个示范:
https://v1.ddnsgo.xyz/link/11111?clash=1

复制好了Clash订阅之后打开Clash for Android应用程序。请点击配置。

IMG_7843.JPG

请在新弹出的窗口中点击新配置。
IMG_7844.JPG
然后选择从URL导入。在对应地方填写订阅地址并保存。
IMG_7845.JPG
IMG_7847.JPG
IMG_7849.JPG
点击节点右侧的三个点按钮,可以修改订阅设置。如图:
IMG_7850.JPG
提示:机场服务器信息可能会不定时更新,若出现大面积节点超时现象,可尝试刷新订阅。
返回首页。点击开关,即可进行DL。会提示是否同意创建连线,请点击允许。
IMG_7851.JPG
开启DL后,可以点击中间的DL选项卡,进入策略组面板,在这里可以切换节点。直接点击你想要的节点即可进行切换。
IMG_7852.JPG
点击⚡图标可以进行延迟测试,测试结果将显示在节点名称右侧。

Clash for Android 测试延迟的方法为从目标 policy 返回 http response header 数据包的时间,并不是简单的ping 。
测试延迟会导致机场网页上显示的在线设备数异常飙升,这是正常现象,等一等就好了。

点击右上角的三个点按钮,可以进入更多设置:

  • 刷新订阅
  • 更改DL模式
  • 改变DL组(策略组)排序
  • 改变DL(节点)排序
  • 前缀合并(即节点名字前缀相同的进行归类显示)
    IMG_7853.JPG
    IMG_7854.JPG

本地文件导入

点击 配置 👉 新配置 👉 从文件导入,然后从本地文件夹选择自己要导入的配置文档。
某些厂商的ROM可能报如下错误,请选择其他文件管理器导入。
10

查询日志

点击日志面板,然后选择Clash日志捕捉工具即可抓取日志。默认是关闭日志的,以防内存溢出。
IMG_7857.JPG
IMG_7858.JPG
IMG_7859.JPG

其他设置

IMG_7860.JPG
IMG_7862.JPG

分应用DL

点击设置 👉 网络,最下方可以设置分应用DL。
点击访问控制模式可以切换黑白名单。自行理解即可。
点击访问控制应用包列表即可选择应用。
IMG_7863.JPG

切换DL模式

如果是2.0.18及之前的版本,DL模式设置路径为DL → 模式,如图:
IMG_7853.JPG
IMG_7854.JPG

3.6.2 2.1.1之后的版本

如果是2.1.1之后的版本,DL模式设置路径为设置 → 覆写 → 模式,如图:
IMG_4577.JPG
IMG_4579.JPG
IMG_4578.JPG

语言设置

语言设置路径:Settings → Interface → Language → Simplified Chinese
设置 👉 界面 👉 语言 👉 简体中文
IMG_7864.JPG
若当前系统语言为简体中文,则软件默认显示简体中文。
若当前系统语言为繁體中文或其它语言,则默认显示English。

暗黑模式

Clash for Android现已适配暗黑模式。
入口:设置 👉 界面 👉 暗黑模式
开启后效果如图:
IMG_7865.JPG
IMG_7866.JPG

常见的订阅错误报告

如果遇到以下提示:

1
Invalid Config:yaml:unmarshal errors: line 1:cannot unmarshal !!str c3M6Ly9...点击拷贝拷贝失败拷贝成功

说明用错了订阅链接,请检查自己是不是复制错了或者多了空格之类的。

如果遇到此类提示:

1
Invalid Config:Value for 'Proxy' is invalid:Unexpected null or empty点击拷贝拷贝失败拷贝成功

说明你还没买套餐,或者订阅为空。请联系你所在机场的管理员。

易用性设置

大部分安卓ROM都会因为电池策略导致Clash for Andorid应用程序被杀掉导致无法连接网络。出现这种情况的特征是通知栏中连接仍然存在,但实际上无法访问网络(有时也包括国内网络)。这是因为Clash for Android主程序和大爬梯框架是独立存在的,主程序被系统清理后会导致流量仍然通过大爬梯路由到本地,但此时没有应用程序来处理这些流量,导致无法上网。

始终开启大爬梯

以RealmeX(Android 10)为例,点击设定 👉 其他无线连接 👉 VVN,打开一律保持连线。
IMG_7868.JPG
IMG_7869.JPG
IMG_7872.JPG
IMG_7873.JPG

省电策略/允许后台运行

长按Clash图标,选择应用程式资讯。
勾选允许自动啓动和允许其他应用程式关联啓动。
点击耗电保护,选择允许背景执行。
IMG_7874.JPG
IMG_7875.JPG
IMG_7876.JPG

通知栏快速启动

IMG_7878.JPG
IMG_7879.JPG

注意:Clash使用 HTTP HEAD 方法对测试网址(server_check_url)进行网页相应测试,以确认节点的可用性。数值在5000以内均为正常值,超出则显示为超时。数值大小和网速快慢没太大关系。

本文转载自:https://w1.v2dns.xyz/doc/#/Android/clash

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

Mac平台对Chrome浏览器进行多开操作实现

发表于 2021-12-23

前言

对于老司机而言, 浏览器多开是个常规必备的需求, 这种多开并非指的的开一个新的窗口, 而是一个新的应用, 这样我们就能在某个网站登录多个小号, 避免反反复复的来回繁琐登录 嘿嘿

接下来 以Mac平台为例, 介绍下如何对谷歌浏览器进行多开操作

操作步骤

  1. 首先打开终端输入以下命令, 创建小号浏览器数据存放目录

    1
    mkdir ~/Documents/NewChrome
  2. 然后复制应用, 并对新应用进行重新命名 这里命名为New Chrome

    image-20211223153504315

  3. 进入到程序目录 找到执行文件所在目录

    image-20211223153815748

  4. 在该目录下新建一个文本文件, 然后将以下代码写入该文件

    1
    sudo /Applications/New\ Chrome.app/Contents/MacOS/Google\ Chrome --user-data-dir="/Users/Documents/NewChrome"
  5. 在终端执行以下命令将文本文件转成可执行文件

    1
    chmod 775 文件名

    执行该命令前先将文本文件后缀删掉

    最后变成这个样子:

    image-20211223154717658

  6. 双击该文件即可运行

    image-20211223154754427

总结

Chrome多开的核心在于数据文件的指定, 也就是在启动浏览器时只要指定一个新的数据目录就相当于多开了, 这个数据目录保存了浏览器所有的数据信息 包括了Cookie 用户密码 插件信息等等

因此, 实际上只需要执行以下命令就可以快速多开:

1
sudo /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --user-data-dir="小号浏览器数据存放目录"

上面的步骤中之所以复制一个新的应用, 是为了避免误操作毁了原来的应用, 建议大家在使用时也复制一份, 这样怎么折腾都无妨了

如果我们要多开好几个那么创建多个数据目录即可:

image-20211223164554218

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

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

Android中关于设置屏幕是否休眠的几种方法介绍

发表于 2021-12-21

前言

我们在做视频播放的放得时候 , 肯定会有这样的一个需求, 那就是视频播放时禁止锁屏息屏, 视频暂停或者退出时恢复锁屏息屏

那么, 有以下几种方法供大家参考

方法一:持有WakeLock

添加休眠锁,休眠锁必须成对出现。

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
private WakeLock mWakeLock = null;

private void acquireWakeLock() {
if(mWakeLock == null) {

PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);

mWakeLock = pm.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP,
this.getClass().getCanonicalName());

mWakeLock.acquire();
}

}
@Override
protected void onResume() {
super.onResume();
acquireWakeLock();
}

@Override
protected void onPause() {
super.onPause();
releaseWakeLock();
}

private void acquireWakeLock(){
if(mWakeLock != null) {
mWakeLock.acquire();
}
}
private void releaseWakeLock() {
if(mWakeLock != null) {
mWakeLock.release();
///mWakeLock = null;
}
}

在onResume以及onPause执行相应操作

AndroidManifest.xml 文件中添加权限:

1
2
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.DEVICE_POWER" />

WakeLock获取时相关的flag如下所示:

  • PARTIAL_WAKE_LOCK :保持CPU 运转,屏幕和键盘灯有可能是关闭的。
  • SCREEN_DIM_WAKE_LOCK :保持CPU 运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯
  • SCREEN_BRIGHT_WAKE_LOCK :保持CPU 运转,允许保持屏幕高亮显示,允许关闭键盘灯
  • FULL_WAKE_LOCK :保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度

PS:现在官方已经不推荐使用这种方式保持亮屏了,推荐改为以下两种方式

方法二:在Window设置flag

在Activity布局中设置Windows属性进行控制,但是一定要在加载布局之前执行,此种方法的局限性是只有在Activity类中有效,Activity退出时失效。

1
2
3
4
5
6
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, 
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.***);

//或者设置下面的也一样
//getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

这种方式不需要申请权限,也是官方推荐的做法

这个方法的好处是,与wakelocks不同 ,它不需要具体的权限,并且在换不同应用程序的操作中,系统会管理,不必担心没有释放的未使用的资源。

你并不需要清除FLAG_KEEP_SCREEN_ON标志,除非你不再需要在屏幕上停留在你运行应用程序。当应用程序进入后台或返回到前台发生,窗口管理器负责保障正常的事件处理,但是如果你明确的想要清除这个标致,从而允许屏幕熄灭,可以使用 clearFlags() 方法

如下:

1
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

就可以控制屏幕熄灭了

*方法三:在界面布局xml中顶层添加属性

在View布局中添加属性,此种方法的好处是不一定非要在Activity界面运行时屏幕常亮才有效,View启动后可以自主设置。

View的xml布局中加入:

在XML文件中,使用android:keepScreenOn属性

1
2
3
4
5
6
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true">
...
</relativelayout>

这个设置 android:keepScreenOn=“true” 等同于FLAG_KEEP_SCREEN_ON。

代码中执行是否保持屏幕常亮:

1
2
View.setKeepScreenOn(true);
View.setKeepScreenOn(false);

转载自:https://blog.csdn.net/CLinuxF/article/details/103273411

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

关于机场订阅链接转换

发表于 2021-12-16

前言

一直在用免费的大爬梯, 虽然不是太稳定, 但是也够用了 , 平常外网需求并不是太多

给大家推荐一个机场订阅链接在线转换工具:

点击进入

image-20211216113509711

该项目已经开源, 源码地址如下:

GitHub

哪里找大爬梯

我个人平常的大爬梯需求基本上都是在Github上找的, 比如 V2Free

其他的大家可以自行搜索

另外以下这个网站每天也会更新ssr和TG节点:

  • SSR

  • 免费TG代理

目前在用的是V2free的免费服务, 每天签到可以获取免费流量, 配合ClashX使用, 速度还不错哦

如下图:

image-20211216115040948

具体参见: 点击进入

image-20211216114733195

具体参见: 点击进入, 备用地址

附加

  • Telegram频道在线搜索

大爬梯试用

如果你不想花钱, 只是紧急临时用一下, 可以考虑一些提供试用的大爬梯软件, 比如:

  • 西柚加速器: 官网链接

    一个手机号可以试用一天, 如果你有多个手机号, 那么 嘿嘿

  • auVPN: 官网链接

    0.9美元试用7天, 支持支付宝付款

  • v2free: 官网链接 GitHub

    3元试用三天

注意事项

如果打算长期使用某一款大爬梯, 切记不要选择那种用手机号注册的, 尽量选择用邮箱注册, 邮箱也最好使用国外的, 至于为什么, 大家都懂的哈哈

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

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

2021年终总结 这要从我抽中了小爱音响开始说起

发表于 2021-12-14

最近参加了掘金的年终总结活动, 临时起意写了一篇文章, 点击进入掘金, 为了礼品我也是够拼了 哈哈 以下是原稿:

站立和倾斜在树上的女人

「时光不负,创作不停,本文正在参加2021年终总结征文大赛」

所谓无图不丈夫 XDM喜欢否?

前言

今天办公室异常闷热 热得我一看屏幕就眼睛发肿, 导致无法正常工作

于是乎 原本没打算参加年终总结活动的我写起了总结

唯一的动力就是掘金的大礼 哈哈

说到大礼 昨天不小心抽中了一个小爱音响 还在活动群炫耀了一番:

image-20211214100831346

image-20211214100925150

说到抽奖 作为一个在年会经常抽中一等奖的我 在这给大家分享一下个人的心得:

  • 首先 你要有一个抽奖资格 …

  • 然后 在抽奖的这段时间里 内心一定要保持非常开心的状态 让自己兴奋起来 男同胞们如果不够兴奋可以多看几遍上面那张大图, 也就是让抽奖机感受到你的激情 让对方明白你非常想要 哈哈

  • 这听起来似乎有点玄 不过没关系 不用太在意这些细节 你要想象成这奖品已经到了手

  • 一切准备好后 开始抽奖 那么中奖概率能大幅提升一个档次 咳咳

如果抱着无所谓的态度 那么抽中的概率会大大降低 , 所谓心心念念 必有回响嘛

以上只是个人经验瞎扯 无科学根据 仅供参考哈哈

下面附上我16年公司年会抽中的一个ipad mini:

image-20211214100209725

目前将其当做第二屏使用, 提升生产力的同时, 还能缓解颈椎不适, 嘿嘿

今年收获

今年收获很大, 话不多说, 直接看下面:

  • SKG颈椎按摩器时尚语音款 一台
  • 瑞视达T1手机投影仪 一台
  • 小霸王D99增强版游戏机 一台
  • 小熊咖啡机全自动滴漏式0.7L 一个
  • 多元兼容黑色帆布双肩包 一个
  • 未来星乐园”定制积木 一座
  • 字节跳动智能感温保温杯 一只
  • 掘金 T 恤 一件
  • 掘金棒球帽 两顶
  • 掘金搪瓷杯 两只
  • 字节跳动空调毯 一床
  • 小册优惠码 两个
  • 掘金Bug 52个

image-20211214103132112

image-20211214103224187

明年Flag

明年我打算把Q400游戏机拿下 ​​

未来五年

争取把任天堂 NS 拿下

我已经做好了打持久战的准备了 哈哈哈

最后

再次感谢掘金, 让我收获了这么多的礼品

另外

近期 我的第三张个人原创音乐专辑已经全网上线了, 欢迎大家前来捧场, 以下是网易云试听链接:

茶余饭后

​

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

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

一个简单的在线制作 lrc 文件的小工具

发表于 2021-12-11

前言

最近音乐专辑上线, 需要给歌曲制作lrc滚动歌词, Mac平台这方好使的软件不多, 于是尝试找个能在线通过网页制作歌词的网站, 最后找到了这个:

网站地址: https://judes.me/lrc_editor/

用了一下 感觉还不错, 而且项目是开源的, 源码地址如下:

GitHub链接

音乐专辑

我的第三张个人原创音乐专辑《茶余饭后》大部分歌曲歌词都是用这个工具制作的, 以下是网易试听链接:

专辑已经全网上架, 欢迎大家来捧场哦~

​

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

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

Web自动化框架selenium的介绍与使用

发表于 2021-12-02

介绍

selenium 是一个 web 的自动化测试工具,可以模拟人工Web浏览,, 适合用于自动化处理和爬虫任务, 该框架支持C、 java、ruby、python等多种语言, 支持三大操作系统和各种常见浏览器

官方文档:

  • https://selenium-python.readthedocs.io/index.html
  • https://seleniumhq.github.io/selenium/docs/api/py/api.html

接下来以python为例, 给大家介绍selenium 的具体使用

selenium使用前准备

  1. 框架安装

    1
    pip install selenium
  2. web驱动安装

    推荐下载使用谷歌或火狐浏览器, 然后根据浏览器版本安装与之对应版本的驱动, 这里我使用的是谷歌浏览器

    打开浏览器设置, 查看浏览器版本:

    在这里插入图片描述

    然后下载驱动:

    ChromeDriver下载地址

    在这里插入图片描述

    谷歌123之后的版本驱动下载地址

    image-20240417115034597

    将下载的驱动解压到以下目录:

    1
    2
    Win:复制webdriver到Python安装目录下
    Mac:复制webdriver到/usr/local/bin目录下

    如果是火狐浏览器同理,以下是两大类浏览器驱动下载备用链接:

    Chrome ( chromedriver ) Firefox ( geckodriver )
    官方下载 官方下载
    淘宝镜像 淘宝镜像
    备用下载 备用下载

    接下来 我们开始引入框架并使用

  3. 框架引入

    1
    from selenium import webdriver

开始使用

  1. 自动打开浏览器访问某个网页

    1
    2
    3
    4
    from selenium import webdriver

    browser = webdriver.Chrome()
    browser.get('http://www.baidu.com/')
  2. 获取网页的源码

    1
    2
    3
    4
    5
    from selenium import webdriver

    browser = webdriver.Chrome()
    browser.get('http://www.baidu.com/')
    print(browser.page_source)
  3. 不打开浏览器获取网页源码

    很多情况下我们只需要让程序在后台静默执行就行, 不需要频繁开启浏览器, 那么我们需要对驱动进行相关设置, 如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    from selenium import webdriver
    chrome_options = webdriver.ChromeOptions()
    # 使用headless无界面浏览器模式
    chrome_options.add_argument('--headless') #增加无界面选项
    chrome_options.add_argument('--disable-gpu') #如果不加这个选项,有时定位会出现问题

    browser = webdriver.Chrome(chrome_options=chrome_options)
    browser.get('http://www.baidu.com/')
    print(browser.page_source)
  4. 以指定配置启动浏览器

    常用浏览器有常用的一些设置, 如果我们想在自动化的过程中加载进来可以使用add_argument方法, 如下:

    1
    2
    3
    4
    5
    #coding=utf-8
    from selenium import webdriver
    option = webdriver.ChromeOptions()
    option.add_argument('--user-data-dir=C:\Users\Administrator\AppData\Local\Google\Chrome\User Data') #指定数据目录
    driver=webdriver.Chrome(chrome_options=option)
  5. 指定驱动的目录

    除了将下载的驱动存放到系统指定目录使用之外, 我们还可以直接指定驱动的存放路径, 方便我们临时测试多个不同的驱动效果, 配置方法如下:

    1
    2
    3
    driver_path = r'D:\ProgramApp\chromedriver\chromedriver.exe'
    # 初始化一个driver,并且指定chromedriver的路径
    driver = webdriver.Chrome(executable_path=driver_path)
  6. webdriver常用api汇总

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    browser = webdriver.Chrome()

    browser.get_cookies() #获取所有的cookies
    browser.page_source #获取网页源码
    browser.delete_all_cookies() #删除所有cookies
    browser.delete_cookie(key) #删除某个cookies
    browser.implicitly_wait(10) #设置超时时间
    browser.execute_script("window.open('https://www.douban.com/')") #打开一个新页面
    browser.title #获取网页标题
    browser.current_url #获取当前网页url
    browser.capabilities['version'] #获取浏览器版本号
    browser.maximize_window() #浏览器最大化
    browser.minimize_window() #浏览器最小化
    browser.set_window_size(480, 800) #设置浏览器宽高
    browser.forword() # 页面前进
    browser.back() #页面后退
    browser.close() #关闭当前页面
    browser.quit() #退出整个浏览器

    注意: 如果访问一些需要有cookie验证的页面,我们可以先访问主页,然后再访问详情页,webdriver会自动携带cookie

  7. ChromeOptions常用函数汇总

    1
    2
    #设置代理ip
    options.add_argument("--proxy-server=http://110.73.2.248:8123")
  1. 网页元素定位查找

    • 通过元素ID进行定位

      1
      browser.find_element_by_id()
    • 通过标签名的方式进行定位

      1
      browser.find_element_by_tag_name("input")
    • 通过class的方式进行定位

      1
      browser.find_element_by_class_name("xxx")
    • 通过css方式定位

      1
      browser.find_element_by_css_selector("xxx")
  1. 事件模拟

    主要分为键盘事件和鼠标事件

    1. 键盘事件

      通过 send_keys()调用键盘按键, 比如:

      1
      2
      3
      4
      from selenium.webdriver.common.keys import Keys

      send_keys(Keys.TAB) # TAB
      send_keys(Keys.ENTER) # 回车

      参考代码如下:

      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
      #coding=utf-8 
      from selenium import webdriver
      from selenium.webdriver.common.keys import Keys #需要引入 keys 包
      import os,time

      driver = webdriver.Firefox()
      driver.get("http://passport.kuaibo.com/login/?referrer=http%3A%2F%2Fwebcloud .kuaibo.com%2F")

      time.sleep(3)
      driver.maximize_window() # 浏览器全屏显示

      driver.find_element_by_id("user_name").clear()
      driver.find_element_by_id("user_name").send_keys("fnngj")

      #tab 的定位相相于清除了密码框的默认提示信息,等同上面的 clear()
      driver.find_element_by_id("user_name").send_keys(Keys.TAB)
      time.sleep(3)
      driver.find_element_by_id("user_pwd").send_keys("123456")

      #通过定位密码框,enter(回车)来代替登陆按钮
      driver.find_element_by_id("user_pwd").send_keys(Keys.ENTER)

      #也可定位登陆按钮,通过 enter(回车)代替 click()
      driver.find_element_by_id("login").send_keys(Keys.ENTER)
      time.sleep(3)

      driver.quit()

      键盘组合键的用法:

      1
      2
      #ctrl+a 全选输入框内容 
      driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'a')
      1
      2
      #ctrl+x 剪切输入框内容 
      driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'x')
  1. 鼠标事件

    鼠标事件一般包括鼠标右键、双击、拖动、移动鼠标到某个元素上等等。 需要引入ActionChains类

    引入方法:

    1
    from selenium.webdriver.common.action_chains import ActionChains

    ActionChains 常用方法:

    1
    2
    3
    4
    5
    6

    perform() 执行所有ActionChains 中存储的行为;
    context_click() 右击;
    double_click() 双击;
    drag_and_drop() 拖动;
    move_to_element() 鼠标悬停。

    鼠标双击示例:

    1
    2
    3
    4
    #定位到要双击的元素
    qqq =driver.find_element_by_xpath("xxx")
    #对定位到的元素执行鼠标双击操作
    ActionChains(driver).double_click(qqq).perform()

    鼠标拖放示例:

    1
    2
    3
    4
    5
    6
    #定位元素的原位置 
    element = driver.find_element_by_name("source")
    #定位元素要移动到的目标位置
    target = driver.find_element_by_name("target")
    #执行元素的移动操作
    ActionChains(driver).drag_and_drop(element, target).perform()
  1. 特殊定位

    1. iframe定位

      1
      2
      #先找到到 ifrome1(id = f1)
      browser.switch_to_frame("f1")
    2. 内嵌窗口定位:

      1
      browser.switch_to_window("f1")

附加内容

  1. Python Webdriver Exception速查表

    webdriver在使用过程中可能会出现各种异常,我们需要了解该异常并知道如何进行异常处理。

    异常 描述
    WebDriverException 所有webdriver异常的基类,当有异常且不属于下列异常时抛出
    InvalidSwitchToTargetException 下面两个异常的父类,当要switch的目标不存在时抛出
    NoSuchFrameException 当你想要用switch_to.frame()切入某个不存在的frame时抛出
    NoSuchWindowException 当你想要用switch_to.window()切入某个不存在的window时抛出
    NoSuchElementException 元素不存在,一般由find_element与find_elements抛出
    NoSuchAttributeException 一般你获取不存在的元素属性时抛出,要注意有些属性在不同浏览器里是有不同的属性名的
    StaleElementReferenceException 指定的元素过时了,不在现在的DOM树里了,可能是被删除了或者是页面或iframe刷新了
    UnexpectedAlertPresentException 出现了意料之外的alert,阻碍了指令的执行时抛出
    NoAlertPresentException 你想要获取alert,但实际没有alert出现时抛出
    InvalidElementStateException 下面两个异常的父类,当元素状态不能进行想要的操作时抛出
    ElementNotVisibleException 元素存在,但是不可见,不可以与之交互
    ElementNotSelectableException 当你想要选择一个不可被选择的元素时抛出
    InvalidSelectorException 一般当你xpath语法错误的时候抛出这个错
    InvalidCookieDomainException 当你想要在非当前url的域里添加cookie时抛出
    UnableToSetCookieException 当driver无法添加一个cookie时抛出
    TimeoutException 当一个指令在足够的时间内没有完成时抛出
    MoveTargetOutOfBoundsException actions的move操作时抛出,将目标移动出了window之外
    UnexpectedTagNameException 获取到的元素标签不符合要求时抛出,比如实例化Select,你传入了非select标签的元素时
    ImeNotAvailableException 输入法不支持的时候抛出,这里两个异常不常见,ime引擎据说是仅用于linux下对中文/日文支持的时候
    ImeActivationFailedException 激活输入法失败时抛出
    ErrorInResponseException 不常见,server端出错时可能会抛
    RemoteDriverServerException 不常见,好像是在某些情况下驱动启动浏览器失败的时候会报这个错

  2. Xpath&Css定位方法速查表

    描述 Xpath Css
    直接子元素 //div/a div > a
    子元素或后代元素 //div//a div a
    以id定位 //div[@id=’idValue’]//a div#idValue a
    以class定位 //div[@class=’classValue’]//a div.classValue a
    同级弟弟元素 //ul/li[@class=’first’]/following- ul>li.first + li
    属性 //form/input[@name=’username’] form input[name=’username’]
    多个属性 //input[@name=’continue’ and input[name=’continue’][type=’button
    第4个子元素 //ul[@id=’list’]/li[4] ul#list li:nth-child(4)
    第1个子元素 //ul[@id=’list’]/li[1] ul#list li:first-child
    最后1个子元素 //ul[@id=’list’]/li[last()] ul#list li:last-child
    属性包含某字段 //div[contains(@title,’Title’)] div[title*=”Title”]
    属性以某字段开头 //input[starts-with(@name,’user’)] input[name^=”user”]
    属性以某字段结尾 //input[ends-with(@name,’name’)] input[name$=”name”]
    text中包含某字段 //div[contains(text(), ‘text’)] 无法定位
    元素有某属性 //div[@title] div[title]
    父节点 //div/.. 无法定位
    同级哥哥节点 //li/preceding-sibling::div[1] 无法定位

​

​

​

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

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

Python爬虫框架之PyQuery的使用

发表于 2021-12-02

前言

Python之所以很适合写爬虫, 其中一个原因是拥有丰富的解析器Lib

以HTML解析为例就有XPATH,Beautiful Soup和PyQuery等等

想用哪个用哪个

那么今天我们就来介绍其中PyQuery这个解析器的用法, PyQuery的语法和jquery大同小异, 如果你熟悉jquery的使用, 那么这款解析器绝对适合你

组件安装

1
pip install pyquery

组件引入

1
from pyquery import PyQuery as pq

三个小示例

假设我们有这么一个HTML文本:

1
2
3
4
5
6
7
8
<div id="wrap">
<ul class="s_from">
我是测试文本
<link href="http://aaa.com">aaa</link>
<link href="http://bbb.com">bbb</link>
<link href="http://ccc.com">ccc</link>
</ul>
</div>

如果我们要获取div标签下的所有内容(包含div标签), 那么我们可以这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pyquery import PyQuery as pq
html = '''
<div id="wrap">
<ul class="s_from">
我是测试文本
<link href="http://aaa.com">aaa</link>
<link href="http://bbb.com">bbb</link>
<link href="http://ccc.com">ccc</link>
</ul>
</div>
'''
doc = pq(html)
result=doc("#wrap")
print(result)

得到的结果为:

1
2
3
4
5
6
7
8
<div id="wrap">
<ul class="s_from">
我是测试文本
<link href="http://aaa.com">aaa</link>
<link href="http://bbb.com">bbb</link>
<link href="http://ccc.com">ccc</link>
</ul>
</div>

如果我们要获取div标签下的所有元素(不包含div标签),, 那么我们可以使用children()函数, 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pyquery import PyQuery as pq
html = '''
<div id="wrap">
<ul class="s_from">
我是测试文本
<link href="http://aaa.com">aaa</link>
<link href="http://bbb.com">bbb</link>
<link href="http://ccc.com">ccc</link>
</ul>
</div>
'''
doc = pq(html)
result=doc("#wrap").children()
print(result)

那么得到的结果为:

1
2
3
4
5
6
<ul class="s_from">
我是测试文本
<link href="http://aaa.com">aaa</link>
<link href="http://bbb.com">bbb</link>
<link href="http://ccc.com">ccc</link>
</ul>

如果我们要获取ul标签下的所有内容, 我们可以这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pyquery import PyQuery as pq
html = '''
<div id="wrap">
<ul class="s_from">
我是测试文本
<link href="http://aaa.com">aaa</link>
<link href="http://bbb.com">bbb</link>
<link href="http://ccc.com">ccc</link>
</ul>
</div>
'''
doc = pq(html)
result=doc("ul").html()
print(result)

那么得到的结果为:

1
2
3
4
我是测试文本
<link href="http://aaa.com">aaa</link>
<link href="http://bbb.com">bbb</link>
<link href="http://ccc.com">ccc</link>

通过上面三个小例子示范我们大致感受了一下PyQuery的使用, 但是依然无法深入了解, 接下来我们对其用法进行总结

使用总结

  1. 通过id获取html使用#

    1
    pq(html)("#xxx")
  2. 通过class获取html使用’.`

    1
    pq(html)(".xxx")
  3. 通过标签名获取html直接使用标签

    1
    pq(html)("div")
  4. 查找父元素使用parent()

    1
    pq(html)("#xxx").parent()
  5. 获取目标位置下包裹的所有的元素

    1
    pq(html)("#xxx").children()
  6. 获取目标位置下包裹的所有的html内容

    1
    pq(html)("#xxx").html()
  7. 获取目标位置下包裹的所有的文本内容

    1
    pq(html)("#xxx").text()

    注意: 我们要和html()与children()进行区分, 我们用一个例子来解释:

    如果使用html():

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # coding:utf-8

    from pyquery import PyQuery as pq
    html = '''
    <div id="wrap">
    <ul class="s_from">
    我是测试文本
    <link href="http://aaa.com">aaa</link>
    <link href="http://bbb.com">bbb</link>
    <link href="http://ccc.com">ccc</link>
    </ul>
    </div>
    <link href="http://ddd.com">ccc</link>
    </ul>
    '''
    doc = pq(html)
    result=doc("#wrap").html()
    print(result)

    得到的结果为:

    1
    2
    3
    4
    我是测试文本
    <link href="http://aaa.com"/><p>aaa</p>
    <link href="http://bbb.com"/>bbb
    <link href="http://ccc.com"/>ccc

    如果使用children():

    1
    2
    3
    doc = pq(html)
    result=doc(".s_from").children()
    print(result)

    得到结果为:

    1
    2
    3
    <link href="http://aaa.com"/><p>aaa</p>
    <link href="http://bbb.com"/>bbb
    <link href="http://ccc.com"/>ccc

    如果使用text():

    1
    2
    3
    doc = pq(html)
    result=doc(".s_from").text()
    print(result)

    得到结果为:

    1
    2
    3
    4
    我是测试文本
    aaa
    bbb
    ccc

    一目了然

  8. 查找兄弟元素使用siblings()

    1
    pq(html)("#xxx").siblings()
  9. 将所有获取到的元素组成数组items()

    1
    pq(html)("#xxx").items()

    比如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # coding:utf-8

    from pyquery import PyQuery as pq
    html = '''
    <div id="wrap">
    <ul class="s_from">
    我是测试文本
    <link href="http://aaa.com">aaa</link>
    <link href="http://bbb.com">bbb</link>
    <link href="http://ccc.com">ccc</link>
    </ul>
    </div>
    <link href="http://ddd.com">ccc</link>
    </ul>
    '''
    doc = pq(html)
    result=doc("link")
    print(result)

    那么得到的结果为:

    1
    2
    3
    4
    <link href="http://aaa.com"/>aaa
    <link href="http://bbb.com"/>bbb
    <link href="http://ccc.com"/>ccc
    <link href="http://ddd.com"/>ccc

    如果我们想对其进行遍历获取其中某一个元素, 那么可以这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # coding:utf-8

    from pyquery import PyQuery as pq
    html = '''
    <div id="wrap">
    <ul class="s_from">
    我是测试文本
    <link href="http://aaa.com">aaa</link>
    <link href="http://bbb.com">bbb</link>
    <link href="http://ccc.com">ccc</link>
    </ul>
    </div>
    <link href="http://ddd.com">ccc</link>
    </ul>
    '''
    doc = pq(html)
    result=doc("link").items()
    for i in result:
    print(i)
  10. 获取标签属性信息使用attr()

    还是上面的例子, 如果我们要获取link标签中href的值, 那么可以这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    # coding:utf-8

    from pyquery import PyQuery as pq
    html = '''
    <div id="wrap">
    <ul class="s_from">
    我是测试文本
    <link href="http://aaa.com">aaa</link>
    <link href="http://bbb.com">bbb</link>
    <link href="http://ccc.com">ccc</link>
    </ul>
    </div>
    <link href="http://ddd.com">ccc</link>
    </ul>
    '''
    doc = pq(html)
    result=doc("link").items()
    for i in result:
    print(i.attr('href'))
    #或者
    print(i.attr.href)
    # 上面两种获取href的方法任选其一
  11. 精确查找使用空格

    啥意思呢, 我们还是用一个例子来说明:

    如果我们要利用层级关系精确查找, 那么可以这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # coding:utf-8

    from pyquery import PyQuery as pq
    html = '''
    <div id="wrap">
    <ul class="s_from">
    我是测试文本
    <link id="first" "href="http://aaa.com">111<p>aaa</p></link>
    <link href="http://bbb.com">bbb</link>
    <link href="http://ccc.com">ccc</link>
    </ul>
    </div>
    <link href="http://ddd.com">ccc</link>
    </ul>
    '''
    doc = pq(html)
    result=doc("#wrap .s_from #first")
    print(result)

    层级之间使用空格进行分隔, 得到的结果为:

    1
    <link id="first"/>111

    我们惊奇地发现, 查找到的内容有缺失,居然没有打印<p>aaa</p>, 如果我们将link标签改为a标签:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # coding:utf-8

    from pyquery import PyQuery as pq
    html = '''
    <div id="wrap">
    <ul class="s_from">
    我是测试文本
    <a id="first" "href="http://aaa.com">111<p>aaa</p></a>
    <link href="http://bbb.com">bbb</link>
    <link href="http://ccc.com">ccc</link>
    </ul>
    </div>
    <link href="http://ddd.com">ccc</link>
    </ul>
    '''
    doc = pq(html)
    result=doc("#wrap .s_from #first")
    print(result)

    则结果为:

    1
    <a id="first">111<p>aaa</p></a>

    你可能会说之前写的语法有问题 link标签怎么能又嵌套其他标签呢, 事实上, 你也难保会碰上诸如此类的情况, 毕竟前端鱼龙混杂, 当我们获取不到值的时候, 需要特殊注意一下

  1. 根据标签属性精确查找

    比如 我们要查找itemprop属性值为keywords的meta标签, 可以这样写:

    1
    2
    doc = pq(html)
    doc('meta[itemprop="keywords"]')

    如果需要嵌套查找 比如查找itemprop属性值为author的div标签下的itemprop属性值为name的meta标签 可以这样写:

    1
    2
    doc = pq(html)
    d('div[itemprop="author"]')('meta[itemprop="name"]')

    更多层级的嵌套也是类的写法

  2. 给元素添加class

    1
    pq(html)("#xxx").addClass('active')

    ​ 如果class已经存在, 则不重复添加

  3. 移除元素的class

    1
    pq(html)("#xxx").removeClass('active')
  4. 给元素添加css样式

    1
    pq(html)("#xxx").css('font-size','14px')
  5. 移除某个标签

    1
    pq(html)("#xxx").remove('ul')
  6. 伪类选择器

    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
    from pyquery import PyQuery as pq
    html = '''
    <div href="wrap">
    hello nihao
    <ul class="s_from">
    asdasd
    <link class='active1 a123' href="http://asda.com"><a>helloasdadasdad12312</a></link>
    <link class='active2' href="http://asda1.com">asdadasdad12312</link>
    <link class='movie1' href="http://asda2.com">asdadasdad12312</link>
    </ul>
    </div>
    '''

    doc = pq(html)
    its=doc("link:first-child")
    print('第一个标签:%s'%its)
    its=doc("link:last-child")
    print('最后一个标签:%s'%its)
    its=doc("link:nth-child(2)")
    print('第二个标签:%s'%its)
    its=doc("link:gt(0)") #从零开始
    print("获取0以后的标签:%s"%its)
    its=doc("link:nth-child(2n-1)")
    print("获取奇数标签:%s"%its)
    its=doc("link:contains('hello')")
    print("获取文本包含hello的标签:%s"%its)
  7. 多选查找, 用逗号分隔

    1
    pq(html)("h1,h2") #表示查找h1和h2标签
  8. 过滤查找filter

    1
    pq(html).filter(".fisrt") #过滤出class为.fisrt的内容
  9. 使用find方法查找

    上面我们介绍的查找都是pq(html)("xxx") 列表形式, 除此之外我们还可以用使用调用函数的形式进行查找, 效果也是一样的:

    1
    2
    3
    pq(html)("#xxx") 
    #或者用
    pq(html).find("#xxx")

最后

以上只是该库的一部分使用方法, 一边用一边掌握, 我个人还是比较喜欢使用这一套解析库, 能解决大部分的应用场景

​

​

​

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

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

Android原生格斗游戏开发

发表于 2021-12-01

前言

昨天晚上做了个梦, 梦见我在沙…

梦里的事已经记不得了, 不过大半夜醒来后大脑异常清醒活跃, 居然在构思着一款格斗游戏

也不知道这灵光从何而来, 近大半年都没有玩游戏, 也没有做游戏相关的开发

不过在我内心深处 确实是有一个3A游戏梦, 话说格斗游戏, 算是我童年最爱吧

不管怎么着, 反正当时是越想越起劲, 心跳加速, 鼻子发痒, 差点误以为流了鼻血

既然这么刺激, 那么 就将想法变成现实吧, 开始着手进行游戏的开发, 这次平台我选择用Android原生, 为什么不直接使用第三方引擎, 主要还是想着把基础的东西捋一遍, 地基打好了, 上层建筑也就没什么难的

游戏架构设计

无论游戏还是普通应用, 都是由两个大部分组成的, 一个是场景界面, 另一个则是事件处理

我们只需要从这两个方面着手即可

场景界面

这款游戏的场景很简单, 只有一个场景, 和拳皇类似, 一个背景, 左右各一人, 就这么简单

事件处理

移动端的游戏, 我们肯定是需要在屏幕上加上触控的游戏摇杆, 来操作角色的行动

说到动作, 所有的角色都具备左右上下跑跳滑铲的动作, 因此这部分我们在代码实现的时候, 可以将其进行抽象到父类中, 让所有子类角色与生俱来

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

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

使用python对博客网站的文章进行爬取

发表于 2021-12-01

前言

说到爬取文章啥的, 最好使的肯定是python, python中有很多爬虫库可供我们使用, 方便快捷, 虽然工具很多, 但是大同小异, 我们只需要用好一个库就够了

接下来以掘金为例, 给大家演示一下如何爬取网站中的文章:

网站结构分析

调出浏览器控制台, 通过分析, 我们发现掘金和简书不同, 其网站中的文章链接全部都是通过接口动态请求的, 而非以Nginx容器静态存放

由于我们需要获取多篇文章,而不是单篇, 所以文章链接我们必须先拿到手, 然后再根据链接挨个将文章爬出来

文章链接获取

在推荐一栏通过上拉加载我们很轻松就能获取到请求的接口和参数, 我们只需要将其拷贝出来用python模拟请求即可

image-20211201163303973

请求接口:

1
https://api.juejin.cn/recommend_api/v1/article/recommend_cate_feed?aid=xxx&uuid=xxx

请求参数:

1
{"id_type":2,"sort_type":200,"cate_id":"6809637769959178254","cursor":"1","limit":20}

其中cursor字段表示页数, 我们可以循环递增这个字段的值来源源不断地获取数据

响应数据:

image-20211201163627506

这个article_id就是我们需要获取的值, 将这个值和https://juejin.cn/post/进行拼接就得到了文章的实际地址, 如下:

1
https://juejin.cn/post/7016520448204603423

好了, 分析完毕后, 直接上代码实现:

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
# coding:utf-8


import codecs
import time
import requests
import json
import sys
# 增加try except嵌套层数 避免
sys.setrecursionlimit(10000)



cache_file_name = 'temp_juejin.txt'

cache = []


def loadCache():
with codecs.open(cache_file_name, "r", "utf-8") as fr:
for line in fr:
cache.append(line)
#print(cache)
#return cache[len(cache)-1]


def startScrape():

apiUrl='https://api.juejin.cn/recommend_api/v1/article/recommend_cate_feed?aid=2608&uuid=7023196943133656589'
HEADERS = {
'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:11.0) Gecko/20100101 Firefox/11.0',

'Accept-Encoding' : 'gzip,deflate,sdch',
'Accept-Language' : 'zh-CN,zh;q=0.8',
'Content-type': 'application/json; charset=UTF-8',
'accept': 'application/json, text/plain, */*',

}
for index in range(1000):
body = {"id_type":2,"sort_type":200,"cate_id":"6809637769959178254","cursor":"1","limit":20}
body["cursor"]=str(index+1)
print(body)
r = requests.post(url=apiUrl, headers=HEADERS,data=json.dumps(body))
print(r.status_code)

res=json.loads(r.content)

with codecs.open(cache_file_name, "a", "utf-8") as f:
for item in res["data"]:
print()
id=item["article_info"]["article_id"]
link = "https://juejin.cn/post/"+id
print(link)
#if link not in cache: #判断存在或者不存在
if not any(link in s for s in cache):
cache.append(link)
f.write(link+"\n")
print("新增一条连接")
#time.sleep(10)
#切记 url不要加入换行 否则404
f.close()
time.sleep(2)




def job():

loadCache()
startScrape()




if __name__ == '__main__':
job()

执行该代码前先在同级目录下新建一个temp_juejin.txt文件, 用于存放获取到的所有文章链接, 对于初学者, 这里需要注意的是json的转换处理和请求头的设置, 如果没有使用json.dumps进行转换, 那么请求会失败, 如果请求头不加Content-type和accept或者没填对, 请求正常但是返回的不是正常的数据, 这一块是很多人极易忽视的地方

代码运行后爬取的结果如下:

image-20211201164332262

好了, 有了文章链接, 下一步我们就开始挨个文章的爬取

文章爬取

爬虫框架, 我这里使用的是PyQuery, 关于PyQuery的用法, 可参见《Python爬虫框架之PyQuery的使用》

接下来我们爬取文章的标题和内容, 代码如下:

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
# -*- coding:utf-8 -*-

import requests
from pyquery import PyQuery as pq
import codecs
import os
import sys





sys.setrecursionlimit(1000000)

# 当前文件路径
current_path = os.path.abspath(__file__)
# 父目录
father_path = os.path.abspath(os.path.dirname(current_path) + os.path.sep + ".")



headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36',
'cookie': '__cfduid=d89ead99eeea979ea1f2a1a6243d186461600935008; Hm_lvt_2374bfdfe14a279e4a045267051b54e1=1600935010,1601459114; __yjsv3_shitong=1.0_7_8b1bac638e380ca12f87734ab2405afe2e94_300_1601470572844_223.104.3.46_aaa564dc; cf_chl_1=04a386244ad8d71; cf_chl_prog=x17; cf_clearance=f4af2dbdded649a7cf11a5a52d168289e98e68c6-1601470577-0-1zd4e21871z8a534313z279abd70-150; Hm_lpvt_2374bfdfe14a279e4a045267051b54e1=1601470578',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',

}

session = requests.Session()
session.headers.update(headers)

origin_url_cache_file_name="temp_juejin.txt"

originUrlCache = []

# 将文件中内容按行加载至列表中
def loadCache(filename, filter_text):
cache = []
with codecs.open(filename, "r", "utf-8") as fr:
if filter_text:
for line in fr:
if filter_text in line:
cache.append(line.replace("\n", ""))
else:
for line in fr:
cache.append(line.replace("\n", ""))
return cache



def get_article_by_url(url):
rep = session.get(url)
d=pq(rep.text)
title = d('h1').text()
content = d('.markdown-body').html()
return title, content

def startScrape():
for link in originUrlCache:

print(link + "\n")
title, content = get_article_by_url(link)
print(title + "\n")
print(content)





if __name__ == '__main__':

#将需要爬取的url加载到内存中
originUrlCache=loadCache("{parent}/{filename}".format(parent=father_path,filename=origin_url_cache_file_name), None)
#开始爬取文章
startScrape()

但是打印结果全部为None, 去控台一查发现掘金文章页面内容是通过js动态渲染的, 如果直接获取html是无法通过PyQuery获取到我们想要的内容的, 那这咋办?

想一下, 如果我们能拿到渲染完成后的html, 然后再通过PyQuery进行查找, 不就完事了

问题在于如何获取到渲染完成后的页面源码, 单纯的Get请求肯定是不行的, 我们需要模拟浏览器渲染才行,

这个时候我们就需要用到一个Web自动化框架, 也就是大名鼎鼎的selenium, 它可以模拟真实的浏览器访问和查找甚至是点击操作, 这里我们只需要利用它得到页面源码即可, 关于selenium的详细使用, 可参见《Web自动化框架selenium的介绍与使用》

于是代码修改成如下模样:

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
# -*- coding:utf-8 -*-

import requests
from pyquery import PyQuery as pq
import codecs
import os
import sys

from selenium import webdriver



chrome_options = webdriver.ChromeOptions()
# 使用headless无界面浏览器模式
chrome_options.add_argument('--headless') #增加无界面选项
chrome_options.add_argument('--disable-gpu') #如果不加这个选项,有时定位会出现问题

browser = webdriver.Chrome(chrome_options=chrome_options)




sys.setrecursionlimit(1000000)

# 当前文件路径
current_path = os.path.abspath(__file__)
# 父目录
father_path = os.path.abspath(os.path.dirname(current_path) + os.path.sep + ".")




origin_url_cache_file_name="temp_juejin.txt"

originUrlCache = []

# 将文件中内容按行加载至列表中
def loadCache(filename, filter_text):
cache = []
with codecs.open(filename, "r", "utf-8") as fr:
if filter_text:
for line in fr:
if filter_text in line:
cache.append(line.replace("\n", ""))
else:
for line in fr:
cache.append(line.replace("\n", ""))
return cache



def get_article_by_url(url):
browser.get(url)
d = pq(browser.page_source)
title = d('h1').text()
content = d('.markdown-body').html()
return title, content

def startScrape():
for link in originUrlCache:

print(link + "\n")
title, content = get_article_by_url(link)
print(title + "\n")
print(content)





if __name__ == '__main__':

#将需要爬取的url加载到内存中
originUrlCache=loadCache("{parent}/{filename}".format(parent=father_path,filename=origin_url_cache_file_name), None)
#开始爬取文章
startScrape()

该代码运行的前提是需要安装谷歌浏览器

运行时如果提示This version of ChromeDriver only supports Chrome version, 那么说明浏览器版本和驱动版本不一致, 需要下载与浏览器相匹配的驱动

查看谷歌浏览器版本:

在这里插入图片描述

然后下载驱动:

ChromeDriver下载地址

在这里插入图片描述

将下载的驱动解压到以下目录:

1
2
Win:复制webdriver到Python安装目录下
Mac:复制webdriver到/usr/local/bin目录下

至此, 我们成功爬取到指定文章地址的标题和内容

既然获取到了想要的数据, 那么接下来你可以考虑将其存放到本地, 或者上传到你的wordpress

关于wordpress文章的上传,可参考文章《如何将python采集到的文章保存到wordpress》

文章上传到wordpress

秉着善始善终的原则, 以上面的代码为例给大家补充上上传wordpress后的最终代码:

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
87
88
89
90
91
92
93
94
95
96
97
98
# -*- coding:utf-8 -*-

import time
from lxml import html
import requests
from pyquery import PyQuery as pq
import codecs
import os
import sys
from wordpress_xmlrpc import Client, WordPressPost
from wordpress_xmlrpc.methods.posts import GetPosts,NewPost

from selenium import webdriver
import time


chrome_options = webdriver.ChromeOptions()
# 使用headless无界面浏览器模式
chrome_options.add_argument('--headless') #增加无界面选项
chrome_options.add_argument('--disable-gpu') #如果不加这个选项,有时定位会出现问题

browser = webdriver.Chrome(chrome_options=chrome_options)

sys.setrecursionlimit(1000000)

# 当前文件路径
current_path = os.path.abspath(__file__)
# 父目录
father_path = os.path.abspath(os.path.dirname(current_path) + os.path.sep + ".")

pushed_cache_file_name="temp_juejin_pushed_url.txt"
origin_url_cache_file_name="temp_juejin.txt"




pushedCache = []
originUrlCache = []
wp = Client('http://您的域名/xmlrpc.php', 'wordpress用户名', 'wordpress登录密码')

# 将文件中内容按行加载至列表中
def loadCache(filename, filter_text):
cache = []
with codecs.open(filename, "r", "utf-8") as fr:
if filter_text:
for line in fr:
if filter_text in line:
cache.append(line.replace("\n", ""))
else:
for line in fr:
cache.append(line.replace("\n", ""))
return cache



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))

def get_article_by_url(url):
browser.get(url)
d = pq(browser.page_source)
browser.quit
title = d('h1').text()
content = d('.markdown-body').html()
return title, content

def startScrape():
for link in originUrlCache:
if not any(link in s for s in pushedCache):
print(link + "\n")
title, content = get_article_by_url(link)
print(title + "\n")
print(content)
push_article(title,content)
time.sleep(2)
with codecs.open("{parent}/{filename}".format(parent=father_path,filename=pushed_cache_file_name), 'a', "utf-8") as fw:
fw.write(link + "\n")
fw.close()




if __name__ == '__main__':
#将已经爬取过的url加载到内存中
pushedCache=loadCache("{parent}/{filename}".format(parent=father_path,filename=pushed_cache_file_name), None)
#将需要爬取的url加载到内存中
originUrlCache=loadCache("{parent}/{filename}".format(parent=father_path,filename=origin_url_cache_file_name), None)
#开始爬取文章
startScrape()

只要将域名, 用户名和密码替换成你自己的就行

注意wordpress_xmlrpc库的安装:

1
pip install python-wordpress-xmlrpc

补充

另外 上面获取文章链接环节也可以直接使用selenium进行获取, 虽然不如调接口来的快, 但是碰上接口被加密的情况, 那么selenium的方式能快速解决

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

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

1…202122…51

乱码三千

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

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