jupyter notebook,设置自启动

一、Debian

(base) root@debian:/etc/systemd/system# cat jupyter.service

[Unit]
Description=Jupyter Notebook
After=network.target
[Service]
Type=simple
ExecStart=/root/anaconda3/bin/jupyter-notebook –config=/root/.jupyter/jupyter_notebook_config.py –no-browser

WorkingDirectory=/root/anaconda3/bin/
#文件路径名
Restart=always
RestartSec=10
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=notify
#RuntimeDirectory=sshd
#RuntimeDirectoryMode=0755

 

[Install]
WantedBy=multi-user.target

3、添加权限并设置开机自启chmod +x /etc/jupyter.service

systemctl enable jupyter

systemctl start jupyter.service

检查状态:systemctl status jupyter.service

返回Active:active信息,则成功。

最后我们就可以在/etc/rc.local里,添加开机的自启命令什么的了。记住添加在exit 0之前。

注意:更改自启脚本后,需要重新运行一下命令已使其生效。systemctl enable jupyter

如果有更改服务配置文件test.service,需要执行以下命令

刷新:systemctl daemon-reload

启动:systemctl start jupyter.service

***另启动脚本

###########################自己改的jupyter启动程序 /etc/init.d/jupyter
#!/bin/sh
start()
{
echo “=========================”
echo “Jupyter notebook AutoStart”
echo “=========================”
}

status()
{
echo “jupyter notebook stauts”
systemctl status jupyter.service | grep “Active:”

}
stop()
{
echo “Stopping jupyter notebook”
kill $(ps aux|grep -m 1 ‘jupyter-notebook –allow-root’|awk ‘{ print $2}’)

}

case “$1” in
start)
echo “starting jupyter notebook”
jupyter notebook –allow-root &
;;
stop)
stop
;;
status)
status
;;
restart)
stop
start
;;
*)
echo “Usage: jupyter {start|stop|restart|status}”
;;
esac
exit 0

四、设置自启动

1 update-rc.d jupyter defaults

步骤二(Level 3 启动项后面增加软连接)

1 cd /etc/rc3.d/
2 ln -s ../init.d/jupyter S01jupyter

reboot 重启测试

二、树莓派安装

树莓派安装1> 树莓派原生OS不带pip工具,安装pip管理工具,原生OS上有两个python版本,需指定版本(python3-pip/python2-pip)

 

sudo apgget install python3-pip

2>切换root用户
notes:直接切换会报没权限错误,需先设置root密码,执行下列命令,然后设置密码;

 

sudo passwd root

执行“su 用户名”命令切换用户,后面执行所有的命令都是在Root管理者权限下执行,(在pi下不能实现自启动)

 

su root

安装配置jupyter

1 安装jupyter,国内镜像源下载会更块,-i参数指定 https://pypi.douban.com/simple/, 其中pyzmq-22.0.3-cp37-cp37m-linux_armv7l.whl包下载容易报错,建议电脑本地安装

 

pip3 install -i https://pypi.douban.com/simple/ jupyter

2配置jupyter
安装完成后,执行下列命令

 

  jupyter notebook --generate-config

此时在/root/下会生成一个/.jupyter文件夹

 

root@raspberrypi:~# ls -al
total 56
drwx------  6 root root  4096 Mar  8 07:17 .
drwxr-xr-x 18 root root  4096 Jan 11 05:15 ..
-rw-------  1 root root  3288 Mar  8 07:18 .bash_history
-rw-r--r--  1 root root   570 Dec  9 14:40 .bashrc
drwx------  3 root root  4096 Mar  8 06:14 .cache
drwx------  2 root root  4096 Mar  8 07:14 .jupyter
drwxr-xr-x  3 root root  4096 Mar  8 06:22 .local
-rw-r--r--  1 root root   148 Dec  9 14:40 .profile
-rw-------  1 root root    49 Mar  8 06:29 .python_history
-rw-------  1 root root 13803 Mar  8 07:17 .viminfo
drwx------  3 root root  4096 Mar  8 01:20 .vnc
root@raspberrypi:~# cd .jupyter/
root@raspberrypi:~/.jupyter# ls -al

终端输入,

 

jupyter notebook password

提示输入密码,此处会生成密钥保存json文件中,此处后面会用到

 

root@raspberrypi:~/.jupyter# ls -al
total 60
drwx------ 2 root root  4096 Mar  8 07:14 .
drwx------ 6 root root  4096 Mar  8 07:17 ..
-rw------- 1 root root   129 Mar  8 06:50 jupyter_notebook_config.json
-rw-r--r-- 1 root root 48533 Mar  8 07:14 jupyter_notebook_config.py

打开/.jupyter 文件后编辑“jupyter_notebook_config.py”

 

c.NotebookApp.ip='*'                                              //‘*’表示局域网内任意IP都可以访问,
c.NotebookApp.allow_remote_access=True         //表示接受远程连接
c.NotebookApp.password=u'argon2:$argon2id$v=19$m=10240,t=10,p=8$QImcaSHkIZuOzmZwNgduTQ$ZSHvDSq4OZNX8ZonXgnbuA'      //保存在Json文件中的密钥
c.NotebookApp.open_browser=False                   //默认不打开浏览器
c.NotebookApp.port=48888                                  //默认端口
c.NotebookApp.notebook_dir='/home/pi/'             //默认工作目录

设置自启动

此处有多种方法,
方法1>编辑/etc.rc.local 文件,在exit 0 前加入 “jupyter notebook –allow-root”

 

#!/bin/sh -e
# rc.local
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
# In order to enable or disable this script just change the execution
# bits.
# By default this script does nothing.
# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi
jupyter notebook --allow-root
exit 0

方法二
在/etc/init.d/文件夹下增加执行文件jupyter.init

 

#!/bin/bash
case "$1" in
     start)
         echo "starting jupyter notebook"
         jupyter notebook --allow-root &
         ;;
     stop)
        echo "stopping jupyter notebook"
        kill $(ps aux|grep -m 1 'jupyter-notebook --allow-root'|awk '{ print $2}')
        ;;
     *)
        echo "Usage: service jupyter notebook start|stop"
        exit 1
        ;;
esac
exit 0

添加执行权限

chmod +x /etc/init.d/jupyter.init

重启设备

#运行jupyter.init 文件
sudo service jupyter.init start
#终止jupyter.init 文件
sudo service jupyter.init stop

设置开机启动

sudo update-rc.d jupyter.init defaults

设置好后重启设备

三、WINDOWS脚本启动 jupyter notebok

在桌面新建文本文件 “jupyter.bat” (以bat结尾就行),输入以下代码,倒数第二行的D:\Jupyter_workspace修改为你想要作为根目录的路径

%隐藏cmd窗口%
@echo off
if “%1″==”h” goto begin
start mshta vbscript:createobject(“wscript.shell”).run(“””%~nx0″” h”,0)(window.close)&&exit
:begin
cd /d D:\Jupyter_workspace
jupyter notebook
双击该文件即可启动jupyter notebok,并且不会弹出命令行
————————————————

脚本关闭 jupyter notebok
新建文本文件 “Kill Jupyter.bat” (以bat结尾就行),输入以下代码:

%隐藏cmd窗口%
@echo off
if “%1″==”h” goto begin
start mshta vbscript:createobject(“wscript.shell”).run(“””%~nx0″” h”,0)(window.close)&&exit
:begin
taskkill /f /im jupyter-notebook.exe
双击该文件即可关闭 jupyter notebok
————————————————

见过的最全的网络爬虫干货总结!

·  阅读 41156

这可能是你见过的最全的网络爬虫干货总结!

昨天的时候我参加了掘金组织的一场 Python 网络爬虫主题的分享活动,主要以直播的形式分享了我从事网络爬虫相关研究以来的一些经验总结,整个直播从昨天下午 1 点一直持续到下午 5 点,整整四个小时。

整个分享分为三个阶段,第一阶段先介绍了自己从大学以来从事编程开发以来的相关历程,第二阶段是正式的网络爬虫分享流程,详细总结了网络爬虫开发的一些要点,第三阶段是解答一些提问,并抽奖送出一些礼品。所以在这里我会对我昨天分享的主要内容做下总结,另外还会附上视频回放、PPT,另外还会为大家送上一些福利,希望大家可以支持!

总括

整个分享的主题叫做《健壮高效的网络爬虫》,本次分享从抓取、解析、存储、反爬、加速五个方面介绍了利用 Python 进行网络爬虫开发的相关知识点和技巧,介绍了不同场景下如何采取不同措施高效地进行数据抓取的方法,包括 Web 抓取、App 抓取、数据存储、代理选购、验证码破解、分布式抓取及管理、智能解析等多方面的内容,另外还结合了不同场景介绍了常用的一些工具包,全部内容是我在从事网络爬虫研究过程以来的经验精华总结。

爬取

对于爬取来说,我们需要学会使用不同的方法来应对不同情景下的数据抓取任务。

爬取的目标绝大多数情况下要么是网页,要么是 App,所以这里就分为这两个大类别来进行了介绍。

对于网页来说,我又将其划分为了两种类别,即服务端渲染和客户端渲染,对于 App 来说,我又针对接口的形式进行了四种类别的划分——普通接口、加密参数接口、加密内容接口、非常规协议接口。

所以整个大纲是这样子的:

  • 网页爬取
    • 服务端渲染
    • 客户端渲染
  • App 爬取
    • 普通接口
    • 加密参数接口
    • 加密内容接口
    • 非常规协议接口

爬取 / 网页爬取

服务端渲染的意思就是页面的结果是由服务器渲染后返回的,有效信息包含在请求的 HTML 页面里面,比如猫眼电影这个站点。客户端渲染的意思就是页面的主要内容由 JavaScript 渲染而成,真实的数据是通过 Ajax 接口等形式获取的,比如淘宝、微博手机版等等站点。

服务端渲染的情况就比较简单了,用一些基本的 HTTP 请求库就可以实现爬取,如 urllib、urllib3、pycurl、hyper、requests、grab 等框架,其中应用最多的可能就是 requests 了。

对于客户端渲染,这里我又划分了四个处理方法:

  • 寻找 Ajax 接口,此种情形可以直接使用 Chrome/Firefox 的开发者工具直接查看 Ajax 具体的请求方式、参数等内容,然后用 HTTP 请求库模拟即可,另外还可以通过设置代理抓包来查看接口,如 Fiddler/Charles。
  • 模拟浏览器执行,此种情形适用于网页接口和逻辑较为复杂的情况,可以直接以可见即可爬的方式进行爬取,如可以使用 Selenium、Splinter、Spynner、pyppeteer、PhantomJS、Splash、requests-html 等来实现。
  • 直接提取 JavaScript 数据,此种情形适用于真实数据没有经过 Ajax 接口获取,而是直接包含在 HTML 结果的某个变量中,直接使用正则表达式将其提取即可。
  • 模拟执行 JavaScript,某些情况下直接模拟浏览器执行效率会偏低,如果我们把 JavaScript 的某些执行和加密逻辑摸清楚了,可以直接执行相关的 JavaScript 来完成逻辑处理和接口请求,比如使用 Selenium、PyExecJS、PyV8、js2py 等库来完成即可。

