Python爬虫技术

爬虫技术概要

作者:@Galaxyzeta

0 摘要

大数据时代背景下,数据分析的价值极具应用价值,大数据分析无处不在,例如淘宝网的商品推荐,用户画像等。与此同时,网络数据量多而错综复杂,如何从如此多的网页中提取数据,成为了数据分析的前提,是其中最重要的步骤之一。本文通过作者个人的Python爬虫案例和项目经验,由浅至深地向读者介绍如何高效地从网页中分析数据特征,绕过常见反爬机制,提取数据,整理和分析数据。读者在阅读本文后并动手实践后,能够入门爬虫技术并达到爬虫技术的中级水平。

备注:本文编写过程仓促,且作者水平不高,出现错误在所难免,希望得到指正。

关键词:

爬虫,反爬,Python,Session,Cookie,Request,Response,自动化,Ajax,Json,CSS选择器,Beautifulsoup,ChromeDriver, 正则表达式

爬虫技术概要0 摘要1 准备工作1.1 安装必要环境1.2 安装必要包1.3 部分名词解释2 爬虫入门实战2.1 访问网页2.2 分析网页结构2.3 解析网页数据2.5 新的困境2.5.1 初级反爬机制2.5.2 爬取复杂数据3 数据筛选方法总结3.1 正则表达式3.2 CSS选择器3.3 Bs4常用方法介绍3.4 解决上文的问题4 反爬措施简介与应对策略4.1 异步请求加载4.1.1 Ajax简介4.1.2 JSON简介4.1.3 微博Ajax原理破解4.2 模拟登录4.2.1 登陆与会话保持4.2.2 验证码4.2.3 12306网站模拟登录解析4.3 自动化操作5 总结

1 准备工作

爬虫(Web Spider,Crawler)是指能够按照特定规则在网站上获取用户期望的信息的一段程序。由于 Python 语言拥有丰富的网络访问/数据分析开源包,所以用它编写爬虫程序比用 Java / C++ 容易不少。本章介绍编写爬虫前应做的准备和应当具备的知识。

1.1 安装必要环境

Python 集成开发环境(IDE):PyCharm 或 Microsoft Visual Studio Code;

Python 解释器:采用 Python3.7.5 版本,并配置环境变量。

Anaconda:是一个 Python 的包管理工具,使用 Anaconda 可以避免在不同项目中重复安装同一个包,因为 Anaconda 通过不同的 环境 把包管理起来了。这里的 环境 相当于所有包的容器,例如你创建了一个与深度学习有关的环境,叫做 PyDeepLearning,那么你可以把 Tensorflow / Numpy / Pytorch 等包都放到这个环境下,下次只要在工程中把编译器调整为该环境对应的解释器(每个环境在被创建时都会生成对应版本的Python解释器),代码就能成功运行,避免了每个工程重复安装包的麻烦。

以上内容的安装方法不再赘述。

1.2 安装必要包

将 Anaconda 的环境变量配置后,在终端输入以下命令:

如果能看到 cmd 出现版本号,则说明 Anaconda 环境变量配置成功。现在在 Anaconda 中创建虚拟环境,其中[EnvName] 为你创建的环境的名字,[Version] 为创建的 Python 解释器的版本。

先激活环境,然后通过终端命令安装必要的包:

requests 包用于向网站发出访问请求,而 Beautifulsoup 用于从获取的 HTML 文本中提取必要信息,具体内容将在下文解释。至此,准备工作完毕,只要在工程中配置好刚刚配置的解释器,就可以编写爬虫程序了。

1.3 部分名词解释

为了方便没有基础的读者更好的阅读下面的内容,我对下文会出现的专业词汇按照本人理解作尽可能通俗的解释。如果下文出现你不熟悉的词汇,可以回看这里的解释。

  1. Request/Response

网页是运行在服务器上的,那么我们是如何从浏览器浏览能够浏览到服务器上的网页的呢?首先当网址(Url)被输入后,浏览器通过 Http 协议 向服务器发送 请求 Request,服务器接收到请求数据后返回 响应 Response ,表示服务器同意/拒绝了访问请求。当浏览器接收到响应,会根据响应的状态码判断能否进行页面跳转。常见的状态码有 200,404,512等。当一个200的响应被接收到,页面就能发生跳转,我们也就看到了浏览器上的网址。相反,当我们看到 404 错误网页,就说明一个404的响应被接收到,浏览器不能对网站进行访问。

  1. Session/Cookie

