前几天买了云服务器,这几天安装个python3环境,跑个selenium

 

1 一个结合文件发送,命令行,监控一体化的链接工具支持跨平台      http://www.hostbuf.com/?install_fs

按照顺序双击即可

 

 

 

2 命令行安装python(root身份),命令完全兼容centos7.6  https://www.linuxidc.com/Linux/2018-07/153286.htm

 

3 安装虚拟环境,此处有些小插曲,记录如下

安装虚拟机必要环境

可以先更新下pip

pip install --upgrade pip

sudo pip install virtualenv

sudo pip install virtualenvwrapper

安装结束就启动虚拟环境(如果不行可以重复操作)

source virtualenvwrapper.sh

创建虚拟环境(py3_flask是虚拟环境名字)

mkvirtualenv -p python3 py3_flask

查看虚拟环境(可用tab按钮,快捷方便)

workon py3_flask

退出虚拟环境

deactivate

删除虚拟环境(先退出才能删除)

rmvirtualenv py3_flask

查看虚拟环境新安装的包

pip freeze

 

4 这几天用本地软件跑selenium,网络不稳定,我都忘了我还有个云主机闲着。今天部署下

  安装chrome

  yum install https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm

  查看版本

  在上面有 83.0.4103.116-1    

  下载chromedriver找对应版本        https://npm.taobao.org/mirrors/chromedriver/

  wget http://npm.taobao.org/mirrors/chromedriver/83.0.4103.39/chromedriver_linux64.zip

  

  将下载的文件解压,放在如下位置
  unzip chromedriver_linux64.zip
  mv chromedriver /usr/bin/
  赋予权限

  chmod +x /home/mysoft/spyder/chromedriver

  

  编辑py文件  此处给出一个可以正常运行的文件示例

  

#! /usr/bin/python3

from selenium import webdriver

chrome_options = webdriver.ChromeOptions()

# 不加载图片,加快访问速度
chrome_options.add_experimental_option("prefs", {"profile.mamaged_default_content_settings.images": 2})

# 此步骤很重要,设置为开发者模式,防止被各大网站识别出来使用了Selenium
chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])

chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--disable-dev-shm-usage')
browser = webdriver.Chrome(options=chrome_options)
url = "https://www.baidu.com/"
browser.get(url)
html = browser.find_element_by_xpath("//*").get_attribute("outerHTML")
print(html)
print("-----------------------------------")

  

记录几个报错

chrome not run,,,,,, 可能是chromeoption设置不好,参照以上代码

 No such file or directory   xxxx   可能是没有权限 chmod u+x xxxx

如果还有其他不可描述的错误。比如语法没错,但是就是通不过,可能是python缩进有问题,花费两三分钟统一下格式

 查看正在运行的python程序  ps -ef | grep python

找到进程id 杀死进程      kill -9 4394

 

selenium的键盘按键的正确用法   https://www.jianshu.com/p/56e1295b031f  

eg:driver.find_element_by_id('DomainName').send_keys("{ENTER}")

 记录几个xpath的操作

    driver.find_element_by_id('DomainName').clear()
time.sleep(0.2 * random.random())
driver.find_element_by_id('DomainName').send_keys("%s.com\n" % (li))
driver.find_element_by_id('DomainName').send_keys("{ENTER}")

WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.CLASS_NAME, 'search-write-btn')))
# tag_element = driver.find_element_by_class_name('search-write-btn')
# ActionChains(driver).move_to_element(tag_element).perform().click()
time.sleep(0.5 + 0.2 * random.random())
# driver.find_element_by_class_name('search-write-btn').click()
# js ="document.getElementByClass('search-write-btn').click()"  # js点击元素
# driver.execute_script(js)

# 显示等待知道元素出现
WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.CLASS_NAME, 'search-write-btn')))
html = driver.find_element_by_xpath("//*").get_attribute("outerHTML")

write_to_html(str(i),html)
result = driver.find_element_by_xpath("//*[contains(text(), '未被注册')]") 

 

记录几个刷新界面的方法 https://www.cnblogs.com/MasterMonkInTemple/p/4097512.html

在linux编程中,如果文件中用到当前目录,则应该cd   到指定目录下,不然程序会报路径找不到错误,另一种解决方式是在程序中获取当前路径,然后拼接