爬取 / App 爬取

对于 App 的爬取,这里分了四个处理情况:

  • 对于普通无加密接口,这种直接抓包拿到接口的具体请求形式就好了,可用的抓包工具有 Charles、Fiddler、mitmproxy。
  • 对于加密参数的接口,一种方法可以实时处理,例如 Fiddler、mitmdump、Xposed 等,另一种方法是将加密逻辑破解,直接模拟构造即可,可能需要一些反编译的技巧。
  • 对于加密内容的接口,即接口返回结果完全看不懂是什么东西,可以使用可见即可爬的工具 Appium,也可以使用 Xposed 来 hook 获取渲染结果,也可以通过反编译和改写手机底层来实现破解。
  • 对于非常规协议,可以使用 Wireshark 来抓取所有协议的包,或者使用 Tcpdump 来进行 TCP 数据包截获。

以上便是爬取流程的相关分类和对应的处理方法。

解析

对于解析来说,对于 HTML 类型的页面来说,常用的解析方法其实无非那么几种,正则、XPath、CSS Selector,另外对于某些接口,常见的可能就是 JSON、XML 类型,使用对应的库进行处理即可。

这些规则和解析方法其实写起来是很繁琐的,如果我们要爬上万个网站,如果每个网站都去写对应的规则,那么不就太累了吗?所以智能解析便是一个需求。

智能解析意思就是说,如果能提供一个页面,算法可以自动来提取页面的标题、正文、日期等内容,同时把无用的信息给刨除,例如上图,这是 Safari 中自带的阅读模式自动解析的结果。

对于智能解析,下面分为四个方法进行了划分:

  • readability 算法,这个算法定义了不同区块的不同标注集合,通过权重计算来得到最可能的区块位置。
  • 疏密度判断,计算单位个数区块内的平均文本内容长度,根据疏密程度来大致区分。
  • Scrapyly 自学习,是 Scrapy 开发的组件,指定⻚页⾯面和提取结果样例例,其可⾃自学习提取规则,提取其他同类⻚页⾯面。
  • 深度学习,使⽤用深度学习来对解析位置进⾏行行有监督学习,需要⼤大量量标注数据。

如果能够容忍一定的错误率,可以使用智能解析来大大节省时间。

目前这部分内容我也还在探索中,准确率有待继续提高。

存储

存储,即选用合适的存储媒介来存储爬取到的结果,这里还是分为四种存储方式来进行介绍。

  • 文件,如 JSON、CSV、TXT、图⽚、视频、⾳频等,常用的一些库有 csv、xlwt、json、pandas、pickle、python-docx 等。
  • 数据库,分为关系型数据库、非关系型数据库,如 MySQL、MongoDB、HBase 等,常用的库有 pymysql、pymssql、redis-py、pymongo、py2neo、thrift。
  • 搜索引擎,如 Solr、ElasticSearch 等,便于检索和实现⽂本匹配,常用的库有 elasticsearch、pysolr 等。
  • 云存储,某些媒体文件可以存到如七⽜牛云、又拍云、阿里云、腾讯云、Amazon S3 等,常用的库有 qiniu、upyun、boto、azure-storage、google-cloud-storage 等。

这部分的关键在于和实际业务相结合,看看选用哪种方式更可以应对业务需求。

反爬

反爬这部分是个重点,爬虫现在已经越来越难了,非常多的网站已经添加了各种反爬措施,在这里可以分为非浏览器检测、封 IP、验证码、封账号、字体反爬等。

下面主要从封 IP、验证码、封账号三个方面来阐述反爬的处理手段。

反爬 / 封 IP

对于封 IP 的情况,可以分为几种情况来处理:

  • 首先寻找手机站点、App 站点,如果存在此类站点,反爬会相对较弱。
  • 使用代理,如抓取免费代理、购买付费代理、使用 Tor 代理、Socks 代理等。
  • 在代理的基础上维护自己的代理池,防止代理浪费,保证实时可用。
  • 搭建 ADSL 拨号代理,稳定高效。

反爬 / 验证码

验证码分为非常多种,如普通图形验证码、算术题验证码、滑动验证码、点触验证码、手机验证码、扫二维码等。

  • 对于普通图形验证码,如果非常规整且没有变形或干扰,可以使用 OCR 识别,也可以使用机器学习、深度学习来进行模型训练,当然打码平台是最方便的方式。
  • 对于算术题验证码,推荐直接使用打码平台。
  • 对于滑动验证码,可以使用破解算法,也可以模拟滑动。后者的关键在于缺口的找寻,可以使用图片比对,也可以写基本的图形识别算法,也可以对接打码平台,也可以使用深度学习训练识别接口。
  • 对于点触验证码,推荐使用打码平台。
  • 对于手机验证码,可以使用验证码分发平台,也可以购买专门的收码设备,也可以人工验证。
  • 对于扫二维码,可以人工扫码,也可以对接打码平台。

反爬 / 封账号

某些网站需要登录才能爬取,但是一个账号登录之后请求过于频繁会被封号,为了避免封号,可以采取如下措施:

  • 寻找手机站点或 App 站点,此种类别通常是接口形式,校验较弱。
  • 寻找无登录接口,尽可能寻找⽆无需登录即可爬取的接口。
  • 维护 Cookies 池,使⽤用批量账号模拟登录,使⽤时随机挑选可用 Cookies 使⽤即可,实现:https://github.com/Python3WebSpider/CookiesPool。

加速

当爬取的数据量非常大时,如何高效快速地进行数据抓取是关键。

常见的措施有多线程、多进程、异步、分布式、细节优化等。

加速 / 多线程、多进程

爬虫是网络请求密集型任务,所以使用多进程和多线程可以大大提高抓取效率,如使用 threading、multiprocessing 等。

加速 / 异步

将爬取过程改成非阻塞形式,当有响应式再进行处理,否则在等待时间内可以运行其他任务,如使用 asyncio、aiohttp、Tornado、Twisted、gevent、grequests、pyppeteer、pyspider、Scrapy 等。

加速 / 分布式

分布式的关键在于共享爬取队列,可以使用 celery、huey、rq、rabbitmq、kafka 等来实现任务队列的对接,也可以使用现成的框架 pyspider、Scrapy-Redis、Scrapy-Cluster 等。

加速 / 优化

可以采取某些优化措施来实现爬取的加速,如:

  • DNS 缓存
  • 使用更快的解析方法
  • 使用更高效的去重方法
  • 模块分离化管控

加速 / 架构

如果搭建了分布式,要实现高效的爬取和管理调度、监控等操作,我们可以使用两种架构来维护我们的爬虫项目。

  • 将 Scrapy 项目打包为 Docker 镜像,使用 K8S 控制调度过程。
  • 将 Scrapy 项目部署到 Scrapyd,使用专用的管理工具如 SpiderKeeper、Gerapy 等管理。

以上便是我分享的全部内容,所有的内容几乎都展开说了,一共讲了一个半小时。

上面的文字版的总结可能比较简略,非常建议大家如有时间的话观看原版视频分享,里面还能看到我本人的真面目哦,现在已经上传到了 Bilibili,链接为:www.bilibili.com/video/av343…,欢迎大家观看学习和收藏~

另外对于这部分内容,其实还有我制作的更丰富的思维导图,预览图如下:

点击图片,获取爬虫思维导图高清图片

另外还有原演讲稿我也一并分享给大家,都放在我的公众号了。

获取方式如下:

  • 回复”爬虫讲稿“,获取本次分享的 PPT 内容。

暗网系列之:利用Python + OnionScan 打造自己的安全威胁情报平台(一)

2017-08-02 16:40

 

MottoIN暗网系列专题的目标,是让大家更加全面、更深入的了解暗网,这当中自然涉及安全威胁情报分析平台的话题。

OnionScan 是一个用来在暗网中寻找潜在的泄露数据的利器,最新版本中还加入了一些炫酷的可视化效果,尽管项目的管理团队并没有公布实现深度扫描的技术细节,也没有说明那些看起来非常酷的可视化效果是如何生成的。

不过,没关系,接下来,就让我们一起尝试使用 Python + OnionScan完成安全威胁情报平台的搭建,探讨如何在暗网中进行深度探索、寻找感兴趣的信息、分析有用的情报,顺便也提高一下数据可视化的技能。

通常让我们感到恐怖的,不是看不到的东西,而是看到了却不明白的东西”,深入暗网深处,看看能找到那些可怕的/宝贵的信息。

第一部分(Part  1)

流程简介

初始工作的简单流程,如下所述:

  1. 拥有一台可以7*24小时运行的服务器,扫描工作需要花费大量的时间(自己有服务器的话最好,练手的话也可以使用云服务器);
  2. 在服务器上运行Tor 软件;
  3. 安装 OnionScan;
  4. 编写Python脚本,处理扫描工作,并将扫描结果进行数据管理;
  5. Python进阶,优化数据分析结果的可视化展示效果

搭建合适的服务器及运行环境

第一步,创建服务器环境。推荐使用Ubuntu16.4(下文中也将以此作为演示环境)。根据自己的主机环境,选择合适的连接到服务器的方式。

  • windows系统:Putty;
  • Mac OS X或Linux系统:直接使用ssh命令(sshroot@IPADDRESS)

第二步,配置服务器的环境。连接到Ubuntu服务器上,运行如下命令:

apt-get update

apt-get install tor git bison libexif-dev

apt-get install python-pip

pip install stem

第三步:安装Go语言的运行环境。OnionScan是用Go语言编写的,参考Ryan Frankel 《http://www.hostingadvice.com/how-to/install-golang-on-ubuntu/》 的教程,在服务器上执行下列命令:

bash<<(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)

[[ -s “$HOME/.gvm/scripts/gvm” ]] && source “$HOME/.gvm/scripts/gvm”

source /root/.gvm/scripts/gvm

gvm install go1.8–binary

gvm use go1.8

也可以通过离线下载的方式进行安装:https://golang.org/dl/

第四步,安装OnionScan。命令如下:

go get github.com/s-rah/onionscan

go install github.com/s-rah/onionscan

完成上述步骤后,在终端输入:

onionscan

如果返回“onionscan”的命令行使用信息,恭喜你,onionscan已经安装成功了;

关闭终端后,如果发现不能运行onionscan的话,可以在终端输入下列命令解决该问题:

