普通视图

发现新文章,点击刷新页面。
昨天以前首页

为什么应该阻止 ChatGPT 和 Bytedance 爬虫抓取你的页面?


这几天,我发现我的一两个服务器过载(高于平常的CPU使用率),我查看了 Apache 日志,发现 ChatGPT Bot(也称为 GPTBot/1.0)和字节跳动 Bots(也称为 Bytespider)的访问记录。

您可以通过以下 BASH 命令检查访问您服务器的前 10 个 IP:

#!/bin/bash

awk '{a[$1]++}END{for(v in a)print v, a[v]}'  /var/log/apache2/*.log* | sort -k2 -nr | head -10
bytedance-bots-crawling-apache2-logs 为什么应该阻止 ChatGPT 和 Bytedance 爬虫抓取你的页面? ChatGPT (OpenAI) LINUX 折腾 资讯 运维

字节跳动 Bots(Bytespider)访问日志(Apache2)

gptbot-crawling-apache2-logs 为什么应该阻止 ChatGPT 和 Bytedance 爬虫抓取你的页面? ChatGPT (OpenAI) LINUX 折腾 资讯 运维

ChatGPT Bots(GPTBot)访问日志(Apache2)

为什么应该阻止 ChatGPT 和字节跳动 Bots 抓取您的页面?

ChatGPT还有字节跳动都有自己的大模型,他们就是通过抓取你的数据来喂他们的LLMs(大型语言模型)。这些 bots 免费使用您的材料(信息或数据)。它们给您的服务器增加了额外的负担,这是可以避免的。

我不喜欢它们从我的网站获取信息,白撸我的羊毛,但如果您觉得无所谓,可以将它们列入白名单。

如何阻止ChatGPT和字节跳动的爬虫抓取您的页面?

使用 robots.txt 阻止

一种比较软性的阻止方式是在网站根目录的 robots.txt 文件中添加以下内容:

User-agent: GPTBot
Disallow: /

User-agent: Bytespider
Disallow: /

然而,这些爬虫可能选择不遵守这些规则。比如百度爬虫就不遵守。

使用 CloudFlare 的 WAF 规则阻止

另一种更强硬的方法是通过添加一些防火墙规则来阻止它们,例如,您可以添加一个 CloudFlare WAF 规则来阻止它们:

cloudflare-waf-block-gpt-and-bytespider-bots 为什么应该阻止 ChatGPT 和 Bytedance 爬虫抓取你的页面? ChatGPT (OpenAI) LINUX 折腾 资讯 运维

添加 Cloudflare WAF 安全规则以阻止 GPTBot 和 Bytespider Bot 的访问。

比如还可以在表达式编译器(Expression Editor)里加入其它限制:

(http.user_agent contains "GPTBot") or 
(http.user_agent contains "Bytespider") or 
// 可以根据需求加入其它限制,比如限制 Amazonbot
(http.user_agent contains "Amazonbot") or 
// 访问 WordPress 博客访问评论链接
(http.request.uri contains "?replytocom=")

使用 HTTP 头阻止

您可以通过在服务器配置中设置适当的 HTTP 头来阻止特定的用户代理。以下是如何在 htaccess)加速网站”>Apache 和 Nginx 服务器上实现这一点:
对于 Apache,在您的 .htaccess 文件中添加以下内容:

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTP_USER_AGENT} GPTBot [NC,OR]
  RewriteCond %{HTTP_USER_AGENT} Bytespider [NC]
  RewriteRule .* - [F,L]
</IfModule>

对于 Nginx 服务器,在您的 Nginx 配置文件中添加以下内容:

if ($http_user_agent ~* (GPTBot|Bytespider)) {
    return 403;
}

使用自定义中间件阻止

如果您对应用程序的服务器端代码有控制权,您可以编写中间件来阻止这些用户代理。

在 Express(Node.js)中的示例:

app.use((req, res, next) => {
  const userAgent = req.headers['user-agent'];
  if (/GPTBot|Bytespider/i.test(userAgent)) {
    res.status(403).send('Forbidden');
  } else {
    next();
  }
});

在 Django(Python)中的示例:

from django.http import HttpResponseForbidden

class BlockBotsMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        user_agent = request.META.get('HTTP_USER_AGENT', '')
        if 'GPTBot' in user_agent or 'Bytespider' in user_agent:
            return HttpResponseForbidden('Forbidden')
        return self.get_response(request)

使用这些方法的组合可以有效地阻止 GPT-4 和 ByteSpider bots 访问您的网站。在服务器级别的阻止(通过 HTTP 头、防火墙规则或 WAF)与 robots.txt 指令结合使用可以提供更强大的解决方案。

英文:Why and How You Should Stop the ChatGPT and Bytedance Bots Crawling Your Pages?

本文一共 702 个汉字, 你数一下对不对.
为什么应该阻止 ChatGPT 和 Bytedance 爬虫抓取你的页面?. (AMP 移动加速版本)

扫描二维码,分享本文到微信朋友圈
75a5a60b9cac61e5c8c71a96e17f2d9c 为什么应该阻止 ChatGPT 和 Bytedance 爬虫抓取你的页面? ChatGPT (OpenAI) LINUX 折腾 资讯 运维
The post 为什么应该阻止 ChatGPT 和 Bytedance 爬虫抓取你的页面? first appeared on 小赖子的英国生活和资讯.

相关文章:

  1. 按揭贷款(房贷,车贷) 每月还贷计算器 去年给银行借了17万英镑 买了20万7500英镑的房子, 25年还清. 前2年是定率 Fix Rate 的合同 (年利率2.49%). 每个月大概是还 700多英镑. 有很多种还贷的计算方式, 定率/每月固定 是比较常用的. 简单来说就是 每个月交的钱是...
  2. 你要找什么样的老婆? 找媳妇的标准 昨天和网友在剑桥面基, 网友奔现, 他从爱尔兰过来, 小我12岁, 就聊到了找对象的标准. TLDR; 找老婆不要(只)看颜值, 而要注重性格, 为人处事和顾家等更重要的品质, 当然性和谐也很重要. 在当今社会, 人们对于找伴侣的标准有所不同. 有些人认为颜值是最重要的, 因为外貌吸引力可以让人在日常生活中感到愉悦, 这是人的本性,...
  3. 在LINUX下循环备份的方法 备份是我们常需要做的事, 你可以在服务器上有一个文件夹专门用于存放备份.然后定期删除(可以是一个脚本定期执行),这样就比较麻烦,因为如果你想每次删除比较旧的备份, 你就得对备份进行时间倒序. 其实可以完全利用LINUX下的 date命令来生成想要的文件名用于备份.比如你想保留过去的 24 小时备份,那么,你可以用: 1 2 H=`date +"%H"` ls > backup_$H  #...
  4. HPZ800服务器主板太老不支持超过2TB的大硬盘 我家里一直用的是HPZ800服务器, 很吵, 很老, 虽然这台服务器已经有十年之久(我在EBAY上买来用了五年多了), 但是即使放到今天, 这服务器速度依旧很快, 很稳定. 由于服务器用的是ECC较验内存, 所以基本上不重启关机. HPZ800主机有两个硬核CPU – 因特志强 X5650 – 每个CPU是12核....
  5. 智能手机 HTC One M9 使用测评 虽然我对手机要求不高, 远远没有像追求VPS服务器一样, 但是怎么算来两年内换了四个手机, 先是三星 S4 用了一年多, 然后 Nokia Lumia 635 Windows Phone, 后来又是 BLU, 半年多前换了...
  6. 把年假分成几周请完 – 工作不是全部 我的工作合同里写着 一年享有 25年工作日 带薪假期 这是比较好的福利之一. 搬家的时候请了三天 还有就是零零散散请了几天 比如 看GP 等等. 每年假期可以有 5天能移到 下一年使用 所以我就把剩下的请了 但是是每周请一天...
  7. ChatGPT-4 使用 Math Wolfram 插件解决数学脑筋急转弯问题 这篇文章, 我们看一个简单的数学问题(脑筋急转弯), 并用 Python 解决它. 我们看一下LLM(大型语言模型): ChatGPT3.5和ChatGPT4. 通过 ChatGPT-Plus 订阅(目前每月 20 美元 + VAT增值税), 我们可以启用...
  8. AI 美女视频 – 抖音网红要失业了? 随着 ChatGPT 全网爆火, 这一两个月AI技术的发展真是日新月异, 一两天就有搞出个新名堂, 都有点试玩不动了. 推特上有日本人通过AI搞出了美女视频. 是不是已经很真实了, 我感觉再这么下去抖音网红要失业了. AI做美女图已经相对很成熟了, 比如 Stable.Diffusion, MidJounery (见视频 Youtube,...

实时关注豆瓣租房信息,几行代码帮你轻松搞定

作者 lolilukia
2020年2月23日 15:58

现代年轻人的日常生活已经离不开互联网,无论是订机票,点外卖还是网购,本质上,我们都已经习惯从互联网获取信息,并从中筛选、鉴别,作出决策。

但有时,如何从浩瀚的信息之海找到我们所需要的东西,则是一个大问题。这时,技术就派上了用场。

设想这样一种场景,你租住的房子很快就要到期,可你却诸事缠身,没办法花费诸多精力寻找合适的房源。你第一时间想到了房屋中介,但又投鼠忌器,害怕自己的个人信息被人不经意间「分享」,你还希望直接和一房东对话,找一套直租房源。

你想到了论坛,你看到了密密麻麻的帖子,并从中仔细挑选符合你期望的房源。结果你发现,看了半天,满意的似乎并不多,只能再刷刷看有没有新发布的帖子。

生活中诸如此类的情景还有很多,其实,在精力有限的情况下,可以让你的电脑替你去论坛搜索所期望的信息,收集打包并呈现在你眼前。

下面以租房和寻找二手物品为例,介绍我们是如何用简单的方法筛选出相关信息并进行定时更新的。

豆瓣小组获取租房信息

豆瓣上有很多专门的租房小组,尽管这些年也逐渐「沦陷」为房屋中介的战场,但由于历史悠久,我们还是能从中筛选出合适房源。

接下来的尝试,我们以「上海租房」小组为例,从该主页可以看到,相同类型的小组不少,当然也适用于这个方法。

图片
豆瓣「上海租房」小组首页

知己知彼,百战不殆。在抓取该页面信息之前,我们先来看看页面结构是怎样的。

点击豆瓣页面中的「更多小组讨论」后,会发现帖子标题涵盖了我们关心的地铁线路站名以及周边位置等信息。因此,我们的目标就可以概括为定时获取包含某些关键字的帖子标题以及链接并去重。

图片
小组讨论帖标题的关键词

「人生苦短,我用 Python」,我们的这个小工具就是基于 Python 3 实现的。而且方便的是,小组讨论不必登录就可以浏览,这就省去了模拟浏览器登录的麻烦。

安装 python

首先,我们需要 安装 Python ,详细方法可见这篇教程。建议使用 3.x 版本,毕竟今年 1 号起, 2.X版本官方都停止维护了。

Windows 下载安装包后,运行安装即可。

终端处输入 Python 显示版本信息则表示安装成功。

图为在 Windows cmd 中的效果。

图片
cmd 中输入 python 查看版本

虽然 Python 以短小精悍闻名,但我们还是想再精简下工作量,我们使用 Scrapy 框架来抓取网页上的信息,Scrapy 是 Python 的一个知名第三方爬虫库,Windows 平台可以直接通过安装Python后自带的 pip 安装,一行命令解决。

pip install Scrapy

但 Mac OS 系统自带的 Python 2.7 会和 Scrapy 产生冲突,Mac OS 用户建议使用 virtualenv 在虚拟环境中进行安装。 都安装完毕后,就可以创建项目了。

创建项目

我们创建一个用以提取信息发送邮件的项目,将其命名为 ForumSpider。新建项目,首先 cd 到相应的目录,执行如下的命令:

scrapy startproject ForumSpider

一个初始的 Scrapy 项目就生成了,下图是这个项目的目录结构,由于我们实现的功能比较简单,可以暂时不用关心其他文件,我们只需在 settings.py 中进行简单设置,然后在 spiders 目录下定义一个我们自己的爬取工具就够用了。

图片
scrapy 项目结构

首先,我们需要在 settings.py 中设置 USER_AGENT,即用户代理,

User Agent中文名为用户代理,简称 UA,是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等

简而言之,这就是客户机器的身份标识。我们需要设置此项以便能够隐藏机器的身份,不容易被网站拒绝。settings.py 中已经自带了一些配置。在浏览器中按下 F12,选择 Network 标签页,随意点击一个链接,就可以从 Header 中获取 USER_AGENT:

图片
查看 User Agent

将其替换 settings.py 中的 USER_AGENT:

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
图片
修改配置

另外,我们选择遵循 Robots 规则

robots.txt是一种存放于网站根目录下的ASCII编码的文本文件,它通常告诉网络搜索引擎的漫游器(又称网络蜘蛛),此网站中的哪些内容是不应被搜索引擎的漫游器获取的,哪些是可以被漫游器获取的。

Robots.txt中定义了我们可以爬取的范围,符合对应该网站的爬取规范,以避免不必要的爬虫风险。之后,我们就可以新建一个工具定义我们的爬取规则。在此之前,我们需要从网站中找寻一定的规律来编写我们的脚本,我们打开刚才的「更多小组讨论」的帖子列表页面,观察 url 的规律,下图分别是第一页的 url 和第二页的 url,可以看出,分页参数 start 代表开始的元素编号,每页 25 个帖子:

图片
第 0 -25 个帖子的 url
图片
第 25 -50 个帖子的 url

了解了每次爬取的 url 的变化规律,接下来我们需要了解爬取内容的 DOM 树结构,进入控制台,选择 Elements 标签页,使用旁边的选择器定位标题所在的结构:

图片
定位标题所在元素的操作
图片
标题所在的 a 标签

我们发现,整个列表是在一个名为 olt 的 class 中呈现的,标题所在的 class 名为 title,并且其中的超链接标签中包含了我们需要的所有信息,标题和链接。由于页面中可能包含有多个名为 title 的 class,因此我们将其父级元素 olt 同时作为条件选择以便更方便地定位。

回到刚才的项目,我们此时需要新建一个名为 douban 的爬取工具:

scrapy genspider douban "douban.com"

douban.com 是我们设定的爬取域,生成的文件如图所示:

图片
工具主函数

start_urls 代表了爬取的 url,但实际上我们如果需要爬取多个页面的话, url 则是动态的。因此我们可以将 allowed_domains 和 start_urls 变量删去,用 start_requests 方法来动态生成爬取的 url:

def start_requests(self):
    for i in range(0, 5 * 25, 25):
        url = 'https://www.douban.com/group/549538/discussion?start={page}'.format(page=i)
        yield scrapy.Request(url=url, callback=self.parse)

这个方法的功能就是循环爬取 start=0 到 start=100 的页面内容,每次共爬取 5 页,爬取时调用 parse 中指定的规则。 在刚才我们探索页面结构的基础上,parse 方法定义为:

def parse(self, response):
    for title in response.css('.olt .title'):
        yield {'title': title.css('a::text').getall(), 'link': title.css('a::attr(href)').getall()}

这个方法的含义是获取 olt 的子元素 title 下的 a 标签的文本和 href 属性,即内容和链接。getall 代表获取符合上述条件的所有元素的内容和链接。 到这里,爬取的功能已经全部编写完毕了,一共是 7 行代码。但我们所需要的功能是在获取到新发布的帖子的信息时,收到推送或提醒。Scrapy 中内置了 mail 模块,可以很轻松地实现定时发送邮件的功能。那我们可以考虑先把爬取到的信息存储到文件中进行分析,再将由关键词筛选得到的信息与上一次筛选过后的信息进行比较,如果存在更新,就更新存储筛选信息的文件,并发送邮件。我们可以用以下的命令来将爬取到的信息输入到 JSON 文件中:

scrapy crawl douban -o douban.json

既然需要定时执行,那我们就需要在根目录中创建一个 douban_main.py,用 time 库编写一个简单的定时器,用以爬取之前清空存储爬取信息的文件,并每 21600 秒(6 个小时)执行一次爬取分析:

import time, os
while True:
    if os.path.exists("douban.json"):
        with open("douban.json",'r+') as f:
            f.truncate()
    os.system("scrapy crawl douban -o douban.json")
    time.sleep(21600)

最后一步,就是筛选信息并发送邮件了,发送邮件需要引用 MailSender 类:

from scrapy.mail import MailSender

首先,我们要确保发送邮件的邮箱 SMTP 服务开启,并获取授权码,以 QQ 邮箱为例:

图片
开启 POP3 / SMTP 服务及 IMAP / SMTP 服务

获取授权码之后,配置 MailSender 实例:

mailer = MailSender(
    smtphost="smtp.qq.com",
    mailfrom="xxxxxxxxx@qq.com",
    smtpuser="xxxxxxxxx@qq.com",
    smtppass="16 位授权码",
    smtpssl=True,
    smtpport=465
)

最后,我们需要指定一些关键词,为了便于理解,匹配的写法比较简易,注重性能的朋友们可以使用正则匹配。注意每次分析完毕之后,我们将迄今为止出现的符合关键词的信息写入到 douban_store.json 中,并在新信息出现时保持更新。这个过程写在爬虫程序结束之后调用的 close 方法中。附上 douban.py 的所有内容:

# -*- coding: utf-8 -*-
import scrapy, json, os
from scrapy.mail import MailSender
class DoubanSpider(scrapy.Spider):
    name = 'douban'
    def start_requests(self):
        for i in range(0, 5 * 25, 25):
            url = 'https://www.douban.com/group/549538/discussion?start={page}'.format(page=i)
            yield scrapy.Request(url=url, callback=self.parse)
    def parse(self, response):
        for title in response.css('.olt .title'):
            yield {'title': title.css('a::text').getall(), 'link': title.css('a::attr(href)').getall()}
    def close(self):
        mailer = MailSender(
            smtphost="smtp.qq.com",
            mailfrom="xxxxxx@qq.com",
            smtpuser="xxxxxx@qq.com",
            smtppass="xxxxxxxxxxxxx",
            smtpssl=True,
            smtpport=465
        ) # 配置邮箱
        obj_store, new_info = [], []
        key_words = ['枫桥路', '曹杨路', '11 号线']
        if os.path.exists("D:\\ForumSpider\\douban_store.json"):
            with open("D:\\ForumSpider\\douban_store.json", 'r') as f:
                obj_store = json.load(f)  # 读取之前爬取的符合关键词的信息
        with open("D:\\ForumSpider\\douban.json", 'r') as load_f:
            load_dict = json.load(load_f)
            for info in load_dict:
                content = info["title"][0].replace('\n', '').replace('\r', '').strip() #按标题进行筛选
                for k in key_words:
                    if k in content:
                        tmp = {"title": content, "link": info["link"][0]}
                        if tmp not in obj_store: # 如果之前的爬取没有遇到过,则加入到新信息列表
                            new_info.append(tmp)
                            obj_store.append(tmp)
        if len(new_info) > 0:
            with open("D:\\ForumSpider\\douban_store.json", 'w') as writer:
                json.dump(obj_store, writer) # 更新到旧信息列表
            return mailer.send(  # 发送邮件
                to=['lolilukia@foxmail.com'],
                subject='【豆瓣脚本】上海租房',
                body='\n'.join([str(x['title'] + ':' + x['link']) for x in new_info])
            )                        

运行 douban_main.py 即可定时运行这个信息爬取脚本:

python douban_main.py

包含主函数,这个脚本一共 51 行,现在已经能满足使用需要,当然还可以进一步精简优化。执行脚本之后,很快我就收到了第一封邮件:

图片
租房信息爬取结果邮件

上述脚本适用于所有豆瓣小组,稍改改动优化过后也可以应用于获取留学信息、追星八卦等等方面。

场景 2:获取二手物品信息

上述的场景适用于不需要登录就能查看信息的一些网站,然而大多数情况下,更多的信息需要登录之后才能查看。很多网站登录的时候使用了验证码,扫码等策略避免自动登录,cookie 的模拟登录方式又极容易过期,使用简单的策略爬取网站信息似乎有些困难,下面以 v2ex 论坛为例,介绍另一种爬取网页信息的半自动方法。

为何称为半自动方法呢,进入 v2ex 的登录页,我们发现登录框的下方需要输入验证码,如果我们需要模拟登录的话,可能还需要写一个模式识别的程序,甚至比我们浏览论坛的时间成本还高。如果能够人工输入一次验证码,然后让程序自动定时爬取,好像也可以接受。这样的话,我们可以采用模拟人工操作浏览器行为的框架 selenium。

selenium 依旧可以使用 pip 来进行安装:

pip install selenium

selenium 3 之后需要单独安装浏览器驱动,因此我们需要下载 geckodriverchromedriver

,其他浏览器需要安装对应的驱动),并将它们都加入到环境变量 PATH 中。

首先,我们先使用 selenium 调用浏览器,打开 v2ex 的登录页面:


from selenium import webdriver
sigin_url = 'https://www.v2ex.com/signin'
driver = webdriver.Chrome('D:\\chrome_driver\\chromedriver.exe')
driver.get(sigin_url)

以下是运行效果:

图片
selenium 运行效果

接下来,我们需要自动填充用户名和密码,然后等待我们人工输入验证码进入论坛。我们还是使用 CSS Selector 的方式定位元素,找到用户名和密码所在的输入框:

图片
查看输入框的 DOM 树结构

我们发现这两个输入框没有标识 id,也没有特别的 class 名称,因此我们可以使用 find_elements_by_css_selector 返回这一类元素的列表,幸运的是登录页一共只有 3 个输入框,因此我们可以通过索引迅速锁定它们,并填充我们的用户名密码。当然这里也可以用 tag 来定位:

user_name = driver.find_elements_by_css_selector('.cell .sl')[0]
user_name.send_keys('v2ex 用户名')
user_pwd = driver.find_elements_by_css_selector('.cell .sl')[1]
user_pwd.send_keys('v2ex 密码')

运行效果如下:

图片
打开页面自动输入用户名和密码

验证码需要我们自行输入,为了让程序等待我们输入完毕验证码并点击登录按钮之后再进行爬取,我们设定一个 while 循环,当页面跳转到论坛列表页,出现特定元素时跳出:

while True: # 等待人工输入验证码
    table = driver.find_elements_by_id('Tabs')
    if len(table) != 0:
        break

其余的逻辑与场景 1 大抵相仿,在此不多加赘述。模拟浏览器行为的写法比较简单,访问页面时调用形如 driver.get(url) 的方法即可,抓取的写法也很好理解,只是由于调用了浏览器,爬取速度会稍慢。不过这也无妨,我们要做的就是在点击登录按钮之后等待邮件即可。由于这个场景不再使用 Scrapy 进行抓取,发送邮件我们改用 Python 内置的 smtplib 和 email 模块,进行简单的配置(16 位授权码的获取方式参见场景 1):

import smtplib
from email.mime.text import MIMEText
from email.header import Header
sender = 'xxxxxx@qq.com'
subject = '【v2ex 脚本】二手交易'
smtpserver = 'smtp.qq.com'
passcode = '场景 1 出现过的 16 位授权码'

然后需要构造一个 MIMEText 实例,用以定义发送的内容、发件人、收件人和主题等等:

msg = MIMEText(body, 'html', 'utf8')
msg['From'] = sender
msg['To'] = sender
msg['Subject'] = Header(subject, charset='utf8')

这里的 body 就是我们筛选出的新信息的字符串,发送邮件的过程也十分简单:

smtp = smtplib.SMTP()
smtp.connect(smtpserver)
smtp.login(sender, passcode)
smtp.sendmail(sender, sender, msg.as_string())

如果需要多次运行,则可以使用 JSON 文件记录筛选过的信息,如果仅运行一次,将 obj_store 放置在 while 循环外即可。注意尽量避免较短时间内多次进行登录操作,否则可能会被封 IP。另外,如果新增回复,链接会发生变化,因此此处只判断 title 是否出现过。附上 v2ex_main.py 的所有内容:

from selenium import webdriver
import time, os, json
import smtplib
from email.mime.text import MIMEText
from email.header import Header


sender = 'xxxxxxxxx@qq.com'
subject = '【v2ex 脚本】二手交易'
smtpserver = 'smtp.qq.com'
passcode = '16 位授权码'


sigin_url = 'https://www.v2ex.com/signin'
driver = webdriver.Chrome('D:\\chrome_driver\\chromedriver.exe')
driver.get(sigin_url)
user_name = driver.find_elements_by_css_selector('.cell .sl')[0]
user_name.send_keys('v2ex 用户名')
user_pwd = driver.find_elements_by_css_selector('.cell .sl')[1]
user_pwd.send_keys('v2ex 密码')
while True: # 等待人工输入验证码
    table = driver.find_elements_by_id('Tabs')
    if len(table) != 0:
        break
key_words = ['mbp', 'AirPods', '触摸板']
obj_store = []
while True:
    new_info = []
    for i in range(0, 5):
        driver.get('https://www.v2ex.com/go/all4all?p={page}'.format(page=i+1))
        items = driver.find_elements_by_css_selector('.item_title a')
        for item in items:
            for k in key_words:
                if k in item.text:
                    tmp = {'title': item.text, 'link': item.get_attribute('href')}
                    if tmp['title'] not in obj_store:
                        new_info.append(tmp)
                        obj_store.append(tmp['title'])
    if len(new_info) > 0:
        body = '\n'.join([str(x['title'] + ':' + x['link']) for x in new_info])
        msg = MIMEText(body, 'html', 'utf8')
        msg['From'] = sender
        msg['To'] = sender
        msg['Subject'] = Header(subject, charset='utf8')
        smtp = smtplib.SMTP()
        smtp.connect(smtpserver)
        smtp.login(sender, passcode)
        smtp.sendmail(sender, sender, msg.as_string())
        smtp.close()
    time.sleep(1800)

爬取的过程如下图所示:

图片
整体运行效果

切记不要关闭浏览器,随后会收到一封来自脚本的邮件:

图片
二手信息爬取结果邮件

总结

以上仅是相应于场景提出的小规模样例,生活中其实有相当多的应用,比如最近一段时间抢购口罩等等。这样的小工具能够一定程度上提高我们生活的效率,避免花费不必要的时间。

最后,虽然网页爬虫能够给我们的生活带来一定的便利,免去人工筛选信息的烦恼,但还是要注意道德与法律的边界,防止带来一系列负面影响。

❌
❌