Python利用Zabbix API定时报告存在报警的机器

由于手上的zabbix服务器有几个,有时会没注意报警短信,又懒得登陆上去看看zabbix,所以用Python利用zabbix的API获取有问题的机器每天早上发到我邮箱,foxmail又是我天天都用的东西,这样我就可以方便地看到所有有问题的机器了

zabbix_sendmail.py

#!/usr/bin/python
#coding:utf-8
import smtplib
from email.mime.text import MIMEText
import sys
#mail_to_list = ['lihuipeng@xxx.com',]
mail_host = 'smtp.163.com'
mail_user = 'testest'     #发件人邮箱帐号
mail_pass = '123456'      #发件人邮箱密码
mail_postfix = '163.com'
def send_mail(to_list,subject,content):
    me = mail_user+"<"+mail_user+"@"+mail_postfix+">"
    msg = MIMEText(content)
    msg['Subject'] = subject
    msg['From'] = me
    msg['to'] = ";".join(to_list)
    #msg['to'] = to_list
                                                                                             
    try:
        s = smtplib.SMTP()
        s.connect(mail_host)
        s.login(mail_user,mail_pass)
        s.sendmail(me,to_list,msg.as_string())
        s.close()
        return True
    except Exception,e:
        print str(e)
        return False
                                                                                             
if __name__ == "__main__":
    print sys.argv[1]
    print sys.argv[2]
    print sys.argv[3]
    send_mail(sys.argv[1], sys.argv[2], sys.argv[3])

这个是我用来发邮件的脚本,原理就是连接到163邮箱发送邮件,这里我是注册了一个帐号专门用来发邮件的。

zabbix_report.py

#!/usr/bin/python
#coding:utf-8
import json
import urllib2
from urllib2 import URLError
import sys
import zabbix_sendmail
#接收人
mailtolist = ['test@163.com',]
#格式:zabbix地址,zabbix帐号,zabbix密码,邮件标题
zabbix_addresses=['http://test1.zabbix.com,admin,123456,test1','http://test2.zabbix.com,admin,123456,test2','http://test3.zabbix.com,admin,123456,test3']
class ZabbixTools:
    def __init__(self,address,username,password):
                                                                       
        self.address = address
        self.username = username
        self.password = password
                                                                       
        self.url = '%s/api_jsonrpc.php' % self.address
        self.header = {"Content-Type":"application/json"}
                                                                       
                                                                       
                                                                       
    def user_login(self):
        data = json.dumps({
                           "jsonrpc": "2.0",
                           "method": "user.login",
                           "params": {
                                      "user": self.username,
                                      "password": self.password
                                      },
                           "id": 0
                           })
                                                                       
        request = urllib2.Request(self.url, data)
        for key in self.header:
            request.add_header(key, self.header[key])
                                                                   
        try:
            result = urllib2.urlopen(request)
        except URLError as e:
            print "Auth Failed, please Check your name and password:", e.code
        else:
            response = json.loads(result.read())
            result.close()
            #print response['result']
            self.authID = response['result']
            return self.authID
                                                                           
    def trigger_get(self):
        data = json.dumps({
                           "jsonrpc":"2.0",
                           "method":"trigger.get",
                           "params": {
                                      "output": [
                                                "triggerid",
                                                "description",
                                                "priority"
                                                ],
                                      "filter": {
                                                 "value": 1
                                                 },
                                      "expandData":"hostname",
                                      "sortfield": "priority",
                                      "sortorder": "DESC"
                                    },
                           "auth": self.user_login(),
                           "id":1              
        })
                                                                       
        request = urllib2.Request(self.url, data)
        for key in self.header:
            request.add_header(key, self.header[key])
                                                                       
        try:
            result = urllib2.urlopen(request)
        except URLError as e:
            print "Error as ", e
        else:
            response = json.loads(result.read())
            result.close()
            issues = response['result']
            content = ''
            if issues:
                for line in issues:
                    content = content + "%s:%s\r\n" % (line['host'],line['description'])
            return content
                                                                           