gvm use go1.8

第五步,修改Tor的配置

为了便于我们编写的Python脚本可以请求一个新的标识(一个新的IP地址),在这里需要对Tor的配置做一些小小的改动。后边在扫描的过程中如果遇到障碍,会用到这部分的内容。

在终端运行如下命令:

tor —hash-passwordYourPasswd

可以根据自己的喜好,设置“YourPasswd”的内容。这时你会接收到一串输出,把它们复制下来,然后在终端执行下来命令:

vim -w /etc/tor/torrc

此时会打开 torrc文件的编辑视图,跳转到文本底部,将之前复制的那串字符粘贴过来,效果类似下图所示:

 

完成之后,保存退出,在终端输入下来命令用于重启Tor服务:

service tor restart

至此,服务器环境搭建工作基本上就已经完成了。(不算太难,不是吗?)

在正式开始编写Python代码之前,还需要添加感兴趣的.onion地址清单,这样才能在暗网中顺利的执行扫描任务。例如:

wget https://raw.githubusercontent.com/automatingosint/osint_public/master/onionrunner/onion_master_list.txt

Tips:使用SSH连接到远程服务器后,执行一些扫描任务比较耗时,这种情况下,可以使用 Screen 命令,创建多个虚拟终端,在虚拟终端里执行命令,断开之前先把 Screen 挂起,重新启用时可以直接连接到之前的Screen上。

编写Python脚本,封装OnionScan

OnionScan是一款伟大的工具,为了能够更好的利用它为我们服务,需要对其进行封装,何况Tor的连接是出了名的不稳定,我们需要能够杀掉一个卡住的扫描进程,也需要能够从Tor网络中抓取新的IP地址。所以,是事后运用你的Python编码能力了。打开一个新的Python文件,并将其命名为onionrunner.py(完整代码参见文章末尾的更多资料部分)

 

第1-12行:载入脚本中所需的模块;

第14-15行:初始化两空链表,分别保存我们完整的 onion列表和正在进行的会话的onion扫描列表。

第17-18行:利用一个事件对象协调两个将被执行的线程。必须首先设置 Event对象,以便默认情况下主线程可以执行。。

接下来还需要构建一些辅助函数,这些函数将处理 main onions列表,并确保能够继续将新发现的onions添加到列表:

 

第23行:定义get_onion_list函数,主要用于加载我们的扫描清单。

第26-33行:一个判断,如果onion_master_list.txt文件存在(26),那么打开它,并祖杭阅读,将结果添加到stored_onions(30);如果文件不存在,则输出一条错误消息(32)并退出脚本(33)。

第35-37行:简单地输出加载的onions的总数(35),Return。

第41行:定义store_onion函数,它接受一个参数(onion),这是我们希望添加到master列表中的隐藏服务(onion网址)。

第45-46行:打开onion_master_list.txt列表文件(45),然后写入隐藏服务的onion地址(46)。

现在我们将实施与运行onionscan二进制做实际的扫描工作处理功能。保持你的编辑器添加代码:

接下来,将处理与运行onionscan二进制文件执行扫描任务相关的代码。

 

更多源代码的分析,感兴趣的话,可以自行阅读。

终端下,运行一下殒命,就可以开始扫描工作了:

python onionrunner.py

此时,你会看到如下所示的输出:

# python onionrunner.py

[*] Total onions for scanning: 7182

[*] Running 0 of 7182.

[*] Onionscanningnfokjthabqzfndmj.onion

[*] Running 1 of 7182.

[*] Onionscanning gmts3xxfrbfxdm3a.onion

检查 onionscan_results 目录,你会看到新增的一些JSON 文件,这些文件一扫描的隐藏服务的地址命名。让它继续运行吧,如果你真的想收集这些目标的信息的话。当然了,如果你使用了本文中所列的Onions列表,那么可以选择直接下载扫描结果:

https://github.com/automatingosint/osint_public/tree/master/onionrunner

利用Shodan搜索引擎扩大暗网 OSNIT的能力

Shodan 搜索引擎可以说是安全专业人员的最常用工具之一,它的搜索能力极其强大,所以,我们需要想办法把它集成到我们的威胁情报分析平台中。幸运的是,Shodan提供了Python接口,这便于我们利用其API进行一些低水平的交互。

首先,安装Shodan。

Windows: pip install shodan

Mac/Linux: sudo pip install shodan

一般情况下,人们不会将同一台服务器同时托管在“公共网络”和“暗网”中,但是也不能排除这种可能。接下来,我们就以检索暗网中的SSH密钥信息为例,进行测试,看看能否碰撞出一些奇妙的结果。

依照咱们的惯例,依然需要编写一个Python脚本来完成此项工作。这一次我们创建一个名为 “sshkeys.py”的脚本(下载链接参见文末更多资料部分):

sshkeys.py 脚本的代码如下图所示:

 

第3行:加载了shodan 模块;

第19-20行:如果扫描结果中包含一个 SSH 密钥,打印出一个友好的提示;

第22-25行:如果 key_to_hosts字典里已经包含了该SSH 密钥(22),添加当前隐藏的服务并存储在密钥列表里(23)。这里之所以使用一个密钥列表,是因为存在同一个SSH 密钥关联多个隐藏服务的情况,这确实很有趣。如果key_to_hosts 字典中没有该SSH 密钥,那么用一个新的列表初始化字典,并添加当前的隐藏服务(25);

第27-35行:当上边的循环代码遍历完所有的JSON文件,我们需要针对每个密钥做一个快速的分析,判断它是否被多个隐藏服务共享。

第37-50行:利用 Shodan 的API,检查密钥的指纹信息(公共网络中的IP地址)。

你可以使用下列命令,直接运行该脚本:

# python sshkeys.py

至此,你可以去检索一下这些公共网络中的IP地址与暗网中隐藏服务的潜在联系了。当然你也可以使用现成的威胁情报分析工具来自动化完成分析工作。

结论

关于暗网中情报的收集和分析,有很多有趣的工作可以去做。

本文只是一个开始,我们希望读者能更多的从信息安全和隐私保护的角度看待暗网,走进暗网,利用智能的情报分析,帮助我们更多地保护客户。

更多资料

http://www.hostingadvice.com/how-to/install-golang-on-ubuntu/

https://raw.githubusercontent.com/automatingosint/osint_public/master/onionrunner/onionrunner.py

https://github.com/automatingosint/osint_public/blob/master/onionrunner/analysis/sshkeys.py

https://www.hunch.ly

前端 onionscan + tor 实现暗网爬取

trainer-co · 2019年12月11日 · 22 次阅读

1、安装相关依赖

123456
yum update
yum install git bison libexif-devyum install toryum install epel-release
yum install python-pippip install stem

2、 安装 go 语言环境

12345678910111213141516
wget https://dl.google.com/go/go1.12.6.linux-amd64.tar.gz# 解压tar -C /usr/local -xzf go1.12.6.linux-amd64.tar.gz# 创建go项目路径mkdir -p /root/gopath# 添加环境变量vi /etc/profile# 添加内容GOROOT=/usr/local/goGOPATH=/root/gopath
export GOROOT
export GOPATH
export PATH=$PATH:$GOPATH/bin:$GOROOT/bin# 使环境变量生效
source /etc/profile

 

3、安装 onionscan

12345678910
# 由于golang.org被墙,不能直接下载文件,所以需要从镜像仓库手动下载相应的依赖文件
mkdir -p /root/gopath/src/golang.org/x

cd /root/gopath/src/golang.org/x/git clone https://github.com/golang/net.git git clone https://github.com/golang/crypto.gitgit clone https://github.com/golang/sys.git# 安装onionscan
go get github.com/s-rah/onionscan
go install github.com/s-rah/onionscan

在命令行输入onionscan返回相应的命令信息表示 onionscan 安装成功

4、Tor 的配置

由于 onionscan 是通过 tor 代理进行访问暗网,而 tor 在国内不能直接连接上,所以需要进行代理配置

1234567891011121314
# 编辑tor配置文件vi /etc/tor/torrc# 在文件最后添加Socks4Proxy 192.98.203.92:1088 #socks4代理地址,也支持http代理和sock5代理
# tor不能用root用户运行,创建一个用户来运行toruseradd tor# 创建tor运行所需的目录,以及赋予权限mkdir -p /run/tor
chown -R tor:tor /run/tor
# 用tor用户登录su tor# 启动tortor

出现如下图输出,表示 tor 启动成功

 

onionscan 的使用

123456
# 创建onionscan数据存储目录mkdir -p /opt/onionscandb
# 使用onionscan进行爬取onionscan -dbdir /opt/onionscandb  -torProxyAddress 127.0.0.1:9050 -depth 1 -jsonReport -verbose wallstyizjhkrvmj.onion

参数说明:

  1. -dbdir 指定爬取数据存储目录,未指定情况下会保存在当前路径下
  2. -torProxyAddress 使用 tor 代理
  3. -depth 指定扫描暗网的深度
  4. -jsonReport 扫描结果生成 json 报告
  5. -verbose 控制台输出详细信息

扫描结果效果图

 

参考资料

  1. 暗网系列之:利用 Python + OnionScan 打造自己的安全威胁情报平台
  2. 用好 OnionScan,自己动手制作暗网爬虫

Window 下安装Redis服务

下载地址:https://github.com/MSOpenTech/redis/releases

Redis 支持 32 位和 64 位。这个需要根据你系统平台的实际情况选择,这里我们下载 Redis-x64-xxx.zip压缩包到 D:\Development_Tools\Redis

安装完成后,安装目录下大概会有以下几个文件:

redis-server.exe:服务端程序,提供redis服务

redis-cli.exe: 客户端程序,通过它连接redis服务并进行操作

redis-check-dump.exe:本地数据库检查

redis-check-aof.exe:更新日志检查

redis-benchmark.exe:性能测试,用以模拟同时由N个客户端发送M个 SETs/GETs 查询 (类似于 Apache 的ab 工具).

redis.windows.conf: 配置文件,将redis作为普通软件使用的配置,命令行关闭则redis关闭

redis.windows-service.conf:配置文件,将redis作为系统服务的配置,用以区别开两种不同的使用方式

查看及修改redis配置文件http://www.cnblogs.com/ningskyer/articles/5730611.html

打开cmd 窗口 使用cd命令切换目录到 D:\Development_Tools\Redis 运行

redis-server.exe redis.windows.conf

*注:可以把 redis 的路径加到系统的环境变量里,这样就省得再输路径了,后面的那个 redis.windows.conf 可以省略,如果省略,会启用默认的。

输入之后,会显示如下界面:

这时候另启一个cmd窗口,原来的不要关闭,不然就无法访问服务端了。

安装服务

redis-server --service-install redis.windows.conf

OK,大功告成,看看本地的服务,是不是加入了Redis了。