python中出现invalid syntax报错的几种原因

缩进不对,或者符号错误(某些无法描述的错误就是缩进不对)

目前还有一个奇葩错误 

list' object has no attribute 'get'

问题是我用的是drivert.get(url)  并不是获取elements元素导致的错误,

解决方法:将except中异常处理的代码(driver.get(url))想办法放到try中。

某次点击按钮无法使用,解决办法:在输入框后面拼接字符串"\n"          不知为何,在win中运行很好,但是在linux下各种报错。

 

注意下try except用法,注意可能是哪个地方出错了,

注意只对绝对有异常的地方进行try 。。。。except  pass。。。。。。。可以选择什么也不处理

(比如某元素找不到,程序会报异常进而终止运行,这时候必须try上,保证程序整体运行)

注意如果有需要,可多层嵌套try except 对于不同层侧的异常区别对待

注意  if a and b:pass else: 与  if a:  if b:pass  (a)else: 是不一样的

注意 如果比较某字符串相等,从字面看绝对没有不一样的,但是就是不相等,可能是utf8自动加载的字符bom等,处理方式编码方式修改为utf8-mas,或者,首行空一行

 

 

2020.07.13 18:00 继续记录bug

1 异常报错,网上说是文件开头没写# -*- coding: utf-8 -*-等编写方法导致错误,但是我修改了编码之后还是错,加上还是错,修改了编译环境还是错,修改了运行环境还是错

解决办法:可能是pycharm开的编译运行环境太杂乱导致,先关闭所有项目,然后关闭pycharm,然后关闭重启pycharm,,,,,,好了

2 driver获取元素必须先获取element,在获取信息,不方便,可以用lxml解析,具体步骤,lxml只识别文本,得先将driver转成str格式才能被解析

3 可以先用try xpath插件写语法,进行检测,推荐火狐浏览器安装try xpath,其他的我找不着

  https://www.w3school.com.cn/xpath/xpath_syntax.asp

   from lxml import etree
   time.sleep(0.1 + 0.5 * random.random())
    html = driver.find_element_by_xpath("//*").get_attribute("outerHTML")
    html = etree.HTML(html)
    urls = html.xpath("//*[@class='listBox2']/ul/li//h3/a/@href")
    texts = html.xpath("//*[@class='listBox2']/ul/li//h3/a/text()")

4 推荐个driver的写法,配置option使得可以无界面获取数据

def get_driver():
    chrome_options = webdriver.ChromeOptions()
    # 不加载图片,加快访问速度
    chrome_options.add_experimental_option("prefs", {"profile.mamaged_default_content_settings.images": 2})

    # 此步骤很重要,设置为开发者模式,防止被各大网站识别出来使用了Selenium
    chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])

    chrome_options.add_argument('--headless')
    chrome_options.add_argument('--no-sandbox')
    chrome_options.add_argument('--disable-gpu')
    chrome_options.add_argument('--disable-dev-shm-usage')
    #browser = webdriver.Chrome(executable_path="../chromedriver",options=chrome_options)#无界面的selenium
    browser = webdriver.Chrome(executable_path="../chromedriver")#有界面的selenium
    return browser

5 计算程序执行时间time.time()以秒为单位

6 复杂字符替换还是使用正则比较好  推荐菜鸟教程  https://blog.csdn.net/qq_20412595/article/details/82633501  group讲解比较详细

text = re.search(r"([0-9]*[-]?[0-9]*)(\S+)(大学排名|大学排行榜)", text_lis[i]).group(2)
url = re.search(r"../(\S+)", url_lis[i]).group(1)

7 找当前页面url    driver.current_url    判断当前页和下一页是否在同一个页面判断跳转是否成功

8 xpath中contains可以配合属性和text()使用,,注意加点异常捕获

    try:
        driver.find_element_by_xpath("//*[contains(@src, 'narNext.gif')]").click()
    except:
        pass

9 数组连接可以用join  

f.write(",".join(li))

10 正则表达式筛选中文,用group好点

text = "全国服装设计专业"
re.search(r"(全国|)(\S+)",text).group(2)

11 driver.get(url)即在原来的地址栏输入地址,  driver.execute_script(url)即新开一个窗口输入地址  刷新页面driver.refresh()  获取当前页面url   driver.current_url

12 driver切换窗口

