最近朋友拜托我写一个实时爬虫,提醒她某人是否更新消息,作为一个爬虫小白,上网搜了一下资料,三天完成代码和部署,以下作记录贴,堤防遇到的坑,如果大家有更好的想法也欢迎提出!

整体思路

鉴于只是简单的应用,所以没有花费很多时间在图像识别上,直接调用的图鉴提供的接口进行识别,模拟人手抖动避免检测,利用虾推啥来进行微信消息提醒,其他就是一般爬虫的过程,获取网页html,使用BeautifulSoup进行html解析。

爬虫整体代码

# -*- coding: utf-8 -*-
"""
Created on Sat Aug 27 20:31:11 2022@author: JShawn
"""import time, random
from PIL import Image
import requests, json, base64
from selenium import webdriver
from selenium.webdriver.common.by import By
from urllib.request import urlretrieve
from selenium.webdriver.common.action_chains import ActionChains
#爬取数据使用到的库
import requests #虾推啥使用库
import bs4 #网页解析
from bs4 import BeautifulSoup
import re #正则表达式,文字匹配
import urllib #制定url
import sqlite3 #SQL操作class Douban():def __init__(self):self.url = "https://www.douban.com/"# 这里配置驱动参数,如增加代理和UA信息opt = webdriver.ChromeOptions()# 增加代理和UA信息# opt.add_argument('--proxy-server=http://223.96.90.216:8085')opt.add_argument('--no-sandbox')opt.add_argument('--disable-dev-shm-usage')opt.add_argument("--remote-debugging-port=9222")  # thisopt.add_argument('--headless') #浏览器不提供可视化页面. linux下如果系统不支持可视化不加这条会启动失败opt.add_argument('--disable-gpu')opt.add_argument("window-size=1024,768")opt.add_argument('--user-agent=' + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36")# 创建webdriver实例self.driver = webdriver.Chrome("/usr/bin/chromedriver/chromedriver",chrome_options=opt)#该处需要填chromedriver绝对路径才可以运行!def base64_api(self, img):# 图鉴官方提供的接口,这里稍微修改了下,因为自己使用就直接把账号密码放进去了with open(img, 'rb') as f:base64_data = base64.b64encode(f.read())b64 = base64_data.decode()data = {"username": "******", "password": '******', "typeid": 33, "image": b64}result = json.loads(requests.post("http://api.ttshitu.com/predict", json=data).text)if result['success']:return result["data"]["result"]else:return result["message"]return ""def input_username_password(self):# 实现访问主页,并输入用户名和密码self.driver.get(self.url)time.sleep(1)self.driver.save_screenshot("0.jpg")iframe = self.driver.find_element(By.TAG_NAME, 'iframe')  # 主代码在iframe里面,要先切进去self.driver.switch_to.frame(iframe)  # 切到内层time.sleep(0.5)self.driver.find_element(By.CLASS_NAME, 'account-tab-account').click()  # 模拟鼠标点击time.sleep(0.2)self.driver.find_element(By.ID, 'username').send_keys('******')  # 模拟键盘输入time.sleep(0.1)self.driver.find_element(By.ID, 'password').send_keys('******')  # 模拟键盘输入time.sleep(0.2)self.driver.find_element(By.CSS_SELECTOR, '.btn-account').click()def get_img(self):"""获取验证码原图,并获得偏移量和偏移:return:"""time.sleep(1)iframe = self.driver.find_element(By.TAG_NAME, 'iframe')  # 验证码仍然代码在iframe里面,要先切进去self.driver.switch_to.frame(iframe)  # 切到内层time.sleep(0.5)# 获取验证码图片style_str = self.driver.find_element(By.ID, 'slideBg').get_attribute('style')# 获取样式字符串,将该字符串转化为字典style_dict = {i.split(':')[0]: i.split(':')[-1] for i in style_str.split('; ')}# 组装图片地址src = "https://t.captcha.qq.com" + style_dict['background-image'][6:-2]# print(src)# 将图片下载到本地urlretrieve(src, 'douban_img1.png')# 返回网页图片的宽和高return (eval(style_dict['width'][1:-2]), eval(style_dict['height'][1:-3]))def get_distance(self, a, b):# 实现图片缩放captcha = Image.open('douban_img1.png')x_scale = captcha.size[0] / ay_scale = captcha.size[1] / b(x, y) = captcha.sizex_resize = int(x / x_scale)y_resize = int(y / y_scale)"""Image.NEAREST :低质量Image.BILINEAR:双线性Image.BICUBIC :三次样条插值Image.ANTIALIAS:高质量"""img = captcha.resize((x_resize, y_resize), Image.ANTIALIAS)img.save('douban_img2.png')time.sleep(0.5)# 使用云打码获取x轴偏移量distance = self.base64_api(img='douban_img2.png')return distancedef get_track(self, distance):"""计算滑块的移动轨迹"""# 通过观察发现滑块并不是从0开始移动,有一个初始值18.6161a = int((eval(distance) - 18.6161)/4)# 构造每次的滑动参数# 注意这里的负数作用:1.为了模拟人手,2.以上计算很多取了约数,最终结果存在误差,但误差往往在一定范围内,可以使用这些数值简单调整。track = [a, -2.1, a, -1.8, a, -1.5, a]return trackdef shake_mouse(self):"""模拟人手释放鼠标抖动"""ActionChains(self.driver).move_by_offset(xoffset=-0.4, yoffset=0).perform()ActionChains(self.driver).move_by_offset(xoffset=0.6, yoffset=0).perform()ActionChains(self.driver).move_by_offset(xoffset=-1.1, yoffset=0).perform()ActionChains(self.driver).move_by_offset(xoffset=0.9, yoffset=0).perform()def operate_slider(self, track):# 定位到拖动按钮slider_bt = self.driver.find_element(By.CLASS_NAME, 'tc-slider-normal')# 点击拖动按钮不放ActionChains(self.driver).click_and_hold(slider_bt).perform()# 按正向轨迹移动# move_by_offset函数是会延续上一步的结束的地方开始移动for i in track:ActionChains(self.driver).move_by_offset(xoffset=i+0.3, yoffset=0).perform()self.shake_mouse()  # 模拟人手抖动time.sleep(random.random() / 100)  # 每移动一次随机停顿0-1/100秒之间骗过了极验,通过率很高time.sleep(random.random())# 松开滑块按钮ActionChains(self.driver).release().perform()time.sleep(4)def login(self):"""实现主要的登陆逻辑:param account:账号:param password: 密码:return:"""self.input_username_password()time.sleep(0.5)# 下载图片,并获取网页图片的宽高a, b = self.get_img()# 计算滑块的移动轨迹,开始拖动滑块移动print('a:'+str(a))print('b:'+str(b))self.operate_slider(self.get_track(self.get_distance(a, b)))# 输出登陆之后的cookies
#        print(self.driver.get_cookies())time.sleep(0.5)self.driver.save_screenshot("douban.jpg")def __del__(self):"""调用内建的稀构方法,在程序退出的时候自动调用类似的还可以在文件打开的时候调用close,数据库链接的断开"""print("del函数调用")self.driver.close()#初始化数据库,传入数据库的路径,若存在连接,否则建立数据库def init_db(self,dbpath):sql = '''create table if not exists 'notice_info'(id text,content text,href text,date text)'''connect = sqlite3.connect(dbpath)  # 打开或创建数据库c = connect.cursor()  # 获取游标c.execute(sql)  # 执行SQL语句connect.commit()  # 提交事务connect.close()  # 关闭# 得到一个URL的网页内容,并进行异常捕捉def askURL(self,url):head = {  # 用户代理,告诉服务器我们可以接收什么水平的内容'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/''104.0.0.0 Safari/537.36'}request = requests.get(url, cookies=self.regroup_cookies(),headers=head)  # 生成请求#已经确定request.content可以返回html内容return request.content# 提取网页的最新广播,主要使用bs4def dataExtarct(self,html):bs = BeautifulSoup(html, "html.parser")  # 解析文档,作为解析器#日志idid_list=bs.find_all('div',attrs={'class':'status-item'})#日志链接href_list=bs.find_all('div',attrs={'class':'hd'})#日志内容content_list=bs.find_all('div',attrs={'class':'status-saying'})date_list=bs.find_all('span',attrs={'class':'created_at'})
#try:content=content_list[0].find('p').textexcept:content="无文字"mydata = {"href": href_list[0]['data-status-url'],"id": id_list[0]['data-sid'],"content": content,"date": date_list[0]['title']}return mydatadef insert_data(self,mydata, connect):sql = "insert into notice_info(id, content, href, date) values('" + mydata["id"] + "', '" + mydata["content"] + "', '" + mydata["href"] + "', '" + mydata["date"] + "');"c = connect.cursor()c.execute(sql)connect.commit()  # 提交事务connect.close()  # 关闭#将信息存入数据库,如果此次搜索数据库无信息就提醒,有就忽略def save_data(self,mydata, dbpath):sql = "select * from notice_info where id = '" + mydata["id"] + "';"print(sql)connect = sqlite3.connect(dbpath)  # 打开或创建数据库c = connect.cursor()  # 获取游标cursor = c.execute(sql)  # 执行SQL语句result = 0print("数据库"+str(cursor))for row in cursor:print(row)result += 1if result == 0:self.insert_data(mydata, connect)return 1else:return 0# 利用吓推啥,将最新消息推送到微信上# 主要是获取微信的tokendef sendMessage(self,token, mydata):baseurl = "http://wx.xtuis.cn/"url = baseurl + token + ".send"data = {"text": '******',"desp": '内容:' + mydata["content"] + '<br>' \'更新时间:' +mydata["date"]}print(requests.post(url, data=data))#爬取个人主页信息,并与数据库进行比对def track_information(self):#数据库地址dbpath="douban.db"#微信在虾推啥上的tokentoken="******"self.init_db(dbpath)url="https://www.douban.com/people/******/statuses"
#        print(self.askURL(url))mydata=self.dataExtarct(self.askURL(url))flag=self.save_data(mydata,dbpath)print(flag)if flag==1 :self.sendMessage(token,mydata)#登录后获取的cookies需要重新组合def regroup_cookies(self):         cookies = self.driver.get_cookies()  # listcookie_dict = {}for item in cookies:cookie_dict[item['name']] = item['value']print(cookie_dict)return cookie_dictif __name__ == "__main__":douban = Douban()  # 实例化douban.login()  # 之后调用登陆方法douban.track_information()#爬取个人主页信息