启动服务(安装服务之后,Redis并没有启动):

redis-server --service-start

停止服务

redis-server --service-stop

测试:

切换到redis目录下运行

 redis-cli.exe -h 127.0.0.1 -p 6379

设置键值对 set myKey abc

取出键值对 get myKey

 

介绍一款好用的redis可视化工具:Redis Desktop Manager

下载地址:https://redisdesktop.com/download

 

参考文章1:http://www.runoob.com/redis/redis-install.html

参考文章2:http://www.cnblogs.com/ningskyer/articles/5730611.html

python定时爬取网站更新_详解python定时简单爬取网页新闻存入数据库并发送邮件…

于 2020-12-21 11:08:32 发布

一、项目要求

1、程序可以从北京工业大学首页上爬取新闻内容:http://www.bjut.edu.cn

 

2、程序可以将爬取下来的数据写入本地MySQL数据库中。

3、程序可以将爬取下来的数据发送到邮箱。

4、程序可以定时执行。

二、项目分析

1、爬虫部分利用requests库爬取html文本,再利用bs4中的BeaultifulSoup库来解析html文本,提取需要的内容。

2、使用pymysql库连接MySQL数据库,实现建表和插入内容操作。

3、使用smtplib库建立邮箱连接,再使用email库将文本信息加工成邮件消息并发送。

4、使用schedule库实现定时执行该程序。

三、代码分析

1、导入需要的库:

# 爬虫相关模块

import requests

from bs4 import BeautifulSoup

import pymysql

# 发邮件相关模块

import smtplib

from email.mime.text import MIMEText

from email.header import Header

import time

# 定时模块

import schedule

2、获取html文件:

# 连接获取html文本

def getHTMLtext(url):

try:

headers={undefined

“user-agent”:”Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36″,

} # 浏览器请求头

r = requests.get(url, headers = headers, timeout = 30) # 获取连接

r.raise_for_status() # 测试连接是否成功,若失败则报异常

r.encoding = r.apparent_encoding # 解析编码

return r.text

except:

return “”

其中必须添加请求头headers否则get请求时会返回错误页面。

raise_for_status()可以根据状态码判断连接对象的状态,如果成功便继续执行,若连接失败则抛出异常,因此利用try-except捕获。

apparent_encoding()方法可以解析判断可能的编码方式。

3、解析html提取数据:

首先观察网页源码确定新闻标签位置:

 

# 解析html提取数据

def parseHTML(news, html):

soup = BeautifulSoup(html, “html.parser”) # 获取soup

for i in soup.find(attrs = {‘class’ : ‘list’}).find_all(‘li’): # 存放新闻的li标签

date = i.p.string + ‘-‘ + i.h2.string # 日期

href = i.a[‘href’] # 链接

title = i.find(‘h1’).string # 标题

content = i.find_all(‘p’)[1].string # 梗概

news.append([date, href, title, content]) # 添加到列表中

可见所有新闻内容全部存放在class为”list”的div标签中,而每条新闻又存放在li标签中,因此利用find和find_all方法遍历所有li标签。

每个li标签中a标签的href属性存放新闻链接,h1标签存放新闻标题,h2标签存放日期,第一个p标签存放年、月,第二个p标签存放新闻梗概。依次取出对应标签中的文本内容,并将年月日拼接后依次存入news列表中。

4、存入数据库

# 存入数据库

def toMysql(news):

conn = pymysql.connect(host = ‘localhost’, port = 3306, user = ‘root’, passwd = ‘数据库密码’, db = ‘数据库名称’,charset = ‘gbk’, connect_timeout = 1000)

cursor = conn.cursor()

sql = ”’

create table if not exists tb_news(

日期 date,

链接 varchar(400),

标题 varchar(400),

梗概 varchar(400))

”’

cursor.execute(sql) # 建表

for new in news: # 循环存入数据

sql = ‘insert into tb_news(日期, 链接, 标题, 梗概) values(%s, %s, %s, %s)’

date = new[0]

href = new[1]

title = new[2]

content = new[3]

cursor.execute(sql, (date, href, title, content))

conn.commit()

conn.close()

由于新闻字数较多,存取时可能会有乱码以及数据过长存储失败的问题,与数据库编码有关,可以在MySQL的my.ini配置文件中修改默认编码为gbk。

5、发送邮件

# 发送邮件

def sendMail(news):

from_addr = ‘发送邮箱’ # 发送邮箱

password = ’16位授权码’ # 邮箱授权码

to_addr = ‘接收邮箱’ # 接收邮箱

mailhost = ‘smtp.qq.com’ # qq邮箱的smtp地址

qqmail = smtplib.SMTP() # 建立SMTP对象

qqmail.connect(mailhost, 25) # 25为SMTP常用端口

qqmail.login(from_addr, password) # 登录邮箱

content = ”

for new in news: # 拼接邮件内容字符串

content += ‘新闻时间:’ + new[0] + ‘\n’ + ‘新闻链接:’ + new[1] + ‘\n’ + ‘新闻标题:’ + new[2] + ‘\n’ + ‘新闻梗概:’ + new[3] + ‘\n’

content += ‘======================================================================\n’

# 拼接题目字符串

subject = time.strftime(‘%Y-%m-%d %X’, time.localtime(time.time())) + ‘时爬取的北工大首页主要新闻\n’

# 加工邮件message格式

msg = MIMEText(content, ‘plain’, ‘utf-8’)

msg[‘subject’] = Header(subject, ‘utf-8’)

try:

qqmail.sendmail(from_addr, to_addr, msg.as_string())

print(‘发送成功’)

except:

print(‘发送失败’)

qqmail.quit()

注意其中的密码不是指邮箱的登录密码,而是指邮箱的smtp授权码,qq邮箱可以再设置中开启smtp服务,并获取授权码。

 

6、主函数

# 主函数

def main():

news = []

url = “http://www.bjut.edu.cn/”

html = getHTMLtext(url)

parseHTML(news, html)

toMysql(news)

print(news)

sendMail(news)

输入北京工业大学官网的url并新建一个列表news用来存放消息,然后依次调用函数爬取新闻存入数据库并发到邮箱。为了检验上述程序是否可以完成任务,先调用依次main()函数并print(news)看看结果:

main() #测试需要,之后会删除

结果如下:

 

 

 

由此可见程序执行正常。

7、定时执行

# 定时执行整个任务

schedule.every().monday.at(“08:00”).do(main) # 每周一早上八点执行main函数

while True:

schedule.run_pending()

time.sleep(1)

用死循环保证schedule一直运行。设定的是每周一早上8:00执行程序。

为了方便检查效果,先将运行时间改为每5s运行一次:

schedule.every(5).seconds.do(main)

 

每5s便可以收到一封邮件,由此可见满足定时需求。至此程序结束。

四、完整代码

# 爬虫相关模块

import requests

from bs4 import BeautifulSoup

import pymysql

# 发邮件相关模块

import smtplib

from email.mime.text import MIMEText

from email.header import Header

import time

# 定时模块

import schedule

# 连接获取html文本

def getHTMLtext(url):

try:

headers={undefined

“user-agent”:”Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36″,

} # 浏览器请求头

r = requests.get(url, headers = headers, timeout = 30) # 获取连接

r.raise_for_status() # 测试连接是否成功,若失败则报异常

r.encoding = r.apparent_encoding # 解析编码

return r.text

except:

return “”

# 解析html提取数据

def parseHTML(news, html):

soup = BeautifulSoup(html, “html.parser”) # 获取soup

for i in soup.find(attrs = {‘class’ : ‘list’}).find_all(‘li’): # 存放新闻的li标签

date = i.p.string + ‘-‘ + i.h2.string # 日期

href = i.a[‘href’] # 链接

title = i.find(‘h1’).string # 标题

content = i.find_all(‘p’)[1].string # 梗概

news.append([date, href, title, content]) # 添加到列表中

# 存入数据库

def toMysql(news):

conn = pymysql.connect(host = ‘localhost’, port = 3306, user = ‘root’, passwd = ‘数据库密码’, db = ‘数据库名称’,charset = ‘gbk’, connect_timeout = 1000)

cursor = conn.cursor()

sql = ”’

create table if not exists tb_news(

日期 date,

链接 varchar(400),

标题 varchar(400),

梗概 varchar(400))

”’

cursor.execute(sql) # 建表

for new in news: # 循环存入数据

sql = ‘insert into tb_news(日期, 链接, 标题, 梗概) values(%s, %s, %s, %s)’

date = new[0]

href = new[1]

title = new[2]

content = new[3]

cursor.execute(sql, (date, href, title, content))

conn.commit()

conn.close()

# 发送邮件

def sendMail(news):

from_addr = ‘发送邮箱’ # 发送邮箱

password = ’16位授权码’ # 邮箱授权码

to_addr = ‘接收邮箱’ # 接收邮箱

mailhost = ‘smtp.qq.com’ # qq邮箱的smtp地址

qqmail = smtplib.SMTP() # 建立SMTP对象

qqmail.connect(mailhost, 25) # 25为SMTP常用端口

qqmail.login(from_addr, password) # 登录邮箱

content = ”

for new in news: # 拼接邮件内容字符串

content += ‘新闻时间:’ + new[0] + ‘\n’ + ‘新闻链接:’ + new[1] + ‘\n’ + ‘新闻标题:’ + new[2] + ‘\n’ + ‘新闻梗概:’ + new[3] + ‘\n’

content += ‘======================================================================\n’

# 拼接题目字符串

subject = time.strftime(‘%Y-%m-%d %X’, time.localtime(time.time())) + ‘时爬取的北工大首页主要新闻\n’

# 加工邮件message格式

msg = MIMEText(content, ‘plain’, ‘utf-8’)

msg[‘subject’] = Header(subject, ‘utf-8’)

try:

qqmail.sendmail(from_addr, to_addr, msg.as_string())

print(‘发送成功’)

except:

print(‘发送失败’)

qqmail.quit()

# 主函数

def main():

news = []

url = “http://www.bjut.edu.cn/”

html = getHTMLtext(url)

parseHTML(news, html)

print(news)

sendMail(news)

# 定时执行整个任务

schedule.every().monday.at(“08:00”).do(main) # 每周一早上八点执行main函数

while True:

schedule.run_pending()

time.sleep(1)

相关文章
————————————————
版权声明:本文为CSDN博主「weixin_39997695」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_39997695/article/details/111783667

python程序定时或隔时运行

python怎么设置每隔几秒执行脚本?

python设置每隔几秒执行脚本的方法:

1、利用python死循环实现每10s执行一次脚本

#!/usr/bin/env python
import os,time
#how to run it?
#nohup python -u example.py >> /data/logs/example.log 2>&1 &
while True:
        os.system('command')//执行系统命令
        time.sleep(10)//推迟执行、休眠