#切换窗口到最近打开的那一个(实际是切换句柄)
driver.switch_to.window(driver.window_handles[-1])
# 等待窗口全部打开
webDriverWait(driver, 10).until(EC.new_window_is_opened(driver.window_handles))
# 创建一个新窗口
driver.execute_script("https://baike.baidu.com/")


13 记得在每次界面有刷新之后延时一小会儿,我这边服务器慢,我延时3-3.6s左右,具体情况,具体分析

14 打开一个新的界面之后记得先切换窗口句柄,不然不可能获取到指定页面的元素  

15 获取元素可能性很多,注意try except的嵌套使用

 16 重新修改print方法实现log日志  https://www.jianshu.com/p/d485bb30c5bb  (反正我一般不会用这种)  (下面链接时我见过说log日志最简洁的一篇博客)

https://mp.weixin.qq.com/s?src=11&timestamp=1594766431&ver=2461&signature=r5OfNsXrVLPm3ipxK0wbeoc2p4NPr7o9JQKoQgyRo8cuxcoMzYLX7zobIMpBg4q2hcrixANsnuhLcPl50smoCn0fKAbL0j7XiPVZusvDKY4D3OTImp41I50pUxFuX-vB&new=1
https://www.jb51.net/article/165167.htm
https://www.cnblogs.com/itBlogToYpl/p/12753067.html

17 我参考别人的log日志封装了一个日志类  

https://blog.csdn.net/weixin_33991727/article/details/93362394

  下面是我自己封装的log类,可以实现不同级别的log输出到不同的日志中