if __name__ == "__main__":
    for zabbix_addres in zabbix_addresses:
        address,username,password,subject = zabbix_addres.split(',')
        z = ZabbixTools(address=address, username=username, password=password)
        content = z.trigger_get()
        zabbix_sendmail.send_mail(mailtolist, subject, content)
    print "Done!"

这里就是利用API查询信息,然后通过上面的发邮件脚本把信息发出来,效果是这样的:

145315337.png

再添加一个crontab就OK~

本文出自 “运维笔记” 博客,请务必保留此出处http://lihuipeng.blog.51cto.com/3064864/1306261

ps:

可能有的人smtp发送会失败,说是认证没有通过,可以试试修改如下:

#!/opt/venv/bin/python
#coding:utf-8
import smtplib
from email.mime.text import MIMEText
import sys
mail_host = 'smtp.xxxxx.com'
mp = 'password'
mail_postfix = 'xxxxx.com'


def send_mail(to_list,subject,content):
 me = 'xxxxx@xxxxx.com'
 msg = MIMEText(content)
 msg['Subject'] = subject
 msg['From'] = me
 msg['to'] = ";".join(to_list)

 try:
 s = smtplib.SMTP(mail_host,25)
 s.ehlo()
 s.starttls()
 s.ehlo
 s.login(me,mp)
 s.sendmail(me,to_list,msg.as_string())
 s.close()
 return True
 except Exception,e:
 print str(e)
 return False

jq : Linux下json的命令行工具

JSON是前端编程经常用到的格式,对于PHP或者Python,解析JSON都不是什么大事,尤其是PHP的json_encode和json_decode,干的相当的漂亮。Linux下也有处理处理JSON的神器:jq。
对于JSON格式而言,jq就像sed/awk/grep这些神器一样的方便,而也,jq没有乱七八糟的依赖,只需要一个binary文件jq,就足矣。下面我们看下jq的使用。
   1 格式化JSON 

  1. manu@manu:~/code/php/json$ cat json_raw.txt
  2. {“name”:”Google”,”location”:{“street”:”1600 Amphitheatre Parkway”,”city”:”Mountain View”,”state”:”California”,”country”:”US”},”employees”:[{“name”:”Michael”,”division”:”Engineering”},{“name”:”Laura”,”division”:”HR”},{“name”:”Elise”,”division”:”Marketing”}]}

上面的JSON是PHP json_encode之后,echo出来的字符串,很明显,可读性太差。前一阵子写文档,需要将前后段JSON写入文档,我当时是用是网上的JSON格式化工具做的。事实上,jq就可以检查JSON的合法性,并把JSON格式化成更友好更可读的格式:

  1.     cat json_raw.txt | jq .

看到上图,将一团乱麻的JSON格式化成个更可读的形式。其实背后另外检查了JSON的合法性。如果JSON不合法,jq .会报错。我故意写个错误的JSON:

  1. manu@manu:~/code/php/json$ cat json_err.txt
  2. {“name”:”Google”,”location”:{“street”:”1600 Amphitheatre Parkway”,”city”:”Mountain View”,”state”:”California”,”country”:”US”},”employees”:[{“name”:”Michael”,”division”:“Engineering”}{“name”:”Laura”,”division”:”HR”},{“name”:”Elise”,”division”:”Marketing”}]}

上面JSON中加粗和斜体部分,遗漏了一个逗号,所以这个JSON是错误的,jq轻松的可以轻松的检查出来:

  1.     manu@manu:~/code/php/json$ cat json_err.txt |jq .
  2.     parse error: Expected separator between values at line 1, column 183

    2 JSON parse
如上图json,jq如何解析JSON,根据key获取value?

  1.     {
  2.         “key_1”:”value_1″,
  3.         “key_2”:”value_2″,
  4.     }

如何根据key获取value?

  1.     jq ‘.key’


解析不存在的元素,会返回null

  1.     echo ‘{“foo”: 42, “bar”: “less interesting data”}’ | jq .nofoo
  2.     null

3 JSON nested parse(嵌套解析)

  1.     cat json_raw.txt | jq ‘.location.state’
  2.     “California”

   4 JSON parse array

  1.     cat json_raw.txt | jq ‘.employees[1].name’
  2.     “Laura”

   5 内建函数
