一个关于爬前程无忧岗位的脚本,陆陆续续写了好久,今天终于全部弄好,并部署到腾讯云上了。这里总结下我这段时间里写这个脚本碰到的问题和一些解决方案。
如何判断公司简称也在黑名单里
- 理想状态是能识别公司的名称的各种形式,简称,全称,关键词,但我实在不知道这个应该怎么实现。最后采取的是最简单的方案,对于抓取的每一个公司判断它在不在黑名单公司列表里,在的话,就从抓取结果中删除它。
发送邮件采用什么方法? 为什么yagmail我设置了不能发送邮件
发送邮件可以用smtplib库,参考《Python编程快速上手__让繁琐工作自动化》第16章
后来在网上发现一个更简洁的方法,用yagmail库,只需要三行代码就行了。很多东西这个库把你封装好了。
但是我在试验的过程中,一直碰到登陆不了,但是所有设置都是跟文档里一样的,后来在Stack Overflow上看到原来outlook邮箱需要多设置两个参数,smtp_starttls, smtp_ssl。但是这里文档里根本没有提到怎么设置。不过也是人家的库是专门针对gmail的,你拿来用第三方邮箱,也不能保证可用。
1
2
3
4# 报错
# SSL: UNKNOWN_PROTOCOL
yag = yagmail.SMTP(user='*****@outlook.com', password='*****', host='smtp.office365.com', port='587', smtp_starttls=True, smtp_ssl=False)
为什么我的脚本在ubunt上不能运行,报错的地方返回None type,而在mac上可以运行?
这个问题,真是让我抓狂。为什么明明一样的代码,到云服务器上就不行了,我也安装了脚本所需的环境。后来想到会不会是环境的版本问题。
电脑里的beautifulsoup4是4.5.3 lxml3.7.3 python3.6.1
ubuntu是4.6.0, lxml4.2.0 python3.5.2
但是讲道理,新版本的包会兼容旧版本的啊。但最后发现lxml3.7.3没问题。如果一定要用新版本的话,可以参考下面的解决方法。
首先确定我现在碰到的是什么问题?
为什么我的脚本在ubunt上不能运行,报错的地方返回None type,而在mac上可以运行?
- 经查发现是bsObj的获取不一样,对比后发现只抓取了前面一部分
- html获取正常,那就是bsObj=BeautifulSoup(html, “lxml”)问题了
- 任何HTML或XML文档都有自己的编码方式,比如ASCII 或 UTF-8,但是使用Beautiful Soup解析后,文档都被转换成了Unicode
- 改成html.parser后,虽然效率降低了,但不会信息丢失了
- 但是为什么呢?
- 出现解析后源码丢失的可能原因有 2 个:
- BeautifulSoup 有时候会遇到非法的,不支持的 html 源码而导致无法解析或无法正常解析 html;
- 处理的文档太大,而处理的解析器缓存不够造成的信息丢失。
这里换一个解析器,换成 html.parser 就可以了。
- 出现解析后源码丢失的可能原因有 2 个:
- 但是为什么呢?
- html获取正常,那就是bsObj=BeautifulSoup(html, “lxml”)问题了
- 经查发现是bsObj的获取不一样,对比后发现只抓取了前面一部分
最常见的异常现象是当前文档找不到指定的Tag,而这个Tag光是用眼睛就足够发现的了.
find_all()
方法返回 [] ,而find()
方法返回 None .这是Python内置解析器的又一个问题: 解析器会跳过那些它不知道的tag.解决方法还是 安装lxml或html5lib如果同样的代码在不同环境下结果不同,可能是因为两个环境下使用不同的解析器造成的.例如这个环境中安装了lxml,而另一个环境中只有html5lib, 解析器之间的区别 中说明了原因.修复方法是在
BeautifulSoup
的构造方法中中指定解析器
为什么邮箱发送,本地mac端可以,而服务器ubuntu上就不可以?
报错提示
1
smtplib.SMTPAuthenticationError: (535, b'5.7.3 Authentication unsuccessful [HK0P153CA0001.APCP153.PROD.OUTLOOK.COM]')
这个报错什么意思呢,是smtp认证错误,认证不成功
网上查了下大概都是说密码不对或者邮箱的stmp服务未开启,但是我在本地同样的代码可以发送邮件啊
是不是我之前操作的脚本,登陆了,没有退出?
搜索得到的答案大多都是账号密码啥的输错了,但我检查了好几十遍了,没有错啊。起初还以为是腾讯云封锁了25端口的原因,但是我用的是第三方邮件服务,是不受这25端口的影响的。
最后,还真让我在网上找到和我碰到同样问题的人。这里的回答是5.7.3报错是因为已验证的中继会话无法建立,因为此用户没有权限进行外部中继。差不多就是不能登陆邮箱。
1
2
3
4In the question, I noted that "It works in PowerShell". I ran WireShark on the Windows PC and ran the PowerShell commands again.
In the Wireshark session, I saw the same error "535 5.7.3 Authentication unsuccessful".
The PowerShell command (Send-MailMessage) ignores the error and continues to send the message (MAIL FROM, RCPT TO) and the message is delivered.
The issue here is that 5.7.3 can mean that an authenticated relay session cannot be established because this user does not have permissions to relay externally. However, you can run an anonymous relay session by ignoring the error and continuing to send the message.但是为什么呢,账号密码都是对的,还是不能登陆邮箱呢?我突然想登陆到outlook邮箱,看看发件箱有没有记录,结果在邮箱看到outlook给我发的警告邮件,原来是outlook限制我登陆了,异常登陆的地方太多😭。哎,在这里纠结了3个小时。
脚本定时启动,可以什么方法实现?
- 程序内部设置
- 直接暴力的,sleep
- 这种方法太消耗资源了,我这个脚本需要每天定时运行,采用这种方法的话,需要一直运行脚本
- 借用第三方库
- schedule
- celery分布式任务调度模块
- 需要一个消息中间件
- 直接暴力的,sleep
- 程序外部设置
- 借用系统定时计划功能
- crontab定时任务
- 借用系统定时计划功能
- 最后考虑到方便快捷为主,采用crontab定时
- 程序内部设置
crontab为什么运行了我的python脚本,但是没输出
原因:python里面有一个打开文本的操作,用的是相对路径,crontab执行路径暂时不知道,所以即使脚本执行用绝对路径,但是打开文本就会有问题。
解决方法:
- 最好用sh 再包一层,先cd到脚本所在目录,然后再执行,那么python脚本里面不管是相对路径还是绝对路径都可以。
- 在进行文件打开操作的时候,尽量都使用绝对路径,方法:先获取当前路径,再加起来。
所以我用shell来打开python脚本的路径,然后运行
我想在任何路径直接运行我的shell脚本,shell里脚本已经设置了环境变量,但为什么没有反应
经过参阅《鸟哥的私房菜》中的相关内容p.307,export和source,总结的知识点是:
1.自定义变量和环境变量的区别,两者的差异就在于是否会被子进程所继续引用
2.当你登陆Linux并取得一个bash之后,你的bash就是一个独立的进程,接下来你在这个bash下面执行的任何命令都是由这个bash所衍生的子进程,
3.子进程仅会继承父进程的环境变量,但不会继承父进程的自定义变量,当子进程返回时,父进程的自定义变量依然有效
4.要让子进程继承父进程的自定义变量,需要将自定义变量变成环境变量,使用export命令
5.source命令即点(.)命令。source命令是在当前进程中执行参数文件中的各个命令,而不是另起子进程(或sub-shell)。
exec命令也不产生新的子进程。那么exec与source的区别是什么呢?
exec命令在执行时会把当前的shell process关闭,然后换到后面的命令继续执行。
shell中source和sh script的区别
有两种方法执行shell scripts,一种是新产生一个shell,然后执行相应的shell scripts;一种是在当前shell下执行,不再启用其他shell。
新产生一个shell然后再执行scripts的方法是在scripts文件开头加入以下语句
#!/bin/sh
一般的script文件(.sh)即是这种用法。这种方法先启用新的sub-shell(新的子进程),然后在其下执行命令。
另外一种方法就是上面说过的source命令,不再产生新的shell,而在当前shell下执行一切命令。
问题分析:
环境变量(传给子进程的变量,遗传性是本地变量和环境变量的根本区别)只能单向从父进程传给子进程。不管子进程的环境变量如何变化,都不会影响父进程的环境变量。
你在shell中调用的脚本,然后在脚本中调用source,设置的环境变量只对当前的shell脚本所在进程及由这个脚本fork的子进程中有效
然后你在shell中做其他操作的时候,之后设置的环境变量就不起作用了。
我的解决方法是直接在
.bashrc
里添加了脚本目录路径在~路径下,bash 51job_searcher.sh 能运行脚本,但是crontab定时任务就是不能运行脚本
- 在
crontab -e
中设置时,设置脚本的绝对路径
- 在
为什么有的文章里说,执行shell脚本,需要赋予脚本可执行权限
source 命令是在当前的shell环境下执行脚本 ,不会创建子shell;
运行Shell脚本:
直接执行具有x权限的脚本文件:例如:./test.sh
使用指定的解释器程序执行脚本内容:例如:bash test.sh 、sh test.sh
用文本编辑器新建的文件是没有可执行的权限的,可用
chmod u+x filename
设置权限ll命令 文件之后带一个星号”*”表示这个文件是可执行文件
echo -e “Hello World! \a” 为什么在命令行里运行正常,在脚本里就有-e
因为ubuntu默认shell是dash,
sh filename.sh
里的第一个sh指的是dash,即使你脚本里指定了bash。如果要得到输出没有-e的结果,可以运行bash filename.sh
经验
- 大多数报错,你要好好研究报错提示,从上面找线索分析,而不是一头钻进搜索引擎里找答案。
- 不要过分追求完美,现已完成目标为任务
- 设置时间盒子,管理好时间,避免时间黑洞。