用户登录某网站后,服务器用 会话(Session)存储用户登录信息,这样就不会因为用户页面跳转导致登陆失效了。由于Http协议是无状态的,而登陆的用户有很多,服务器不知道应该为哪个用户服务,因此第一次创建 Session 时,服务器会告知浏览器要在本地创建一个携带 id 的 Cookie(不好翻译,理解为存储在终端的数据),这样就能通过本地的 id 追踪服务器上的会话,确定特定用户是不是已经登陆过了,并为特定用户提供服务。

2 爬虫入门实战

网上一般以小型网站作为爬虫的入门教材。http://www.lovehhy.net/Joke 是一个笑话网站,这个网站的主要内容是分页展示了一条条的笑话,因为它几乎没有设置任何的反爬限制措施,用户可以很容易的从这个网站中获得数据,非常适合新手入门。

2.1 访问网页

爬虫的第一步是试图访问网站,并获取它的 Html 文件数据,这里选择将其写入文件,这样爬取一次就可以拿来用了,避免反复爬取浪费时间。用 Python 代码展示如下:

其中,核心语句是html = requests.get(url).content.decode('gbk'),其中,requests.get() 方法用于向目标网站发起请求,其返回值为响应类的对象即 Response 对象。Response对象中的 content 属性保存的就是未经解码的 Html 文本,对其使用 decode(str) 方法,即可把其中编码的字符转化为我们需要的字符。

注意:这里发现爬取的网站采取的是 GBK 编码,一般网站使用 utf-8 方式解码即可。

使用 try except 语句的作用:

  1. 处理文件读写可能抛出的异常;
  2. 处理网络问题导致请求失败的异常。

当网页被成功读取,通过 print() 方法即可看到完整的网页以 Html 的形式被获取了。

 

2.2 分析网页结构

通过此法获得的 Html 文本包含了网页的所有静态信息,要获取这些信息,首先应分析网页信息结构。在浏览器中打开网页,并对你感兴趣的内容右键,点击 审查元素 即可看到当前网页元素所代表的 Html。以糗事百科为例,经过简单的探索,我们发现所有的笑话都被装进了一个 class=catlib<div> 容器中,每一条笑话的标题用<h3>包裹,而内容则被放在了紧跟<h3> 后面的 id=endtext<div> 容器中。用Html描述如下:

 

2.3 解析网页数据

现在我们掌握了这个网站的信息存储结构,只需使用 Beautifulsoup 即可根据结构特征轻而易举地提取 Html 中的数据。由于之前将 Html 存入了文本文件,现在只需从文本中读取即可。以 Python 代码展示如下:

首先引入Beautifulsoup类,这是一个用于解析和定位特定格式文本的类,在爬虫中被频繁使用。那么它是怎么工作的呢?先用 Beautifulsoup 生成一碗美丽的“汤” ,把一大堆 “原材料” html 文字倒入这碗 “汤” 中混合均匀,原先的 html 就会被建立成一颗 “”,根据 “树” 的孩子、祖先,及每个 html 结点的特征关系,我们就可以轻易地把想要的 html 文本提取出来。

soup = Beautifulsoup(html, 'html.parser')表明生成一个采用 html 解析器的 Beautifulsoup对象用于解析 html 内容。

现在我们要用到 2.2 中的分析结果,由于所有文本的共同特征是都被存放在 <div id = endtext> 中,所以通过li = soup.findAll(name="div", id="endtext") 语句,就能把所有符合上述特征的 html 片段存放入列表 li 中。

这里需要说明的是:调用了 soup 相关的查找方法后,得到的内容的类型为 <class 'bs4.element.Tag'> 或者它的列表。这种类型相当于树的结点,即可以根据某个标签查找其前驱后继,祖先孩子兄弟等各种信息,也就是可以继续对它调用查找方法进一步查找。

这种类型还包含了 text 字段,存储除了 html 元素之外的纯文本,所以可以用 text 字段提取蕴含的文字信息。把它们写入文本文件,爬取工作就顺利完成了!

如果想要爬取剩余页面的内容,只需要修改 Url 中的最后一个参数,并重复上述步骤即可,因为它代表了页码。

2.5 新的困境

2.5.1 初级反爬机制

完成了第一个爬虫网站,是不是很有成就感?现在我们来尝试爬取第二个网站: https://wiki.52poke.com/wiki,这也是我目前正在做的个人项目的组成部分。