jq还有一些内建函数如 key,has
key是用来获取JSON中的key元素的:

  1. cat json_raw.txt | jq ‘keys’
  2. [
  3.   “employees”,
  4.   “location”,
  5.   “name”
  6. ]

has是用来是判断是否存在某个key:

  1. cat json_raw.txt | jq ‘has(“name”)’
  2. true
  3. cat json_raw.txt | jq ‘has(“noexisted”)’
  4. false

与JSON相关的我就暂时介绍到这里,希望进一步了解jq并使用的可以去http://stedolan.github.io/jq/manual/,希望了解源码实现的,可以去https://github.com/stedolan/jq,意料之中的事情是 作者用来flex和bison来parse json。我们的示例JSON来自参考文献第一篇。用google搜索,kernalpanic中有篇文章介绍了jshon和json.sh提供了另外的思路。不过我挺喜欢及

参考文献:
How to parse JSON string via command line on Linux
2  jq – command-line JSON processor

使用virtualenv搭建独立的Python环境

virtualenv可以搭建虚拟且独立的python环境,可以使每个项目环境与其他项目独立开来,保持环境的干净,解决包冲突问题。

一、安装virtualenv

virtualenv实际上是一个python包,所以我们可以用easy_install或者pip安装。下面介绍在CentOS系统上的安装方法。

easy_install安装方式:

1
2
[root@localhost ~]# yum install python-setuptools python-devel
[root@localhost ~]# easy_install virtualenv

pip安装方式:

1
2
[root@localhost ~]# easy_install pip
[root@localhost ~]# pip install virtualenv

yum安装方式(epel源):

1
[root@localhost ~]# yum install python-virtualenv

二、创建python虚拟环境

使用virtualenv命令创建python虚拟环境:virtualenv [虚拟环境名称]。

1
2
3
[root@localhost ~]# virtualenv env1
New python executable in env1/bin/python
Installing setuptools, pip...done.

执行后,在本地会生成一个与虚拟环境同名的文件夹。

如果你的系统里安装有不同版本的python,可以使用–python参数指定虚拟环境的python版本:

1
2
3
4
5
[root@localhost ~]# virtualenv --python=/usr/local/python-2.7.8/bin/python2.7 env1
Running virtualenv with interpreter /usr/local/python-2.7.8/bin/python2.7
New python executable in env1/bin/python2.7
Also creating executable in env1/bin/python
Installing setuptools, pip...done.

实测默认情况下虚拟环境不会依赖系统环境的global site-packages。比如系统环境里安装了MySQLdb模块,在虚拟环境里import MySQLdb会提示ImportError。如果想依赖系统环境的第三方软件包,可以使用参数–system-site-packages。此外,也可使用virtualenvwrapper的toggleglobalsitepackages命令控制当前环境是否使用global site-packages。

1
2
3
[root@localhost ~]# virtualenv --system-site-packages env1
New python executable in env1/bin/python
Installing setuptools, pip...done.

三、启动虚拟环境

进入虚拟环境目录,启动虚拟环境,如下:

1
2
3
4
[root@localhost ~]# cd env1/
[root@localhost env1]# source bin/activate
(env1)[root@localhost env1]# python -V
Python 2.7.8

此时命令行前面会多出一个括号,括号里为虚拟环境的名称。以后easy_install或者pip安装的所有模块都会安装到该虚拟环境目录里。

四、退出虚拟环境

退出虚拟环境:deactivate

1
2
(env1)[root@localhost env1]# deactivate
[root@localhost env1]#

五、使用virtualenvwrapper

virtualenvwrapper是virtualenv的扩展工具,可以方便的创建、删除、复制、切换不同的虚拟环境。

1.安装virtualenvwrapper

1
[root@localhost ~]# easy_install virtualenvwrapper

或者:

1
[root@localhost ~]# pip install virtualenvwrapper

创建一个文件夹,用于存放所有的虚拟环境:

1
[root@localhost ~]# mkdir ~/workspaces

设置环境变量,把下面两行添加到~/.bashrc里。

1
2
[root@localhost ~]# export WORKON_HOME=~/workspaces
[root@localhost ~]# source /usr/bin/virtualenvwrapper.sh