2、设置1-10s执行一次脚本

#!/usr/bin/env python
import os,time,random
#how to run it?
#nohup python -u example.py >> /data/logs/example.log 2>&1 &
while True:
        sleeptime=random.randint(0, 10)//1-10随机数
        os.system('command')
        time.sleep(sleeptime)

更多Python知识请关注Python自学网

给定需要的时间执行此函数,每隔5秒执行一次的完整代码如下

import time

def sleeptime(hour, min, sec):
return hour * 3600 + min * 60 + sec

second = sleeptime(0, 0, 5)
while 1 == 1:
time.sleep(second)
print(‘do action’)
# 这是隔5秒执行一次
————————————————
版权声明:本文为CSDN博主「夕闻」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43207144/article/details/110367052

python每天定时9点执行_Python实现定时任务,定时采集数据,定时执行脚本程序都可以…

写后端的同学们可能都知道,工作中可能需要周期性执行一些任务,俗称定时任务。Linux环境下,可以借助于系统自带的crontab完成定时任务。但是很多时候,开发的同学们可能并没有权限去操作crontab,所以就催生了一些不太好的解决方案,比如基于Python/Java里面的Timer去弄一个周期性执行的工具。

很多人学习python,不知道从何学起。

很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。

很多已经做案例的人,却不知道如何去学习更加高深的知识。

那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!

大佬们,醒醒,主角出场了。今天给大家分享一个Python轻量级定时任务解决方案,schedule,可以满足常用的周期性任务需求。

安装

pipinstall schedule

使用

schedule提供了多种方法去描述执行周期,比如:

#1,按照某个时间间隔

every(10).seconds.do(task),表示每隔10秒执行task任务。当然可以把间隔换成其他单位,比如minutes,hours,days

#2,按照一个固定的时间点

every().day.at(‘9:30’).do(task),表示每天9:30执行任务

#encoding=utf-8

fromdatetimeimportdatetime

importtime

importschedule

defjob1(*args):

withopen(‘tasks’,’a’)asf:

f.write(‘[{}]{}\n’.format(datetime.now().strftime(‘%Y-%m-%d %H:%M:%S.%f’),’msg’))

# 每隔5秒执行一次job1

schedule.every(5).seconds.do(job1)

# 每天9:30执行任务

schedule.every().day.at(’09:30′).do(job1)

if__name__ ==’__main__’:

whileTrue:

schedule.run_pending()

time.sleep(1)

效果

如何让任务只执行一次?

只需要在任务最后加上这句话就行,return schedule.CancelJob

#encoding=utf-8

fromdatetimeimportdatetime

importtime

importscheduledef job_run_once(*args):

print(‘Job run only once’)

#

returnschedule.CancelJob

# 只执行一次任务

schedule.every(3).seconds.do(job_run_once)

if__name__ ==’__main__’:

whileTrue:

schedule.run_pending()

time.sleep(1)

就是这么简单,你学会了吗?

  • 实现定时刷新
from time import sleep
from selenium import webdriver
driver= webdriver.Chrome() #  需要 下载 对应浏览器 驱动到 python 安装目录
driver.get("https://blog.csdn.net/qq_27061049/article/details/90577597") # 刷新网址
for i in range(10000): # 刷新次数
    driver.refresh()  # 刷新网页
    sleep(5) # 五秒一次

python中各种转义字符

Python 字符串

字符串是 Python 中最常用的数据类型。我们可以使用引号(‘或”)来创建字符串。

创建字符串很简单,只要为变量分配一个值即可。例如:

var1 = 'Hello World!'
var2 = "Python Runoob"

Python 访问字符串中的值

Python 不支持单字符类型,单字符在 Python 中也是作为一个字符串使用。

Python 访问子字符串,可以使用方括号来截取字符串,如下实例:

实例(Python 2.0+)

#!/usr/bin/python
var1 = Hello World!
var2 = Python Runoob
print var1[0]: , var1[0]
print var2[1:5]: , var2[1:5]

以上实例执行结果:

var1[0]:  H
var2[1:5]:  ytho

Python 字符串连接

我们可以对字符串进行截取并与其他字符串进行连接,如下实例:

实例(Python 2.0+)

#!/usr/bin/python
# -*- coding: UTF-8 -*-
var1 = Hello World!
print 输出 :- , var1[:6] + Runoob!

以上实例执行结果

输出 :-  Hello Runoob!

Python 转义字符

在需要在字符中使用特殊字符时,python 用反斜杠 \ 转义字符。如下表:

转义字符 描述
\(在行尾时) 续行符
\\ 反斜杠符号
\’ 单引号
\” 双引号
\a 响铃
\b 退格(Backspace)
\e 转义
\000
\n 换行
\v 纵向制表符
\t 横向制表符
\r 回车
\f 换页
\oyy 八进制数,y 代表 0~7 的字符,例如:\012 代表换行。
\xyy 十六进制数,以 \x 开头,yy代表的字符,例如:\x0a代表换行
\other 其它的字符以普通格式输出

Python字符串运算符

下表实例变量 a 值为字符串 “Hello”,b 变量值为 “Python”:

操作符 描述 实例
+ 字符串连接
>>>a + b HelloPython
* 重复输出字符串
>>>a * 2 HelloHello
[] 通过索引获取字符串中字符
>>>a[1] e
[ : ] 截取字符串中的一部分
>>>a[1:4] ell
in 成员运算符 – 如果字符串中包含给定的字符返回 True
>>>H in a True
not in 成员运算符 – 如果字符串中不包含给定的字符返回 True
>>>M not in a True
r/R 原始字符串 – 原始字符串:所有的字符串都是直接按照字面的意思来使用,没有转义特殊或不能打印的字符。 原始字符串除在字符串的第一个引号前加上字母”r”(可以大小写)以外,与普通字符串有着几乎完全相同的语法。
>>>print r\n \n >>> print R\n \n
% 格式字符串 请看下一章节

实例(Python 2.0+)

#!/usr/bin/python
# -*- coding: UTF-8 -*-
a = Hello
b = Python
print a + b 输出结果:, a + b
print a * 2 输出结果:, a * 2
print a[1] 输出结果:, a[1]
print a[1:4] 输出结果:, a[1:4] if( H in a) :
print H 在变量 a 中 else :
print H 不在变量 a 中 if( M not in a) :
print M 不在变量 a 中 else :
print M 在变量 a 中
print r\n print R\n

以上程序执行结果为:

a + b 输出结果: HelloPython
a * 2 输出结果: HelloHello
a[1] 输出结果: e
a[1:4] 输出结果: ell
H 在变量 a 
M 不在变量 a 
\n
\n

Python 字符串格式化

Python 支持格式化字符串的输出 。尽管这样可能会用到非常复杂的表达式,但最基本的用法是将一个值插入到一个有字符串格式符 %s 的字符串中。

在 Python 中,字符串格式化使用与 C 中 sprintf 函数一样的语法。

如下实例:

#!/usr/bin/python

print "My name is %s and weight is %d kg!" % ('Zara', 21)

以上实例输出结果:

My name is Zara and weight is 21 kg!

python 字符串格式化符号:

<tbody</tbody

    符   号 描述
      %c  格式化字符及其ASCII码
      %s  格式化字符串
      %d  格式化整数
      %u  格式化无符号整型
      %o  格式化无符号八进制数
      %x  格式化无符号十六进制数
      %X  格式化无符号十六进制数(大写)
      %f  格式化浮点数字,可指定小数点后的精度
      %e  用科学计数法格式化浮点数
      %E  作用同%e,用科学计数法格式化浮点数
      %g  %f和%e的简写
      %G  %F 和 %E 的简写
      %p  用十六进制数格式化变量的地址

格式化操作符辅助指令:

符号 功能
* 定义宽度或者小数点精度
用做左对齐
+ 在正数前面显示加号( + )
<sp> 在正数前面显示空格
# 在八进制数前面显示零(‘0′),在十六进制前面显示’0x’或者’0X'(取决于用的是’x’还是’X’)
0 显示的数字前面填充’0’而不是默认的空格
% ‘%%’输出一个单一的’%’
(var) 映射变量(字典参数)
m.n. m 是显示的最小总宽度,n 是小数点后的位数(如果可用的话)

Python2.6 开始,新增了一种格式化字符串的函数 str.format(),它增强了字符串格式化的功能。


Python 三引号

Python 中三引号可以将复杂的字符串进行赋值。

Python 三引号允许一个字符串跨多行,字符串中可以包含换行符、制表符以及其他特殊字符。

三引号的语法是一对连续的单引号或者双引号(通常都是成对的用)。

 >>> hi = '''hi 
there'''
>>> hi   # repr()
'hi\nthere'
>>> print hi  # str()
hi 
there  

三引号让程序员从引号和特殊字符串的泥潭里面解脱出来,自始至终保持一小块字符串的格式是所谓的WYSIWYG(所见即所得)格式的。

一个典型的用例是,当你需要一块HTML或者SQL时,这时当用三引号标记,使用传统的转义字符体系将十分费神。

 errHTML = '''
<HTML><HEAD><TITLE>
Friends CGI Demo</TITLE></HEAD>
<BODY><H3>ERROR</H3>
<B>%s</B><P>
<FORM><INPUT TYPE=button VALUE=Back
ONCLICK="window.history.back()"></FORM>
</BODY></HTML>
'''
cursor.execute('''
CREATE TABLE users (  
login VARCHAR(8), 
uid INTEGER,
prid INTEGER)
''')

Unicode 字符串

Python 中定义一个 Unicode 字符串和定义一个普通字符串一样简单:

>>> u'Hello World !'
u'Hello World !'

引号前小写的”u”表示这里创建的是一个 Unicode 字符串。如果你想加入一个特殊字符,可以使用 Python 的 Unicode-Escape 编码。如下例所示:

>>> u'Hello\u0020World !'
u'Hello World !'

被替换的 \u0020 标识表示在给定位置插入编码值为 0x0020 的 Unicode 字符(空格符)。


python的字符串内建函数

字符串方法是从python1.6到2.0慢慢加进来的——它们也被加到了Jython中。

这些方法实现了string模块的大部分方法,如下表所示列出了目前字符串内建支持的方法,所有的方法都包含了对Unicode的支持,有一些甚至是专门用于Unicode的。