Centos部署

选择服务器

因为不需要太多内存和CPU,我在腾讯云的优惠专区,购买了一个最便宜的轻量应用服务器,选择了centos7的系统

安装finalshell

finalshell是一个SSH连接工具,可以连接到自己的云服务器,通过终端输入命令的方式执行操作,并且对于文件的增删改查十分方便。 下面给出了下载地址:
Windows版下载地址
Mac版,Linux版安装及教程
首先点击左上角的文件夹图标,打开连接管理器,再按下图点击第一个按钮。

新建的连接框中填入图中的信息,即公网IP,用户名和密码,名称可自定义。

上传爬虫和依赖库安装

服务器在之前已经安装了必要的环境,但爬虫所用到的一些第三方库还没有安装,因此需要手动安装需要的库。通过输入以下指令,即可安装爬虫所需要的第三方库。注意该版本需要python3.+进行编译,在腾讯云服务器中自带python3编译器,但在下载依赖库时,需要注意命令全部都为pip3

Linux下安装第三方库的命令,注意为pip3

pip3 install beautifulsoup4
pip3 install pysqlite3
sudo pip3 install selenium

下面还有比较复杂的库,我会贴出之前的教程,大家遇到对应的问题可以去参考一下

Centos安装Pillow(PIL)

https://blog.csdn.net/lbxoqy/article/details/121008085