这个网站是国内最大的 Pokemon 百科全书网站(Pokemon是任天堂旗下Gamefreak公司创造的虚拟宠物,为人熟知的有皮卡丘,喷火龙等),存储了大量关于 Pokemon 的知识,其信息存储方式非常直白,几乎没有使用任何异步的加载,适合新手进行爬取。

这次爬取的目的是获取皮卡丘页面的指定信息。但是当我们准备如法炮制(参照2.1的方法)对其进行访问时,却发现得到的 Html 没有包含你想要的信息。原因就是服务器发现是机器人在对其访问,于是用一个默认页面拒绝了浏览器的访问请求。

事实上,几乎所有网站都有这种反爬检测,前文介绍的网站只是其中一个特例。但其实这种反爬机制非常容易被绕过,只需要对请求头进行伪装即可。

上面的代码表示把请求头伪装成 Mozilla / Chrome / Safari 浏览器发出的请求,这样服务器就不会把浏览器请求过滤掉。

携带headers信息访问皮卡丘页面,终于能成功访问了。为了能成功访问其他网站,我建议在编写爬虫脚本时,务必加上伪装的请求头。

2.5.2 爬取复杂数据

如果我们要获取皮卡丘的分类信息(即:鼠宝可梦),点击审查元素后就会发现,它被嵌套得很深,如下面的Html所示:

(上图只展示了其中的一部分,实际上的内容更多)

如图, “鼠宝可梦” 被 <table> 嵌套了三次,实际上还有更多层嵌套,且每一层的内部结构都不一样,如果我们使用 2.3 所述的爬取方法,可能会面临很多问题。

下面是可能的写法:

这样写发现得到的根本不是我想要的,因为以 bl-电 为 class 的标签除了这个之外还有非常多

那么把所有带有此标签的内容用 findAll() 提取出来,然后找这是第几个,可以吗?

显然,这种方法的容错性极低,因为每个页面的对应特征可能不同,如果新增若干个 bl-电 标签,再次查找到的肯定不是期望的内容。并且这样的标签特征性太强,不是每个页面都有的,如果想要爬取 “喷火龙” 页面,显然不会出现 bl-电 这样的标签,因为 “喷火龙” 不具备 “电” 属性。

下面总结按照内容特征直接提取的缺点

  1. 为了匹配一项内容所要书写的 soup.find 需要重复很多次,代码不简洁。
  2. 与期望内容完全一样的Css特征在Html中反复出现,即便用 findall 匹配成功,也难以从列表中查找到具体匹配的是哪一项。
  3. 方法不具备普适性,且即便成功拿到期望的内容,换到另一个结构相近但不完全相同的页面,爬虫方法或将失效。

所以,我们要从 结构 入手,再结合 内容 才能更有效地提取内容。我将介绍第三章,有了第三章方法的辅助,就可以轻松处理类似如上信息的爬取了。

3 数据筛选方法总结

3.1 正则表达式

正则表达式 是一种特殊的字符串,它用一套自己的语法规则描述了字符串的特征,可以用来匹配更加复杂的信息,例如字符串 ”Asd12Sfr5“ 中的所有数字,“moon mooon” 中带有两个o的单词等。由于正则表达式比较复杂,且长时间不用容易忘记,这里用几个例子介绍若干常用操作,详细内容可以搜索正则表达式自行深入学习。

在Python语言中,正则表达式库是系统自带的,通过 import re 语句即可使用正则表达式。下面介绍正则表达式的常用方法:

这个方法可以将字符串 string 用正则表达式 pattern 匹配,加上 flag 条件予以限制(可选参数)。但必须是开头就满足匹配条件,否则匹配结果为 None

可能有点听不懂,没关系,我们结合具体案例来看:

【例1】re.match(r"Asd","Asd12Sfr5Asd").group(1)

结果:Asd

上面的代码表示匹配Asd,但必须是开头位置。group(n) 表示展示第n个匹配结果。r出现在字符串前面,表示是原生字符串,即其中的反斜杠不需要转义即可直接写出(否则的话要书写换行则必须 \\n)。

 

这个方法表示匹配所有符合条件的字符串,并以列表的形式展现。

【例2】re.findall(r">(.*?)<br/","<div>hello<br/>asd<br/>qwe<br/></div>")

结果:['asd', 'qwe']