然后就可以使用virtualenvwrapper了。
2.创建虚拟环境:mkvirtualenv [虚拟环境名称]

1
2
3
4
5
6
7
[root@localhost ~]# mkvirtualenv env1
New python executable in env1/bin/python
Installing setuptools, pip...done.
(env1)[root@localhost ~]# mkvirtualenv env2
New python executable in env2/bin/python
Installing setuptools, pip...done.
(env2)[root@localhost ~]#

注意:mkvirtualenv可以使用virtualenv的参数,比如–python来指定python版本。创建虚拟环境后,会自动切换到此虚拟环境里。虚拟环境目录都在WORKON_HOME里。

3.列出虚拟环境:lsvirtualenv -b

1
2
3
(env2)[root@localhost ~]# lsvirtualenv -b
env1
env2

4.切换虚拟环境:workon [虚拟环境名称]

1
2
3
(env2)[root@localhost ~]# workon env1
(env1)[root@localhost ~]# echo $VIRTUAL_ENV
/root/workspaces/env1

5.查看环境里安装了哪些包:lssitepackages

6.进入当前环境的目录:cdvirtualenv [子目录名]

1
2
3
4
5
6
(env1)[root@localhost ~]# cdvirtualenv
(env1)[root@localhost env1]# pwd
/root/workspaces/env1
(env1)[root@localhost env1]# cdvirtualenv bin
(env1)[root@localhost bin]# pwd
/root/workspaces/env1/bin

进入当前环境的site-packages目录:cdsitepackages [子目录名]

1
2
3
4
5
6
(env1)[root@localhost env1]# cdsitepackages
(env1)[root@localhost site-packages]# pwd
/root/workspaces/env1/lib/python2.6/site-packages
(env1)[root@localhost site-packages]# cdsitepackages pip
(env1)[root@localhost pip]# pwd
/root/workspaces/env1/lib/python2.6/site-packages/pip

7.控制环境是否使用global site-packages:toggleglobalsitepackages

8.复制虚拟环境:cpvirtualenv [source] [dest]

1
2
3
[root@localhost ~]# cpvirtualenv env1 env3
Copying env1 as env3...
(env3)[root@localhost ~]#

9.退出虚拟环境:deactivate

10.删除虚拟环境:rmvirtualenv [虚拟环境名称]

1
2
[root@localhost ~]# rmvirtualenv env2
Removing env2...

【爬虫其实很简单】requests 与 beautiful soup基础入门

本篇教程内容完全针对初学者,如果你需要更进阶一点的知识,本篇可能给你的帮助十分有限

准备工作

首先确认代码环境,我们使用python来进行爬虫的开发。在这里我使用的版本是python3.5。这个教程应该适用于所有python3.x版本, python2.x可能做少许的改动就可以直接运行。

这次教程中我们要用到的模块是requests模块。如果没有安装requests模块的同学需要先安装一下。

Mac端的同学先打开terminal,Windows端的同学可以按下’win + r’后调出”运行”,然后输入cmd打开命令指示行。

【windows】按下win + r

【windows】打开cmd

【Mac】打开terminal

打开之后输入

pip install requests

来安装这个模块。

requests是一个非常方便的模块。可能你会看到有很多的代码在使用urllib的模块,这个教程没有使用这些模块的原因是因为它们相比较requests而言都比较复杂,作为一个初学者,我们没有必要一味的攀高。往往比工具更重要的是思想,我们学习的主要是思想,而非工具本身。真正的收获,一定是你忘记你的所有所学之后剩下的东西。

好了我们不说废话了,开始进入正题吧!

小试身手

我们先从简单的地方开始——爬取百度的首页。

打开python,输入下面的代码

import requests

r = requests.get('https://baidu.com')
print(r.text)

你看,百度的界面我们就已经拿到了

百度的网页文件

可能有的同学一开始这样爬会得到一个timeout的错误。如果出现了这样的情况,就是网站怀疑是一个机器人在访问自己,所以作出了一定的阻止。

那怎么办呢?没有关系,我们稍微修改一下我们的代码,改成

headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'}
r = requests.get('https://baidu.com', headers = headers)