Centos7安装chrome和chromedriver

一定要安装对应版本的chrome和chromedriver!而且在代码中要使用chromedriver的绝对路径,否则会找不到驱动!
https://blog.csdn.net/zulien/article/details/84990436

Tips

我在运行的时候在使用del稀构方法关闭chromedriver一直有问题,报错:

ImportError: sys.meta_path is None, Python is likely shutting down

如果遇到这样的错误,close()替换成quit()或者将quit()替换成close()

定时任务

在经过以上步骤后爬虫已经能够成功在服务器上运行,但未实现实时执行的要求。所谓实时,就是使用定时器每隔一段时间执行一次python脚本,这里用到了Linux系统的crontab指令,即定时任务。
crontab教程
在本次部署的步骤:

1.vim /ect/crontab 进入一般模式,即上图所示
2.按i进入编辑模式后,将光标移动到下方的波浪号处
3.黏贴已经写好的命令 */30 * * * * root /home/lighthouse/douban/task.sh 这里需要给出脚本文件的绝对路径和用户名,我的用户为root
4.按esc退出编辑模式,再输入 :wq! 强制保存文件并退出
5.输入 /etc/init.d/cron restart 重启程序 ,若不存在该指令,也可以输入
/sbin/service crond restart 重启服务

shell脚本:

#!/bin/sh. /etc/profile
. ~/.bash_profilepython3 /home/lighthouse/douban/douban.py
killall -9 chrome

因为我稀构方法里无论写driver.close()还是driver.quit()都没办法关闭chromedriver,这样会影响之后爬虫的运行,所以在脚本中使用了killall -9 chrome来杀死所有chrome进程(很糙的办法,如果有更好的方法欢迎补充!)。另外,在使用crontab定时运行shell脚本的时候遇到了无法正常执行的问题,参考了下面的文章:https://magician.blog.csdn.net/article/details/84394809
在#!/bin/sh后面添加了两行代码,restart crontab之后终于运行成功了!