方法 描述
string.capitalize() 把字符串的第一个字符大写
string.center(width) 返回一个原字符串居中,并使用空格填充至长度 width 的新字符串
string.count(str, beg=0, end=len(string)) 返回 str 在 string 里面出现的次数,如果 beg 或者 end 指定则返回指定范围内 str 出现的次数
string.decode(encoding=’UTF-8′, errors=’strict’) 以 encoding 指定的编码格式解码 string,如果出错默认报一个 ValueError 的 异 常 , 除非 errors 指 定 的 是 ‘ignore’ 或 者’replace’
string.encode(encoding=’UTF-8′, errors=’strict’) 以 encoding 指定的编码格式编码 string,如果出错默认报一个ValueError 的异常,除非 errors 指定的是’ignore’或者’replace’
string.endswith(obj, beg=0, end=len(string)) 检查字符串是否以 obj 结束,如果beg 或者 end 指定则检查指定的范围内是否以 obj 结束,如果是,返回 True,否则返回 False.
string.expandtabs(tabsize=8) 把字符串 string 中的 tab 符号转为空格,tab 符号默认的空格数是 8。
string.find(str, beg=0, end=len(string)) 检测 str 是否包含在 string 中,如果 beg 和 end 指定范围,则检查是否包含在指定范围内,如果是返回开始的索引值,否则返回-1
string.format() 格式化字符串
string.index(str, beg=0, end=len(string)) 跟find()方法一样,只不过如果str不在 string中会报一个异常.
string.isalnum() 如果 string 至少有一个字符并且所有字符都是字母或数字则返

回 True,否则返回 False

string.isalpha() 如果 string 至少有一个字符并且所有字符都是字母则返回 True,

否则返回 False

string.isdecimal() 如果 string 只包含十进制数字则返回 True 否则返回 False.
string.isdigit() 如果 string 只包含数字则返回 True 否则返回 False.
string.islower() 如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是小写,则返回 True,否则返回 False
string.isnumeric() 如果 string 中只包含数字字符,则返回 True,否则返回 False
string.isspace() 如果 string 中只包含空格,则返回 True,否则返回 False.
string.istitle() 如果 string 是标题化的(见 title())则返回 True,否则返回 False
string.isupper() 如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是大写,则返回 True,否则返回 False
string.join(seq) 以 string 作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串
string.ljust(width) 返回一个原字符串左对齐,并使用空格填充至长度 width 的新字符串
string.lower() 转换 string 中所有大写字符为小写.
string.lstrip() 截掉 string 左边的空格
string.maketrans(intab, outtab]) maketrans() 方法用于创建字符映射的转换表,对于接受两个参数的最简单的调用方式,第一个参数是字符串,表示需要转换的字符,第二个参数也是字符串表示转换的目标。
max(str) 返回字符串 str 中最大的字母。
min(str) 返回字符串 str 中最小的字母。
string.partition(str) 有点像 find()和 split()的结合体,从 str 出现的第一个位置起,把 字 符 串 string 分 成 一 个 3 元 素 的 元 组 (string_pre_str,str,string_post_str),如果 string 中不包含str 则 string_pre_str == string.
string.replace(str1, str2,  num=string.count(str1)) 把 string 中的 str1 替换成 str2,如果 num 指定,则替换不超过 num 次.
string.rfind(str, beg=0,end=len(string) ) 类似于 find() 函数,返回字符串最后一次出现的位置,如果没有匹配项则返回 -1。
string.rindex( str, beg=0,end=len(string)) 类似于 index(),不过是返回最后一个匹配到的子字符串的索引号。
string.rjust(width) 返回一个原字符串右对齐,并使用空格填充至长度 width 的新字符串
string.rpartition(str) 类似于 partition()函数,不过是从右边开始查找
string.rstrip() 删除 string 字符串末尾的空格.
string.split(str=””, num=string.count(str)) 以 str 为分隔符切片 string,如果 num 有指定值,则仅分隔 num+1 个子字符串
string.splitlines([keepends]) 按照行(‘\r’, ‘\r\n’, \n’)分隔,返回一个包含各行作为元素的列表,如果参数 keepends 为 False,不包含换行符,如果为 True,则保留换行符。
string.startswith(obj, beg=0,end=len(string)) 检查字符串是否是以 obj 开头,是则返回 True,否则返回 False。如果beg 和 end 指定值,则在指定范围内检查.
string.strip([obj]) 在 string 上执行 lstrip()和 rstrip()
string.swapcase() 翻转 string 中的大小写
string.title() 返回”标题化”的 string,就是说所有单词都是以大写开始,其余字母均为小写(见 istitle())
string.translate(str, del=””) 根据 str 给出的表(包含 256 个字符)转换 string 的字符,

要过滤掉的字符放到 del 参数中

string.upper() 转换 string 中的小写字母为大写
string.zfill(width) 返回长度为 width 的字符串,原字符串 string 右对齐,前面填充0

 

python实现excel的覆盖写入和追加

python 读取excel方法(最大行数:1048576)


首先需要导入 import openpyxl

1、打开excel,并且获取sheet

1     inwb=openpyxl.load_workbook(Path_generate)
2     Sheetnames=inwb.get_sheet_names()
3     ws=inwb.get_sheet_by_name(Sheetnames[0])

2,最大行数,列数

1     rows=ws.max_row
2     cols=ws.max_column

3,输出指定数值

1 print(ws.cell(1,1).value)

4,写:创造空白空间及sheet

1 outwb=openpyxl.Workbook()
2 outws=outwb.create_sheet(index=0)

5,写:写入信息

1 outws.cell(row, col).value = row * 2  # 写文件

6,保存文件

1 saveExcel = "D:\work\Excel_txtProcesss\test.xlsx"
2 outwb.save(saveExcel)  # 一定要记得保存

汇总:

读取函数

复制代码
 1  def readExel(self):
 2         filename = r'D:workExcel_txtProcesss
ew-微博-合并58.xlsx'
 3         inwb = openpyxl.load_workbook(filename)  # 读文件
 4 
 5         sheetnames = inwb.get_sheet_names()  # 获取读文件中所有的sheet,通过名字的方式
 6         ws = inwb.get_sheet_by_name(sheetnames[0])  # 获取第一个sheet内容
 7 
 8         # 获取sheet的最大行数和列数
 9         rows = ws.max_row
10         cols = ws.max_column
11         for r in range(1, rows):
12             for c in range(1, cols):
13                 print(ws.cell(r, c).value)
14             if r == 10:
15                 break
复制代码

写函数

复制代码
1     def writeExcel(self):
2         outwb = openpyxl.Workbook()  # 打开一个将写的文件
3         outws = outwb.create_sheet(index=0)  # 在将写的文件创建sheet
4         for row in range(1, 70000):
5             for col in range(1, 4):
6                 outws.cell(row, col).value = row * 2  # 写文件
7             print(row)
8         saveExcel = "D:\work\Excel_txtProcesss\test.xlsx"
9         outwb.save(saveExcel)  # 一定要记得保存
复制代码

背景:需要生成类似自动化case格式的那种excel表格

覆盖式写入:
献上代码:

import xlrd
import openpyxl
from xlutils.copy import copy

#覆盖式写入,定义覆盖写入excel函数
def WriteExcel(path, sheet_name):
”’
# :param sheet_name: 需要改写的sheet_name
# :param path: 工作薄的路径
# :return:
# ”’
workbook = openpyxl.Workbook()
sheet = workbook.active
sheet.title = sheet_name
k_list = []
v_list = []
for k,v in value_dict.items():
k_list.append(k)
v_list.append(v)
for i in range(0, len(k_list)):
sheet.cell(row=1, column=i + 1, value=k_list[i])
for j in range(0, len(v_list)):
sheet.cell(row=i + 2, column=j + 1, value=v_list[j])

workbook.save(path)
print(“xlsx格式表格【覆盖】写入数据成功!”)

if __name__ == ‘__main__’:

#定义工作薄的路径
path = ‘/Users/dongyue/Desktop/code/leecode/xlsx格式demo.xlsx’
#定义要写入的行和列的值
value_dict = {
“请求方法”:”post”,
“请求参数”:”测试参数”,
“返回参数”:”测试参数”,
“预期结果”:”successful”,
“实际结果”:”successful”,
}
#定义excel的sheet_name “xlsx格式测试表 ”
sheet_name = “xlsx格式测试表”

WriteExcel(path,sheet_name)
执行结果是:

excel中的显示是:

 

这个在第二次执行的时候会覆盖原来的内容,所以这种是全部覆盖式的写入。

 

追加式写入:
献上代码:

import xlrd
import openpyxl
from xlutils.copy import copy

#append写入,定义追加写入excel函数
def WriteExcelAppend(path):
”’
:param line_number: 行数
:param path: 工作薄的路径
:return:
”’
workbook = xlrd.open_workbook(path) #打开工作薄
sheets_name = workbook.sheet_names() #获取工作薄的所有的sheet名称
worksheet = workbook.sheet_by_name(sheets_name[0]) #获取工作薄中的第一个sheet
rows_exists = worksheet.nrows #获取已经存在的数据行数
new_workbook = copy(workbook) #将xlrd对象拷贝转化为xlwt对象
new_worksheet = new_workbook.get_sheet(0) #获取转化后的第一个表格
v_list = []
for k, v in value_dict.items():
v_list.append(v)
for j in range(0, len(v_list)):
new_worksheet.write(rows_exists, j, v_list[j])
new_workbook.save(path) # 保存工作簿
print(“xls格式表格【追加】写入数据成功!”)

if __name__ == ‘__main__’:

#定义工作薄的路径
path = ‘/Users/dongyue/Desktop/code/leecode/xlsx格式demo.xlsx’
#定义要写入的行和列的值
value_dict = {
“请求方法”:”post”,
“请求参数”:”测试参数”,
“返回参数”:”测试参数”,
“预期结果”:”successful”,
“实际结果”:”successful”,
}
#定义excel的sheet_name “xlsx格式测试表 ”
sheet_name = “xlsx格式测试表”

WriteExcelAppend(path)

在执行之前我在excel中备注下:

希望达到的预期是在这行之后进行追加

执行结果为:

excel中的展示

 

我在追加的时候只追加了一条数据,如果小伙伴们想追加多条,可以进行循环。这种的数据是我们自行写死的,在测试过程中的话,是需要拉取各种参数,然后进行写入的,我们可以获取各种参数后,给他处理成dict形式。

还有就是如果想自行的让代码看这个操作是执行追加还是覆盖的话。可以先获取下,已经存在的行数(上面的代码中有),如果值等于0,就说明该表中没有数据,可以执行覆盖式的写入,如果值大于0,就需要进行追加式写入。

现在的excel表格是这样的:

 

将下方代码进行更改

if __name__ == ‘__main__’:

#定义工作薄的路径
path = ‘/Users/dongyue/Desktop/code/leecode/xlsx格式demo.xlsx’
#定义要写入的行和列的值
value_dict = {
“请求方法”:”post”,
“请求参数”:”测试参数”,
“返回参数”:”测试参数”,
“预期结果”:”successful”,
“实际结果”:”successful”,
}
#定义excel的sheet_name “xlsx格式测试表 ”
sheet_name = “xlsx格式测试表”