headers的意思就是告诉网站,我们是一个正常的浏览器在给它发送信息,请它给我们正确的信息。

同样的,很多网站不需要登录,直接就可以访问其中的内容,比如糗事百科煎蛋网等等都可以直接爬取下来。

怎么样,是不是有一丝小小的成就感?

你可能就会问了,网页文件里面有那么多的无用信息,我们要怎么把它提取出来呢?

这个时候我们通常有两种做法,一种是正则表达式,一种是通过网页的结构对内容提取。

因为正则表达式相较后者更为复杂,对新手并不十分友好。所以我们这次的爬虫使用直接对网页的内容进行提取的方法来获取信息。如果你很想了解正则表达式的使用方式,你可以期待本教程的后续更新或者崔庆才老师博客中的正则表达式教程

Beautiful soup 的安装

Beautiful soup是另一个python的模块,我们将用这个模块来分解网页的结构,并对其中的内容进行提取。

同样的,Beautiful soup是一个第三方模块,我们需要使用

pip install beautifulsoup4

来对模块进行安装。

但是这还不够,Beautiful soup需要lxml包对文件进行处理,所以在安装完bs4之后你还需要安装lxml包:

pip install lxml

踏上正轨

在进一步讲Beautiful soup的使用之前,我们先分析一下要爬取的网页的结构,这样我们才能更加有效的针对网页的结构对网页的内容进行提取。

这里我们以糗事百科为例进行讲解。

第一件事仍然是我们先把它的页面爬取下来,也就是

import requests


headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'}
r = requests.get('http://www.qiushibaike.com', headers = headers)
content = r.text
print(content)

可以看到网页的内容已经被我们储存到了content变量中,打印出来是这样的:

content

接下来我们来分析网站的结构。

可能你也发现了,直接使用我们打印出来的结果分析起来十分吃力。所以我们使用更加高效的工具——开发者工具(Developer tools)来进行分析。

通常来说任何一个浏览器都有开发者工具,这里我们以Chrome为例。

Mac端在打开糗事百科之后按下option+command+I, Windows端直接按下F12即可。

Developer tools

可以看到,只要我们鼠标移到对应的标签(HTML tag)上,chrome就会帮我们把标签里面包含的网页内容高亮出来。

我们要的内容很简单,就是里面的段子。所以我们右键点击段子所在的位置,点击审查元素(Inspect),chrome就会自动找到该内容对应的标签。

审查元素

可以看到我们要的段子的内容就储存在这个叫做span的标签中。

段子内容

我们再往上追寻,可以看到<span>标签是属于一个叫做<div class=”content”>的标签的。继续往上我们可以看到一个叫做<div class=”article block untagged mb15″ id =….>的标签。

<div class=”article block untagged mb15″ id =….>

点击旁边的小三角,合并标签里面的内容之后我们可以看到有非常多这样格式的标签。而且每一个标签都对应了一个段子。

有很多这样的标签

所以很显然,我们只要把这样的标签都提取出来,我们就可以得到糗事百科中的段子了。

所以现在我们明确了方向——把所有class为article block untagged mb15的div标签找到,然后获取里面span标签的内容。这就是我们要找的段子了。

那要怎么写呢?

首先我们把我们需要的内容转换到Beautiful soup中。

# 引入Beautiful Soup包
from bs4 import BeautifulSoup  

# 把刚刚保存在content中的文件放入Beautiful Soup中
soup = BeautifulSoup(content, 'lxml')

你可能会奇怪后面的’lxml’是什么意思。其实这是因为我们的content是一个字符串(string)数据,它并不是网页文件。所以这里我们告诉Beautiful soup说你就把他当一个网页文件来处理就行。

到目前为止, 我们已经把网页的内容放入了Beautiful soup中,接下来就是施展Beautiful soup的魔法,把网页分成一块块的内容了。

施展魔法

注意,在进行下一步之前你应该确认一下目前我们的代码是这样的:

import requests
from bs4 import BeautifulSoup


headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'}
r = requests.get('http://www.qiushibaike.com', headers = headers)
content = r.text
soup = BeautifulSoup(content, 'lxml')