上面的代码表示匹配 > ... <br/ 中间的内容,( ) 标记了要输出的内容,. 表示匹配任意内容的一个字符,* 表示匹配超过一个的字符,.* 结合表示匹配超过一个字符的任意内容字符串。? 作为非贪婪匹配的标志(匹配0个或1个字符),和 .* 结合表示匹配的内容正好落在 > <br/ 之间。

 

【例3】re.search(r"QQ\d{7}","Number is Qq123456789haha",re.I).group()

上面的代码表示忽略大小写匹配QQ后面的7个数字,re.I 作为flag表示忽略大小写,\d 表示匹配一个数字,{7} 表示匹配7个与其左侧相连部分一致的字符串。

 

由于正则表达式内容多而繁杂,这里就介绍这么多,详细内容可以看网上的相关教程。

3.2 CSS选择器

Css选择器可以根据 Html 标签及其属性特征,以及标签之间的关系快速定位要找的标签,即便是在复杂的 Html 结构中也非常好用。之所以叫做Css选择器,是因为在Css(Cascade Style Sheet,层叠样式表)文件中,就是通过Css选择器,为指定的内容设置样式。

bs4 包提供了 CSS 选择器的查找手段,写法如下:

这个方法返回匹配到的列表,列表中的每个元素都是 elementTag 类型的,因此可以对其中的元素继续调用查找方法。

Css选择器虽然比正则表达式容易,但仍然多而繁杂。下面列出了常用的Css选择器写法的案例,可以胜任大部分信息匹配:

Css选择器解释
table.alter所有类为alter的table
div#hello所有id=hello的div
div.a#hello p所有class=a且id=hello的div元素的所有孩子元素p
h3>h4所有h3标签下的直接孩子h4
a[href=www.baidu.com]所有href=www.baidu.com的a元素
div[style] table>tbody tr包含style属性的div的所有孩子table元素下的直接孩子tbody下的所有孩子tr
#good .luck所有id=good的元素的所有孩子中,class=luck的元素

 

3.3 Bs4常用方法介绍

这一部分进一步介绍了Bs4的方法,使得Bs4用起来更加灵活。实际上Bs4的方法就是对树的操作。

假设已经定义 soup = BeautifulSoup(html, "html.parser")

方法示例解释
soup.findAll(name="div", id="123", class_="ctx")查找 id = 123, class = "ctx" 的所有 div 容器,返回列表
soup.select("div>a[id=123]")根据 css 选择器匹配div下的id=123的所有子元素,返回列表
soup.findAll(name="div", attr = {'id': '123', 'style':"xxxxxx"})查找符合id = 123, style=xxxxxx的div容器
tag.findAllNext(name="h3", limit=5)查找出现在当前tag之后的5条h3元素
tag.findPrevious(name="h1", text="hello")查找当前tag的前一个文字是hello的h1元素
tag.findParent()查找当前tag的最接近的父亲
tag.findNextSibling(a)查找当前tag的下一个a标签的兄弟

 

3.4 解决上文的问题

根据对多个页面结构的研究,我发现所有页面的主要内容都放在class=mw-parser-outputdiv 容器中,且该容器中的右侧都有一列表格,存放了 Pokemon 的各项信息,而我们期望的信息正好包含其中。因此首先锁定右侧表格。经过探索,所有右侧表格都具备特征 .a-r 且一定是第一个。

在表格中,期望的内容一定会出现在 tbody 下的第3个 tr 中:

tr 中,期望的信息可以直接用文本字段提取:

至此,信息提取完毕,并可以简化到一行上完成:

假设信息出现在同一标签下,且分散分布(即文字和Html标签互相交叠),则应使用正则表达式匹配。设想如下情况:

可以这样做:

我认为,数据筛选的最佳实践是先用 Css 选择器匹配,正则表达式的优先级应当低于Css选择器, 因为它比较麻烦。

 

4 反爬措施简介与应对策略

理论上能够通过正则表达式和BS4爬取一切内容。但一般来说,大型的网站为了保护自身数据,或是降低服务器负载,不会允许爬虫在上面长时间抓取数据,或者直接用各种手段反制爬虫,因此,各种反爬措施就被发明出来了。不同网站有不同的反爬措施,同时不同的反爬措施也有相应的对策。为了爬到数据,我们接下来详细讨论每种反爬措施的应对策略。

4.1 异步请求加载

4.1.1 Ajax简介