workbook = xlrd.open_workbook(path)
sheets_name = workbook.sheet_names()
worksheet = workbook.sheet_by_name(sheets_name[0])
rows_exists = worksheet.nrows
if rows_exists == 0:
WriteExcel(path,sheet_name)
else:
WriteExcelAppend(path)
其中取出的是第一个sheet,此时是有数据,这种情况下执行应该是进行追加。执行结果如下:

 

excel中展示:

 

如果将worksheet = workbook.sheet_by_name(sheets_name[0]) 后面的sheets_name[0]改为sheets_name[1],此时获取的就是sheet_name为ceshi的那个表格,这个表格是没有数据的。所以我们此时执行就是覆盖写入,并且之前的sheet是没有了的。

执行结果如下:

excel展示:

——————

 



====================================

——————————
版权声明:本文为CSDN博主「Mojitoice」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Mojitoice/article/details/107020961

您的位置: 网站首页openpyxl教程当前文章

openpyxl删除单行删除多行

删除行与列:

woeksheet.delete_rows(row)#这里填的行数从1开始,1是第一行,所以上面的0是无效的

删除列也是同样可以

woeksheet.delete_cols(row)

点击领取>>python全套教程
点击领取>>js逆向_app逆向_安卓群控

  delete_rows可以指定删除一行也可以删除多行,默认删除一行。官方文档如下:

  openpyxl.worksheet.worksheet.Worksheet.delete_rows()
       delete_rows(idx, amount=1)
       Delete row or rows from row==idx

下面的代码演示openpyxl在excel中追加一行、删除第1行、删除第1到3行(删除行和清空行数据不同,删除行后下面的行会往上移)。

  1. # -*- coding: utf-8 -*-
  2. from openpyxl import Workbook
  3. wb = Workbook() # 默认生成一个名为Sheet的sheet
  4.  
  5. # 创建sheet
  6. for name in [‘a’,‘b’]:
  7. ws = wb.create_sheet(name)
  8.  
  9. # 追加行
  10. for sheet in wb:
  11. for i in range(1,5):
  12. sheet.append([‘a’+str(i),‘b’+str(i)])
  13.  
  14. # 删除第一行
  15. for sheet in wb:
  16. sheet.delete_rows(1)
  17.  
  18. # 删除从1到3行
  19. for sheet in wb:
  20. sheet.delete_rows(1,3)
  21.  
  22. wb.save(‘test.xlsx’)
  23.  

自动化测试远程驱动静默方式(Jenkins+Selenium+Chrome+Docker)

于 2017-08-11 18:39:04 发布

由于之前一直使用PhantomJS作为线上静默方案,并且此方案PhantomJS驱动的Binary和测试代码都在同一台服务器上,导致有时候本地做好的Case经常无法完整的正常运作,并且大多数情况下,测试人员本地Case的编写都是采用Chrome作为首选项,所以我们希望能够统一使用Chrome来进行统一驱动,所以本文记载了工作中遇到的一些坑,以免忘记。

注意:此文档所涉及的内容不太适合新同学,新同学可以打开自动化测试入门教程进行学习,大牛可以直接跳过哈。