还记得吗?我们分析的结果是说所有的段子都在网页中class为article block untagged mb15的div标签中的span标签中。看起来好像有点复杂,没事,我们一步一步来做。

首先我们分解出所有class为article block untagged mb15标签:

divs = soup.find_all(class_ = 'article block untagged mb15')

我们可以打印出divs看看是什么样子的。

print(divs)

divs

可以看到,所有div的标签都已经储存在divs里面了。

在进行下一步之前我们再确认一下,这个时候你的代码应该是这个样子的:

import requests
from bs4 import BeautifulSoup


headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'}
r = requests.get('http://www.qiushibaike.com', headers = headers)
content = r.text
soup = BeautifulSoup(r.text, 'lxml')

divs = soup.find_all(class_ = 'article block untagged mb15')
print(divs)

接下来我们要做的事情就是把这些div里面的span都取出来。

我们先把最后一行去掉,避免不必要的打印。然后提取出每个div里面的span

for div in divs:
    joke = div.span.get_text()
    print(joke)
    print(‘------’)

注意,这个时候你的代码看起来应该是这样的:

import requests
from bs4 import BeautifulSoup


headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'}
r = requests.get('http://www.qiushibaike.com', headers = headers)
content = r.text
soup = BeautifulSoup(r.text, 'lxml')

divs = soup.find_all(class_ = 'article block untagged mb15')

for div in divs:
    joke = div.span.get_text()
    print(joke)
    print('------')

这段代码的意思就是把divs中的每个div都取出来(还记得吗,divs里面有所有的class为article block untagged mb15的div)。取出来之后我们对它说,你把你里面叫做span的标签的文字都给我吧。于是我们就把这里面的笑话都放进了joke当中,并打印了出来。

运行一下程序,可以看到你已经成功把糗事百科首页上面的所有段子爬下来了!

你成功了!

恭喜你已经成功入门了python的爬虫。你现在可以给自己鼓鼓掌::__IHACKLOG_REMOTE_IMAGE_AUTODOWN_BLOCK__::12

爬虫并没有那么难,对吗?

one more thing

我们把打印的内容拉到最后面,发现一些读不通的语句:

第三行不知道在说什么

我们回到糗事百科的首页看看

原来是有图片

原来是有图片,怪不得光看字看不懂。那我们的爬虫现在还不能爬下来图片,那有没有什么办法让这些莫名其妙的话都删掉呢?

我想你也应该想到了,同样的,我们去分析网页的结构,然后告诉python,如果存在带有图片的网页结构,我们就不打印这个段子。

我们打开开发者工具。(你还记得快捷键吗?)然后右键点击图片,审查元素。

打开开发者工具

我们看到,图片的网页标签(HTML tag)是img,所以我们只要在代码中检测div中是否有img标签,我们是不是就知道是不是要打印这条段子了呢?

别急,我们先看看把div里面的img都打印出来是什么样子的。

for div in divs:
    # 在这里我们找到所有的img标签,然后打印
    print(div.find_all('img'))  
    joke = div.span.get_text()
    print(joke)
    print('------')

几乎每一条里面都有图片

看来不行, 我们看到几乎每一条里面都有图片。我们回到chrome再看看div里面的结构,原来图片不只段子里面的图片,还包括了发帖人的头像,评论区的点赞图标等等。

那看来仅仅是看是否img标签来判断还是不够的,那我们就只好再看看别的结构,看看有没有更有效的结构。

段子图片的img标签再往上找几层我们不难发现,它们都存在一个<div class=”thumb”>的标签之下。而那些没有图片的段子就没有<div class=”thumb”>这个标签。

所以你成功发现了解决的方法——只要找每个总的div里面是否有<div class=”thumb”>标签就知道这个段子里面是否包含图片了。

那我们继续修改我们的循环:

for div in divs:
    if div.find_all(class_ = 'thumb'):
        continue
    joke = div.span.get_text()
    print(joke)
    print('------')

if div.find_all(class_ = 'thumb')的意思就是检查div.find_all(class_ = 'thumb')中有没有找到class为thumb的标签,如果找到了,那就说明我们不打印这一段,所以执行continuecontinue的意思就是跳到循环末尾,直接进入下一层循环,中间的代码都不要了,所以我们的代码最后看起来是这样的:

import requests
from bs4 import BeautifulSoup


headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'}
r = requests.get('http://www.qiushibaike.com', headers = headers)
content = r.text
soup = BeautifulSoup(r.text, 'lxml')

divs = soup.find_all(class_ = 'article block untagged mb15')

for div in divs:
    if div.find_all(class_ = 'thumb'):
        continue
    joke = div.span.get_text()
    print(joke)
    print('------')

运行一下,可以发现我们已经已经看不到有图片的段子了。

非常的干净

恭喜你,你已经学会了如何去分析网页的结构,这是非常重要的一步,学会分析的方法比学会任何工具都要有用。

而且你做的非常好!你现在可以去喝一杯咖啡,吃点饼干,休息一下。

如果你精力还很充沛,不妨思考一下,能不能把每个段子的作者,点赞数,评论数都提取出来呢?

举一反三:爬取我网站所有的文字title

import requests
from bs4 import BeautifulSoup


headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'}
for num in range(1,19):
        print("Page",num)
        url='http://teach.shconstant.cn/?paged=%d' %(num)
        r = requests.get(url, headers = headers)
        content = r.text
        soup = BeautifulSoup(content, 'lxml')

        divs = soup.find_all(class_='entry-title')

        for div in divs:
                article = div.a.get_text()
                print(article)
                print('------')

LNMP搭建WordPress博客

几经折腾,我的个人博客终于搭建完成!

环境

1.nginx-1.10.2

2.php-7.0.17

3.mysql-5.6.17

4.wordpress-4.7.3

一、nginx

  • 安装

执行以下指令安装Nginx:

yum install nginx

  • 配置

使用nginx -v指令检查Nginx是否安装完成。然后打开Nginx配置文件:


    vi /etc/nginx/nginx.conf
  server {
        listen       80 default_server;  //监听端口
        listen       [::]:80 default_server;
        server_name  teach.shconstant.cn;  //服务器访问地址
        root         /usr/share/nginx/html;  //服务器根目录

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {  //服务器根目录访问映射路径
            root /usr/share/nginx/html/blog;
            index index.php index.html index.htm;  //首页
        }

        error_page 404 /404.html;
            location = /40x.html {
            root /usr/share/nginx/html;
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
            root /usr/share/nginx/html;
        }

        rewrite /wp-admin$ $scheme://$host$uri/ permanent;
        location ~ \.php$ {  //解析访问php文件时处理规则
            root /usr/share/nginx/html/blog;
            fastcgi_pass 127.0.0.1:9000;  //php-fpm
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
        }
    }
  • 权限设置

访问服务器地址,会出现Access Denied,403Forbidden禁止访问,我们还需要修改服务器访问目录权限


    chown -R nginx:nginx /usr/share/nginx/html/blog
    chmod -R 774 /usr/share/nginx/html/blog