异步请求加载 是运用了 JavaScript 中的 AJAX(Asynchronous Javascript and Xml),即异步 Js 和 Xml 技术。这种方法被大多数博客、论坛网站采用,其特征是网页内容的加载可以在不重新加载所有内容的情况下,自行与服务器交换数据,并异步加载,具体地说,就是内容是随着用户操作,如页面下拉而自动加载的。

这种方法的采用导致原先介绍的静态页面采集几乎失效。因为 Requests 库的 Get() 方法获取网页 Html 的步骤是:进入网站,等待网站同步加载完毕,退出并收集响应体。由于 Ajax 技术下,页面必须由用户动态操作才能全面加载,所以这些 后续加载的内容不会被包含在响应体中

4.1.2 JSON简介

Json(JavaScript Object Notation) ,Js对象简谱,是一种数据存储结构,类似Python的字典,被广泛用于互联网数据交互中,因为它可以以键值对(K-V)很好的描述对象的特征。Ajax 技术与服务器之间的交互用的大多是 Json

一个简单的 Json 样例:

4.1.3 微博Ajax原理破解

打开微博 https://m.weibo.cn/ , 搜索一个用户并进入他的主页,此时打开 Network监控网络状况,并筛选 XHR,只查看异步加载的请求。刷新一次页面,会发现页面向服务器发送了很多的 Ajax 请求,当用户下拉页面后,随着 Ajax 请求再次发出,页面上又会新增 11 条微博博文。

仔细分析这些请求的特征,发现有一个请求携带了初始 11 条博文的数据,它的 Url 是这样的:

继续查看下一条携带另外11条博文信息的Ajax Url,发现它的后面携带了 since_id

继续向下查看,每一条相似的 AjaxUrl 都携带since_id。因此可以推测,since_id 是访问不同博文组合的钥匙,如果能找到 since_id 的来源,就能成功制作爬取页面的所有内容。

幸运的是,经过一番探索,我发现这些 Ajax 请求之间存在 链表 关系。刚开始加载的 Ajax 不包含 since_id,它是链表的 头节点,而 since_id 则相当于后继指针,指向下一个Ajax请求,如图所示:

since_id
since_id
since_id
HeadAjaxUrl
NextAjax
NextAjax
NextAjax

证据就存在于这些 Ajax 请求的响应体 Json 中,这是头节点的 Json 的一部分:

这是头节点后继 Json 的一部分:

对比之前的第二个Url,发现确实是这样,实际上后面的 Json 和 AjaxUrl 都符合上述对应关系,因此我们可以根据这种递推关系,爬取页面所有内容,只需要用 Requests 库访问这些 Url 即可。

由于获得的响应体是 Json,可以转化为 Python 的字典,因此可以不用 Bs4,直接用键访问值的形式提取数据。

4.2 模拟登录

有很多网站需要用户登录才能获得访问数据的权限,因此如何模拟登录成为了亟待解决的难题。

4.2.1 登陆与会话保持

登录是一个 Form 表单的提交过程,用户点击 [登录] 按钮后,浏览器向服务器发送携带表单信息的 Requests,服务器验证后,如果用户登陆成功,服务端将会生成一个 Session,用于保存用户登录信息,同时第一次生成 Session 时,会在本地生成 Cookie 用于保存 SessionId,用于追踪 Session。这样当用户下次进入网站时就会自动进入已登录状态。

上面为传统的登录方法,目前很多网站为了信息安全采取了 Token 验证,即用户登陆成功后,服务端给浏览器签发一个 “令牌”(Token),并存储在Cookie中。每次浏览器发出请求都要带上签发的 “令牌”,如果请求不能通过服务端的验证,服务端返回一个响应拒绝操作。签发的 Token 携带了用户信息和密钥,其中密钥经过了 Hash 函数加密,用于服务端检测Token 的签发方是不是自身,从而检验 Token 有效性。

对于前一种形式的登录,我们只需要手动登录一次,然后从 Network 采集 Cookie 就可以绕过登录。一般用于安全性不高的小型网站。

后一种形式的登录,由于生成的 Token 每次都不同,因此每次访问必须模拟登录。一般大型网站都采用此方法。

由于登陆操作涉及大量 Cookie 操作,所以应当用 Session 代替 requests,这样的话每一步的 Cookie 都能得到保持,其余与 requests 操作类似。示例如下:

 

4.2.2 验证码

只要有模拟登录,基本上不能避免验证码输入。验证码种类五花八门,从最简单的字符图片到动态的图片,再到 “请点击下面所有的xxx” ,甚至还有 “请把滑块拖到指定位置” “把图片转到正面” 这样的高级验证码。