#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
该日志类可以把不同级别的日志输出到不同的日志文件中
'''

import os
import time
import logging
import inspect

handlers = {logging.NOTSET: "./tmp/TNLOG-notset.log",
logging.DEBUG: "./tmp/TNLOG-debug.log",
logging.INFO: "./tmp/TNLOG-info.log",
logging.WARNING: "./tmp/TNLOG-warning.log",
logging.ERROR: "./tmp/TNLOG-error.log",
logging.CRITICAL: "./tmp/TNLOG-critical.log"}

mylog = {
"info":"./tmp/TNLOG-mylog.log"
}
def createFile(filename):
path = filename[0:filename.rfind('/')]
if not os.path.isdir(path):
os.makedirs(path)
if not os.path.isfile(filename):
# 创建并打开一个新文件
fd = open(filename, mode='w', encoding='utf-8')
fd.close()


def createHandlers():
logLevels = handlers.keys()
for level in logLevels:
path = os.path.abspath(handlers[level])
createFile(handlers[level])
handlers[level] = logging.FileHandler(path)
myls = mylog.keys()
for myl in myls:
createFile(mylog[myl])

class TNLog(object):

def printfNow(self):
return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())

def __init__(self, level=logging.NOTSET):
# 加载模块时创建全局变量
self.__loggers = {}
logLevels = handlers.keys()
for level in logLevels:
logger = logging.getLogger(str(level))
# 如果不指定level,获得的handler似乎是同一个handler?
logger.addHandler(handlers[level])
logger.setLevel(level)
self.__loggers.update({level: logger})

def getLogMessage(self, level, message):
frame, filename, lineNo, functionName, code, unknowField = inspect.stack()[2]
'''日志格式:[时间] [类型] [记录代码] 信息'''
return "[%s] [%s] [%s - %s] %s" % (self.printfNow(), level, lineNo, functionName, message)

def info(self, message):
message = self.getLogMessage("info", message)
self.__loggers[logging.INFO].info(message)

def error(self, message):
message = self.getLogMessage("error", message)
self.__loggers[logging.ERROR].error(message)

def warning(self, message):
message = self.getLogMessage("warning", message)
self.__loggers[logging.WARNING].warning(message)

def debug(self, message):
message = self.getLogMessage("debug", message)
self.__loggers[logging.DEBUG].debug(message)

def critical(self, message):
message = self.getLogMessage("critical", message)
self.__loggers[logging.CRITICAL].critical(message)

def mymsg(self, message):
message = "[%s] %s\n" % (self.printfNow(), message)
path = mylog["info"]
with open(path, "a+", encoding='utf-8') as f:
f.write(message)

def logger():
createHandlers()
logger = TNLog()
return logger

if __name__ == "__main__":
logger = logger()
logger.debug("debug")
logger.info("info")
logger.warning("warning")
logger.error("error")
logger.critical("critical")
s = "检测结果 False 当前进度 5.597125720054636% 执行个数 1885 异常值个数 2726 当前检测 bgu "
logger.mymsg(s)
logger.mymsg(s)
logger.mymsg(s)

18  之前运行程序一直都是在前台,长循环程序总是莫名其妙退出,通过尝试,可以用shell脚本写个小脚本,省略那些麻烦的操作,执行某命令可以使得程序需后台运行,

这样就算本地断网也没关系啦。程序命名为xxx.sh

#!/bin/bash
# Your Answer
# filename: cd.sh
# chmod +x cd.sh
# ./cd.sh /var/www
cd /home/mysoft/spyder/choosecom/try32/
nohup  python3 /home/mysoft/spyder/choosecom/try32/try3.py > ./run.log 2>&1 &

2020 07 18 

19 今天继续爬虫,遇到一个问题,我xpath语法没错,在firefox上利用try xpath也可以获取,但是就是匹配不到,经过检查发现在模拟网页跳转之后,网页指针没有定位到当前页,导致页面元素获取不到。

因此在以后每次获取新页面并且要在新页面进行操作时,或者在当前页面关闭之后,可以加上

driver.switch_to.window(driver.window_handles[-1])
driver.close()
driver.switch_to.window(driver.window_handles[-1])  

20 经过摸索,我发现driver类似于单例模式,全局如果只是get一个出来,那全局都只会使用者一个driver,因此如果关闭当前页面一定要记得加上这么一句,反正不会错

driver.switch_to.window(driver.window_handles[-1])

21 记录一个/引发的血案。今天爬取学校数据意外发现学校名称部分是错误的,这个错误刚开始没有发现,知道抓取学校信息时候,在控制台看到这个问题。也就是说,之前爬取的数据都是错误的,必须有重新抓。

解决办法,因为学校这一栏标签内部还有标签,我在爬取的时候没注意。可以使用xpath中//尝试抓取。竟然成功了。。。。与之前相比就是多了一个/

# 之前的 
school = "".join(lis[0].xpath("./tr[%s]/td[3]/text()"%i))
# 现在的
school = "".join(lis[0].xpath("./tr[%s]/td[3]//text()"%i))

  

2020.07.20 记录几个写断点自动恢复的心得

22 注意每次用click之后要延时一会儿,可以用等待元素出现(隐式等待),或者直接暴力等待。

from lxml import etree
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains

webDriverWait(driver, 10).until(EC.new_window_is_opened(driver.window_handles))

23  我用的断点自动恢复的方法是将序号信息写入一个临时文件,命名为record,每次循环开始之前就从这个文件取序号数据(字符串格式)。循环用while来写,注意一般将循环加1操作放在循环最后,如果有特殊需要经过慎重考虑可以放在第一位,注意while的结束条件

24 如果是多重嵌套循环,一定注意,在内层循环结束之后,一定在外层将数据重新置零。不然错误不好找。(因为断点重传的变量在本方法内是全局变量)  

25 不知道之前写没写,linux服务器后台运行程序

cd /home/mysoft/spyder/major_sun/
nohup  python3 /home/mysoft/spyder/major_sun/sun_major_rank.py > ./run.log 2>&1 &

 

2020/07/24 23:00

26 今天写爬虫,重温自己的下一页框架,在此小结一个

  可以通过检测有点击下一页按钮,检测最新的driver与之前的driver的url是否相同,如果相同则说明已经到达最后一页,返回空,如果不一样,则返回driver。

  因此,此方法的首页必须单独处理

27 元素获取文本信息是ele.text属性,而不是ele.text()方法。

28 对于跨区域的元素的点击事件,如果确定其可以正常工作,则可以加try except

29 关闭多于窗口,可以先在最开始设置变量before_handle为当前窗口,后续打开再多窗口,只要这个窗口不关闭,其他都可以关闭。可以构建死循环,一直关闭最后一个窗口,直到窗口等于before_handle  。然后从0开始关闭,,,,具体使用自己定

 

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

  

 

 

 

 

 

 

 

 

  

 

posted @ 2020-07-13 10:29  小城熊儿  阅读(542)  评论(0编辑  收藏  举报