踏坑过程
所以,在最开始的时候我设想的方案以为是Chrome与PhantomJS一样,只需要简单的下载一个Driver就可以了,后来查阅相关文档才得知Chrome Driver必须要在本机上安装一个Google Chrome浏览器,并且要下载最新的,否则可能不支持Headless,并且支持Headless的ChromeDriver版本也必须要大于等于2.31;然后,我就开始在Centos7上进行折腾安装Google Chrome与ChromeDriver 2.31,2.31版本的Driver总报一个错:./chromedriver: /lib64/libc.so.6: version `GLIBC_2.18’ not found (required by ./chromedriver, 查阅了帖子才知道尼玛2.31在Centos上存在Bug,具体Bug的帖子:链接1-Stackoverflow、链接2-Google Chrome问题、链接3-Chrome Driver问题, 后来打算换2.30搭配Xvfb进行测试,结果还是不行,果断放弃了;后来想竟然Centos7不行,那就到Jenkins Slave的Docker容器中跑的看看吧,因为我这个Slave镜像是用的Debian 8,结果Chrome Driver 2.31是可以运行起来的,我以为一切都OK了,我就上代码开始跑,结果总是不行,我就不信这个邪,继续查阅资料,让我找到了某人做的一个Google Chrome Headless的Docker镜像,我用他的方式运行,并进入到容器中我自己安装Driver 2.31,结果整体测试下来,初步达到我的需求了,尼玛终于弄好了。

实施步骤
方案一(不推荐)
由于我找到的那个镜像并不直接支持ChromeDriver,所以我对他的镜像进行了二次打包,具体可以查看我的Docker Hub地址,或我的Github Dockerfile源码库,都有说明,如果你有任何更好的方案也可以提交PR到我的仓库,我会Merge的,谢谢!

注意:由于此方案是我封装的镜像,非官方的selenium-standalone的方式,会存在一些扩展上的问题,比如没有截图的功能等,在此基础上我推荐使用方案二,当然也可以选择第三方案。

Docker 运行
进入到镜像仓库中,根据文档的说明或直接执行以下在Docker环境运行就可以跑起来了,默认情况下会把ChromeDriver的 –verbose 进行开启。

docker run -d –name selenium-chrome -p 9515:9515 –cap-add=SYS_ADMIN caryyu/selenium-chrome:latest
1
Java代码Selenium使用
URL url = null;
try {
url = new URL(“http://172.16.1.12:9515”);
} catch (MalformedURLException e) {
e.printStackTrace();
}

ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.addArguments(“–headless”,”–disable-gpu”,”–window-size=1290,1080″);
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities.setCapability(“chromeOptions”, chromeOptions);
WebDriver wdriver = new RemoteWebDriver(url,capabilities);
方案二(推荐方案)
此方案比第一方案好一些,基于selenium-standalone的方式封装的,通过HTTP地址能够打开并截图监控运行状况,记住Docker运行下列镜像的时候一定要加 –cap-add=SYS_ADMIN 权限(更多查看下面 Docker容器权限 )。

Docker 运行
docker run -it –rm –name chrome –shm-size=1024m –cap-add=SYS_ADMIN -p 4444:4444 yukinying/chrome-headless-browser-selenium
1
Java代码Selenium使用
我只截取了关键的代码片段,主要的核心是以下连接地址。

URL url = null;
try {
url = new URL(“http://172.16.1.12:4444/wd/hub”);
} catch (MalformedURLException e) {
e.printStackTrace();
}
// 初始化WebDriver代码同上

参数说明
–headless 必须使用静默模式,无GUI界面;
–disable-gpu 必须要禁用掉gpu,因为服务器没有图形显示相关支持;
–window-size 自定义窗口大小,因为浏览器的Window大小会决定获取到元素的可能性。
更多配置信息你参考:Google Chrome 命令选项大全
方案三(可选)
此方案是第二方案的升级,同样也是属于standalone的方式,由开源社区进行针对Docker版本的开发与维护,支持很多新特性,如视频录制与回放,VNC直接通过Web实时监控Case的运行情况,更此项目细节请点击这里: 点击查看。

注意:此方案经我测试发现在多线程情况下跑用例对内存与CPU的资源消耗特大,需要仔细研究相关的设置后按优配置方可,切记!切记!

docker run -d –name zalenium -p 4444:4444 \
-e TZ=”Asia/Shanghai” \
-e SCREEN_WIDTH=1920 -e SCREEN_HEIGHT=1080 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v zalenium-videos:/home/seluser/videos \
–privileged dosel/zalenium start

Docker容器权限
上述的例子当中,我们创建运行容器的时候强调了 –cap-add=SYS_ADMIN 选项,并表示此选项必须要加上,否则会出现各种问题;其实还有一个与之对应的选项 –privileged,所以在这里我根据我所查阅到的资料:资料一、资料二,再结合我个人的理解进行简要解释,如下:

–privileged 赋予容器最高权限,基本上宿主机能干的事情,容器里都能干。
–cap-add=SYS_ADMIN 具体指定容器拥有的权限(可多次指定不同权限),更多选项查看这个:点击查看。
Jenkins 推荐两款插件
TestNG & Report
此插件主要针对生成Report对结果进行查看,主要原理就是解析testng.xml文件生成图表视图,具体可以:点击文档。

TestNG In Progress
此插件就是在多线程或单线运行时可以实时监控testcase运行进度状态,可以进行很快定位出错的用例,不用每次针对结果进行查看,具体文档:点击这里。

题外话
题外话与本篇核心无关,你没有兴趣的话直接忽略就行了,我只是把一些杂项记录一下,方便之后的查阅。

Centos 7 安装谷歌浏览器
我们利用yum工具进行安装,因为有一个好处就是更新方便,更多具体细节:点击这里

软件源
我们先创建软件源(/etc/yum.repos.d/google-chrome.repo)。

[google-chrome]
name=google-chrome
baseurl=http://dl.google.com/linux/chrome/rpm/stable/$basearch
enabled=1
gpgcheck=1
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub

查看版本信息
yum info google-chrome-stable

安装命令
yum install google-chrome-stable

下载ChromeDriver
wget https://chromedriver.storage.googleapis.com/2.30/chromedriver_linux64.zip

Xvfb虚拟帧缓冲图形X Window服务器
我看有些人利用Xvfb做虚拟图形输出,所以我也把相关的内容记录一下,但我没有尝试成功。Xvfb官网地址, 这里有一个其他人做的Case:点击查看.

安装
yum search xvfb
yum install xorg-x11-server-Xvfb

启动XVFB组件
Xvfb :2 -screen 0 1024x768x16 +extension RANDR &

测试试试
export DISPLAY=:2 && google-chrome http://www.baidu.com

参考资料
https://github.com/SeleniumHQ/selenium/wiki/ChromeDriver
https://sites.google.com/a/chromium.org/chromedriver/
————————————————
版权声明:本文为CSDN博主「littlebrain4solving」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/littlebrain4solving/article/details/77102084

使用slenium+chromedriver实现无敌爬虫

 

摘要

@概述 通常各大网站的后台都会有一定的反爬机制,既为了数据安全,也为了减小服务器压力 通常反爬的手段的方向,都 […]

@概述

  • 通常各大网站的后台都会有一定的反爬机制,既为了数据安全,也为了减小服务器压力
  • 通常反爬的手段的方向,都是识别非浏览器客户端,而selenium所做的事情,恰恰是驱动真正的浏览器去执行请求和操作,只不过信号不是来源于鼠标,而是来源于selenium的API(selenium本是一个自动化的测试工具)
  • 自然人用户能做的一切,selenium几乎都驱动浏览器取做,无论是否有界面,包括输入、点击、滑动,等等
  • 然而到底是鼠标操作的浏览器发起的请求还是API,对于服务端来说,是没有任何差别的
  • 所以说:做人难,做男人难,做一个后台开发的男人难上加难,让我们开始对其实施蹂躏吧

@一些掌故

  • 早些的时候流行的组合并不是selenium+chrome浏览器驱动,而是selenium+phantomjs
  • phantomjs是一款没有界面的浏览器,业界称作无头浏览器(headless),由于没有界面和渲染,其运行速度要大大优于有界面的浏览器,这恰恰是爬虫喜欢的,因此红极一时
  • 后来chrome和火狐推出了无头模式,且运行速度很流畅,phantomjs已然寿终正寝,因此我们表过不提@开发环境的搭建(基于ubuntu)
  • 安装selenium:sudo pip install selenium
  • 如果没有则安装chrome浏览器(尽量更新到58以上):http://www.linuxidc.com/Linux/2016-05/131096.htm
  • 安装chrome浏览器驱动(注意最新版本尾号是29而非9):https://www.cnblogs.com/Lin-Yi/p/7658001.html

@导包

  1. 您需要选择一个短代码# 导入selenium的浏览器驱动接口
  2. from selenium import webdriver
  3. # 要想调用键盘按键操作需要引入keys包
  4. from selenium.webdriver.common.keys import Keys
  5. # 导入chrome选项
  6. from selenium.webdriver.chrome.options import Options

@第一个程序:抓取页面内容,生成页面快照

  1. # 创建chrome浏览器驱动,无头模式(超爽)
  2. chrome_options = Options()
  3. chrome_options.add_argument('--headless')
  4. driver = webdriver.Chrome(chrome_options=chrome_options)
  5. # 加载百度页面
  6. driver.get("http://www.baidu.com/")
  7. # time.sleep(3)
  8. # 获取页面名为wrapper的id标签的文本内容
  9. data = driver.find_element_by_id("wrapper").text
  10. print(data)
  11. # 打印页面标题 "百度一下,你就知道"
  12. print(driver.title)
  13. # 生成当前页面快照并保存
  14. driver.save_screenshot("baidu.png")
  15. # 关闭浏览器
  16. driver.quit()

@模拟用户输入和点击搜索,跟真人操作一样!

  1. # get方法会一直等到页面被完全加载,然后才会继续程序,通常测试会在这里选择 time.sleep(2)
  2. driver.get("http://www.baidu.com/")
  3. # id="kw"是百度搜索输入框,输入字符串"程序猿"
  4. driver.find_element_by_id("kw").send_keys(u"程序猿")
  5. # id="su"是百度搜索按钮,click() 是模拟点击
  6. driver.find_element_by_id("su").click()
  7. time.sleep(3)
  8. # 获取新的页面快照
  9. driver.save_screenshot("程序猿.png")
  10. # 打印网页渲染后的源代码
  11. print(driver.page_source)
  12. # 获取当前页面Cookie
  13. print(driver.get_cookies())
  14. # ctrl+a 全选输入框内容
  15. driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'a')
  16. # ctrl+x 剪切输入框内容
  17. driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'x')
  18. # 输入框重新输入内容
  19. driver.find_element_by_id("kw").send_keys("美女")
  20. # 模拟Enter回车键
  21. driver.find_element_by_id("su").send_keys(Keys.RETURN)
  22. time.sleep(3)
  23. # 清除输入框内容
  24. driver.find_element_by_id("kw").clear()
  25. # 生成新的页面快照
  26. driver.save_screenshot("美女.png")
  27. # 获取当前url
  28. print(driver.current_url)
  29. # 关闭浏览器
  30. driver.quit()

@模拟用户登录

  1. # 加载微博登录页
  2. driver.get("http://passport.weibo.cn/signin/login?entry=mweibo&r=http%3A%2F%2Fweibo.cn%2F&backTitle=%CE%A2%B2%A9&vt=")
  3. time.sleep(3)
  4. # 找到输入框,键入用户名和密码
  5. driver.find_element_by_id('loginName').send_keys("worio.hainan@163.com")
  6. driver.find_element_by_id('loginPassword').send_keys("Qq94313805")
  7. # 点击登录按钮
  8. driver.find_element_by_id('loginAction').click()
  9. time.sleep(3)
  10. # 快照显示已经成功登录
  11. print(driver.save_screenshot('jietu.png'))
  12. driver.quit()

@使用cookies登录

  1. # 加载知乎主页,查看快照知此时处于未登录状态
  2. driver.get("https://www.zhihu.com")
  3. time.sleep(1)
  4. print(driver.save_screenshot("zhihu_nocookies.png"))
  5. # 操作浏览器登录知乎并抓包cookies
  6. zhihu_cookies = {
  7. # 'aliyungf_tc' : 'AQAAAAR4YFOeswAAnLFJcVRd4MKOTTXu',
  8. 'l_n_c': '1',
  9. 'q_c1': '8572377703ba49138d30d4b9beb30aed|1514626811000|1514626811000',
  10. 'r_cap_id': 'MTc5M2Y0ODUzMjc0NDMzNmFkNTAzZDBjZTQ4N2EyMTc=|1514626811|a97b2ab0453d6f77c6cdefe903fd649ee8531807',
  11. 'cap_id': 'YjQyZTEwOWM4ODlkNGE1MzkwZTk3NmI5ZGU0ZTY2YzM=|1514626811|d423a17b8d165c8d1b570d64bc98c185d5264b9a',
  12. 'l_cap_id': 'MGE0NjFjM2QxMzZiNGE1ZWFjNjhhZmVkZWQwYzBkZjY=|1514626811|a1eb9f2b9910285350ba979681ca804bd47f12ca',
  13. 'n_c': '1',
  14. 'd_c0': 'AKChpGzG6QyPThyDpmyPhXaV-B9_IYyFspc=|1514626811',
  15. '_xsrf': 'ed7cbc18-03dd-47e9-9885-bbc1c634d10f',
  16. 'capsion_ticket': '2|1:0|10:1514626813|14:capsion_ticket|44:NWY5Y2M0ZGJiZjFlNDdmMzlkYWE0YmNjNjA4MTRhMzY=|6cf7562d6b36288e86afaea5339b31f1dab2921d869ee45fa06d155ea3504fe1',
  17. '_zap': '3290e12b-64dc-4dae-a910-a32cc6e26590',
  18. 'z_c0': '2|1:0|10:1514626827|4:z_c0|92:Mi4xYm4wY0FRQUFBQUFBb0tHa2JNYnBEQ1lBQUFCZ0FsVk5DNjAwV3dCb2xMbEhxc1FTcEJPenpPLWlqSS1qNm5KVEFR|d89c27ab659ba979a977e612803c2c886ab802adadcf70bcb95dc1951bdfaea5',
  19. '__utma': '51854390.2087017282.1514626889.1514626889.1514626889.1',
  20. '__utmb': '51854390.0.10.1514626889',
  21. '__utmc': '51854390',
  22. '__utmz': '51854390.1514626889.1.1.utmcsr=zhihu.com|utmccn=(referral)|utmcmd=referral|utmcct=/',
  23. '__utmv': "51854390.100--|2=registration_date=20150408=1'3=entry_date=20150408=1",
  24. }
  25. # 将用户登录产生的cookies全部添加到当前会话
  26. for k, v in zhihu_cookies.items():
  27. driver.add_cookie({'domain': '.zhihu.com', 'name': k, 'value': v})
  28. # 再次访问知乎主页并拍照,此时已经是登录状态了
  29. driver.get("https://www.zhihu.com")
  30. time.sleep(3)
  31. print(driver.save_screenshot("zhihu_cookies.png"))
  32. # 退出浏览器
  33. driver.quit()

@模拟滚动条的滚动(这个用常规的爬虫很难实现)

  1. # 加载知乎主页
  2. driver.get("https://www.zhihu.com")
  3. time.sleep(1)
  4. # 加载本地cookies实现登录
  5. for k, v in zhihu_cookies.items():
  6. driver.add_cookie({'domain': '.zhihu.com', 'name': k, 'value': v})
  7. # 以登录状态再次发起访问
  8. driver.get("https://www.zhihu.com")
  9. time.sleep(3)
  10. # 将页面滚动到最后,执行多次
  11. for i in range(3):
  12. js = "var q=document.documentElement.scrollTop=10000"
  13. driver.execute_script(js)
  14. time.sleep(3)
  15. # 截图并退出,页面侧边滚动条已经下滑了许多像素
  16. print(driver.save_screenshot("zhihu_scroll.png"))
  17. driver.quit()

@一边滚动一边加载

  • 唯品会首页的女装图片,是一边滚动一边进行ajax异步加载的
  • 这个靠常规的抓包实现起来很麻烦
  • 使用selenium我们只需模拟用户多次下拉滚动条,一段时间之后再重新拿取渲染好的页面源码,就可以像爬取静态页面那样去爬取图片了
  • 类似这种操作,其实质就是开挂,是几乎无法防守的
  1. # 唯品会女装图片链接无法直接获得
  2. # 请求唯品会页面
  3. driver.get("https://category.vip.com/search-3-0-1.html?q=3|30036||&rp=30074|30063&ff=women|0|2|2&adidx=1&f=ad&adp=65001&adid=326630")
  4. time.sleep(3)
  5. # 逐渐滚动浏览器窗口,令ajax逐渐加载
  6. for i in range(1, 10):
  7. js = "var q=document.body.scrollTop=" + str(500 * i) # PhantomJS
  8. js = "var q=document.documentElement.scrollTop=" + str(500 * i) # 谷歌 和 火狐
  9. driver.execute_script(js)
  10. print('=====================================')
  11. time.sleep(3)
  12. # 拿到页面源码
  13. html = etree.HTML(driver.page_source)
  14. all_img_list = []
  15. # 得到所有图片
  16. img_group_list = html.xpath("//img[contains(@id,'J_pic')]")
  17. # img_group_list = html.xpath("//img[starts-with(@id,'J_pic')]")
  18. # 正则表达式匹配
  19. # img_group_list = html.xpath(r'//img[re:match(@id, "J_pic*")]',namespaces={"re": "http://exslt.org/regular-expressions"})
  20. # 收集所有图片链接到列表
  21. for img_group in img_group_list:
  22. img_of_group = img_group.xpath(".//@data-original | .//@data-img-back | .//@data-img-side")
  23. print(img_of_group)
  24. all_img_list.append('\n'.join(img_of_group) + '\n')
  25. # 将收集到的数据写入文件
  26. with open('vip.txt', 'w', encoding='utf-8') as f:
  27. f.write('\n'.join(all_img_list))
  28. # 退出浏览器
  29. driver.quit()