对于验证码的破解,我认为可以分成两种:

  1. 传统验证码

    即只是一张图片,包含字符或者数字,不需要用户对其进行交互操作。

    破解方法:

    • 训练深度学习模型,使其具备自动识别验证码的能力。自动识别后填写到表单发往服务器。事实上有 Python 的包可以做到传统验证码识别。
    • 下载本次验证码的图片,或者取得图片 Url,然后人工识别并填写验证码,再把验证码写到表单中发往服务器。
  2. 高级验证码

    即点击图片,拖动滑块类型的验证码。

    破解方法:

    • 部分 ”请点击下图中的xxx“ ”把滑块拖到指定位置“ 验证码实质上是静态图片,表单中会传递一组与鼠标坐标相关的值,以此验证用户是否确实点击到正确的东西。
    • 实在不能解决的请参考 4.3 的万能方法。

4.2.3 12306网站模拟登录解析

在认识实习上课期间,我们小组之前做过 12306 自动抢票脚本,就遇到了模拟登录的问题。

12306 是著名的火车购票平台,它的登录包含了 ”请点击以下所有的xxx“ 类型的验证码。

手动登录多遍,研究 12306 的登陆细节,发现其登录流程主要步骤可用下图描述:

首先异步访问 /captcha/captcha-image64 获取验证码图片。访问后得到一个 Json,其中包含键 image,储存了图片信息。图片经过了 base64 加密,所以要先用 Python 自带的 base64 库对其解密,然后将其写入后缀为 .jpg 的文件中,便可直接查看。

验证码包含8个图片,分成两排,每排4个。验证码答案有多组,每一组是一个二元组,代表鼠标相对图片左上角的像素坐标。对验证码的填写可以用 input() 由用户手动完成`。

当用户点击 [登录] 按钮,提交一个包含用户名,密码,验证码答案等结果的表单,具体如下:

其中,answer 是验证码答案。

把上面的表单 Post 到 /captcha/captcha-check 检验验证码,服务器将返回包含检验是否成功的 Json

如果检验通过,继续将上面的表单Post到 /passport/web/login,服务器检验携带的Cookie合法性,检验后,登录成功。

小组在模拟登录时,能够成功通过验证码验证,但访问 /login 时,页面返回 ”网络可能存在问题“, 表明服务器拒绝了登录请求。其中的原因是在整个过程中,包含了多次对 Cookie 的增删操作,在比对实际情况和模拟登录的 Cookie 的差别后,我们发现最后一步缺少了 3 条必要的 Cookie,导致验证失败:

因此我们在最后一步执行前按实际情况更新了 Cookie,结果登陆成功。

 

4.3 自动化操作

自动化操作是一个万能的爬虫方法,对几乎所有网站都可以使用。

其原理是通过一个 Python 包 Selenium ,这个包能通过代码操控浏览器进行网页浏览,可以执行js代码,并可以进行数据提取。所谓所见即所得。

下面的代码是之前参加比赛时写的,爬取对象是 Medium。由于这个网站的抓包非常困难,我们选择自动化控制来完成。关于 webdriver 的常用操作请参考下面的代码。

 

5 总结

至此我们结束关于爬虫技术的讨论。爬虫的一般流程是:

  1. 试图访问目标 Url。
  2. 对得到的 Html/Json 进行数据提取。
  3. 如果需要,对提取到的数据进行持久化操作。(本文没有涉及)

根据不同网站的类型,可以将爬取方式分为以下三类:

分类举例措施
简单的Html网页,且爬取内容不属于Ajax动态加载糗事百科,Github爬取Html(第二章)
Ajax动态加载,且容易抓包微博,Twitter,简书,Reddit爬取Json(4.1+4.2)
Ajax动态加载,难以抓包Medium自动化操作(4.3)

对于数据的筛选,大致有Css选择器和正则表达式,如果是 Json,将其转化为字典是更好的办法。

由于网站处于不断的更新中,并且其安全技术也在不断升级,所以爬虫是具有时效性的。例如半年前我在制作微博爬虫的时候,它的 url 还没有采用 since_id,而是直白的 page = xxx。

爬虫技术应用前景广泛。单就课内而言,创新实践课程介绍的知识图谱需要数据支撑,深度学习数据集同样需要大量数据。今后我将把数据提取运用到深度学习实践中,力争取得更大的成功。