Python爬虫爬取个人主页信息(拖拽验证码验证)+Linux部署相关推荐

  1. 用python爬虫爬取微博信息

    用python爬虫爬取微博信息 话不多说,直接上代码! import requests from bs4 import BeautifulSoup from urllib import parse i ...

  2. python爬虫爬取房源信息

      目录 一.数据获取与预处理 二.csv文件的保存 三.数据库存储 四.爬虫完整代码 五.数据库存储完整代码 写这篇博客的原因是在我爬取房产这类数据信息的时候,发现csdn中好多博主写的关于此类的文 ...

  3. 复工复产,利用Python爬虫爬取火车票信息

    文章目录 Python 爬虫操作基本操作 python 标准库 urllib 获取信息 上传信息 python 标准库 urllib3 获取信息 上传信息 第三方库 requests 获取特征信息 模 ...

  4. python 爬虫爬取小说信息

    1.进入小说主页(以下示例是我在网上随便找的一片小说),获取该小说的名称.作者以及相关描述信息 2.获取该小说的所有章节列表信息(最重要的是每个章节的链接地址href) 3.根据每个章节的地址信息下载 ...

  5. python爬虫爬取网页信息

    爬虫流程:准备工作➡️爬取网页,获取数据(核心)➡️解析内容➡️保存数据 解析页面内容:使用beautifulsoup定位特定的标签位置,使用正则表达式找到具体内容 import导入一些库,做准备工作 ...

  6. python爬虫爬取华硕笔记本信息

    之前一个朋友麻烦我帮他爬取一下华硕笔记本信息,最后存储为一个csv格式的文件,文件格式为"系列 型号".本文为本人实现该爬虫的心路旅程. 目录 一.获取系列信息 1. 爬虫可行性分 ...

  7. 四小时学python爬虫爬取信息系列(第一天)

    四小时学python爬虫爬取信息系列(第一天)(全是干货) 1.安装requests库(可以在电脑python,我是进入anaconda我建的虚拟环境) anaconda虚拟环境法流程: conda ...

  8. python爬虫爬取当当网的商品信息

    python爬虫爬取当当网的商品信息 一.环境搭建 二.简介 三.当当网网页分析 1.分析网页的url规律 2.解析网页html页面 书籍商品html页面解析 其他商品html页面解析 四.代码实现 ...

  9. Python爬虫爬取链家网上的房源信息练习

    一 原链接:用Python爬虫爬取链家网上的房源信息_shayebuhui_a的博客-CSDN博客_python爬取链家 打开链家网页:https://sh.lianjia.com/zufang/  ...

  10. python爬虫爬取微信公众号小程序信息

    python爬虫爬取微信公众号小程序信息 爬取内容 某汽车维修信息提供的维修店名称,地点以及电话(手机)号码 爬取步骤 啥也别管,先抓包看看,在这里,博主使用的抓包软件是charles 抓包:将网络传 ...

最新文章

  1. 【转】PBR基于物理的渲染
  2. MSB8036 The Windows SDK version 10.0 was not found. Install the required version of Windows SDK o
  3. 五、朴素贝叶斯分类算法
  4. 分布式锁-常用技术方案
  5. Java常用类集接口以及实现方式总结
  6. 使用delphi 开发多层应用(十)安全访问服务器
  7. va_list和vsnprintf、getopt
  8. 接口监控_java应用监控之利用cat接口性能优化,每一次都是血的教训
  9. numpy 中np.max--求序列的最大值和np.maximum--X和Y逐位进行比较,选择最大值
  10. github—本地域名配置方式
  11. 添加CAB最大压缩到右键菜单
  12. QList、QVector、QMap容器类
  13. opencv-Mat数据类型及位数总结
  14. win10更新 vm14用不了
  15. 怎么删除映射网络里的计算机,如何映射网络驱动器 删除映射网络驱动器的方法...
  16. linux安装i3wm桌面环境,ArchLinux + i3wm 桌面 Windows10 双系统安装(重点记录)
  17. Maxcomputer使用实例
  18. 10个免费图片站点(2020年最新)
  19. 2021年域名买卖会有哪些骗局?
  20. 现在的区块链现况技术如何?

热门文章

  1. WinCC V7.2学习记录
  2. ios微信消息自动朗读_如何使您的iOS设备大声朗读文章,书籍和更多内容
  3. svn 服务器ip地址变更
  4. 科技论文写作经验之谈
  5. 针对Win10 Tensorflow-2.x 训练 线程冻结(假死、卡住、几个epoch后、中途停滞、CPU占用0%) 等问题的排查总结
  6. 开源中国携 200 万开发者开始真正的软件众包
  7. 微软拼音输入法调整状态栏水平/垂直选项失效解决办法
  8. [漏洞分析] CVE-2021-3560 PolKit条件竞争本地提权分析
  9. python一阶差分_如何用Python对数据进行差分
  10. 国外5G行业应用产业政策分析及对我国的启示