nginx:nginx为Linux用户和用户组,后文配置php-fpm时将创建。

  • SELinux设置(selinux一般是关闭的,所以这一步可以忽略)为了能完整使用wordpress读写博客、安装主题插件功能还需要修改SELinux安全上下文以拥有对目录文件的读写权限:
        setsebool -P httpd_read_user_content 1
        setsebool -P httpd_enable_homedirs 1
        chcon -R -t httpd_sys_rw_content_t /usr/share/nginx/html/blog

    二、MySQL

    • 安装

    CentOS7以前可以安装MySQL,但是在CentOS7中MySQL由MariaDB替代,大致还是相同的安装方式:

    
        yum install mariadb mariadb-server   
        或
        yum install mysql mysql-server
    
    • 配置

    安装完成后,拷贝配置文件至/etc/my.conf,若已存在my.conf直接覆盖:

    
        cp /usr/share/mysql/my-huge.cnf /etc/my.cnf
    
    • 创建数据库

    随后给数据库创建用户,输入指令:

    
        mysql_secure_installation
    

    按照提醒依次输入用户名、密码,对于其他询问可以直接确定,到最后创建账户成功。

    
        mysql -u root -p
    

    输入之前创建的用户名和密码登录数据库,创建一个wordpress数据库,数据库名可以自定义:

    
        create database wp_db
    

    use wordpress切换至该数据库,创建连接该数据库的账号:

    
        grant all privileges on wp_db.* to wpadmin@localhost identified by "wp123456"
    
    • 权限

    修改数据库文件权限:

    
        chown mysql:mysql /var/lib/mysql -R
    

    三、PHP

    • 安装
    
        sudo yum -y install php php-fpm php-mysql php-gd php-ldap php-odbc php-pear php-xml php-xmlrpc php-mbstring php-snmp php-soap curl
    
    
        sudo yum -y install epel-release
    
    • 配置

    打开php-fpm配置文件:

    
        vi /etc/php-fpm.d/www.conf
    

    找到对应owner,user,group,修改为nginx用户和nginx用户组:

    
        listen.owner = nginx
        listen.group = nginx
        listen.mode = 0666
        ...
        user = nginx
        group = nginx

    然后激活nginx用户:

    
        usermod -s /bin/bash username
    

    也可以直接修改文件:

    
        cat /etc/passwd
    

    发现它的shell是“/sbin /nologin”,需要将起改成“/bin/bash”。

    • 配置php.ini打开php.ini配置文件:
    
        vi /etc/php.ini
    

    找到open_basedir所在行,此参数规定php所能运行的目录,若不修改该值,访问nginx服务器将报Access Denied错误;将该参数值修改为服务器访问目录或者直接注释该行。

    • 启动启动php-fpm:
    
        systemctl start php-fpm
        systemctl enable php-fpm    
        //设置开机自启动php-fpm

    四、WordPress

    下载WordPress安装包,可以直接wget获取也可以ftp上传,解压到/usr/share/nginx/html/blog,访问install.php即进行安装:

  • 给配置文件wp-config-sample.php改名字为:wp-config.php,并修改配置文件
  • /**WordPress数据库的名称 */
     23 define('DB_NAME''wp_db');
     24 
     25 /** MySQL数据库用户名 */
     26 define('DB_USER''wpadmin');
     27 
     28 /** MySQL数据库密码 */
     29 define('DB_PASSWORD''wp123456');
     30 
     31 /** MySQL主机 */
     32 define('DB_HOST''localhost');
  • 图形界面配置安装:URL访问:

http://teach.shconstant.cn/wp-admin/install.php——安装界面

直至安装完成!

 

搭建自己的Shadowsocks服务器

一、安装shadowsocks

yum install python-setuptools && easy_install pip
pip install shadowsocks

二、创建配置文件

vim /etc/shadowsocks.json
{
"server":"your_server_ip",
"server_port":8388,
"password":"yourpassword",
"timeout":300,
"method":"aes-256-cfb",
"fast_open":false,
"workers": 1
}
代码中各字段的含义:
server:服务器 IP地址 (IPv4/IPv6)

server_port:服务器监听的端口,一般设为80,443等,注意不要设为使用中的端口

password:设置密码,自定义

timeout:超时时间(秒)

method:加密方法,可选择 “aes-256-cfb”, “rc4-md5”等等。推荐使用 “rc4-md5”

fast_open:true 或 false。如果你的服务器 Linux 内核在3.7+,可以开启 fast_open 以降低延迟。

workers:workers数量,默认为 1。

备注:如要你需要分享SS服务给朋友或家人,可以配置多个SS账户,具体可以参考下面的代码。
{
"server":"your_server_ip",
"port_password":{
     "8381":"pass1",
     "8382":"pass2",
     "8383":"pass3",
     "8384":"pass4"
     },
"timeout":60,
"method":"rc4-md5",
"fast_open":false,
"workers":1
}

启动

ssserver -c /etc/shadowsocks.json -d start
或不需要配置文件
sudo ssserver -p 443 -k password -m rc4-md5 --user nobody -d start

关闭

ssserver -d stop

日志文件

/var/log/shadowsocks.log

帮助

ssserver -h
参照相关文档 
 https://github.com/shadowsocks/shadowsocks/wiki/Shadowsocks-%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E 
 http://yanyu.farbox.com/post/build-high-performance-shadowsocks-server