python之爬虫三菩提浪子

在编写爬虫程序的过程中提取信息是非常重要的环节,但是有时使用正则表达式无法匹配到想要的信息,或者书写起来非常麻烦,此时就需要用另外一种数据解析方法,也就是本节要介绍的 Xpath 表达式。

XPath(全称:XML Path Language)即 XML 路径语言,它是一门在 XML 文档中查找信息的语言,最初被用来搜寻 XML 文档,同时它也适用于搜索 HTML 文档。因此,在爬虫过程中可以使用 XPath 来提取相应的数据。

提示:XML 是一种遵守 W3C 标椎的标记语言,类似于 HTML,但两者的设计目的是不同,XML 通常被用来传输和存储数据,而 HTML 常用来显示数据。

您可以将 Xpath 理解为在XML/HTML文档中检索、匹配元素节点的工具。Xpath 使用路径表达式来选取XML/HTML文档中的节点或者节点集。Xpath 的功能十分强大,它除了提供了简洁的路径表达式外,还提供了100 多个内建函数,包括了处理字符串、数值、日期以及时间的函数。因此 Xpath 路径表达式几乎可以匹配所有的元素节点。

Python 第三方解析库 lxml 对 Xpath 路径表达式提供了良好的支持,能够解析 XML 与 HTML 文档。

XPath 提供了多种类型的节点,常用的节点有:元素、属性、文本、注释以及文档节点。如下所示:

上面的 XML 文档中的节点例子:

<website></website> (文档节点)

<name></name> (元素节点)

lang="zh-CN" (属性节点)

XML 文档的节点关系和 HTML 文档相似,同样有父、子、同代、先辈、后代节点。如下所示:

上述示例分析后,会得到如下结果:

title name year address 都是 site 的子节点

site 是 title name year address  父节点

title name year address  属于同代节点

title 元素的先辈节点是 site website

website 的后代节点是 site title name year address

Xpath 使用路径表达式在文档中选取节点,下表列出了常用的表达式规则:

Xpath路径表达式

表达式

描述

node_name

选取此节点的所有子节点。

绝对路径匹配,从根节点选取。

//

相对路径匹配,从所有节点中查找当前选择的节点,包括子节点和后代节点,其第一个 / 表示根节点。

选取当前节点。

..

选取当前节点的父节点。

下面以下述代码为例讲解 Xpath 表达式的基本应用,代码如下所示:

路径表达式以及相应的匹配内容如下:

xpath表达式://li

匹配内容:

c语言小白变怪兽

纸质书

80元

红蓝色封装

Python入门到精通

电子书

45元

蓝绿色封装

xpath表达式://li/p[@class="name"]

匹配内容:

c语言小白变怪兽

Python入门到精通

xpath表达式://li/p[@class="model"]

匹配内容:

纸质书

电子书

匹配内容:

xpath表达式://ul/li

匹配内容:

c语言小白变怪兽

纸质书

80元

红蓝色封装

Python入门到精通

电子书

45元

蓝绿色封装

注意:当需要查找某个特定的节点或者选取节点中包含的指定值时需要使用[]方括号。如下所示:

xpath表达式://ul/li[@class="book2"]/p[@class="price"]

匹配结果:45元

Xpath 表达式的通配符可以用来选取未知的节点元素,基本语法如下:

xpath通配符

通配符

描述说明

匹配任意元素节点

@*

匹配任意属性节点

node()

匹配任意类型的节点

示例如下:

xpath表达式://li/*

匹配内容:

c语言小白变怪兽

纸质书

80元

红蓝色封装

Python入门到精通

电子书

45元

蓝绿色封装

多个 Xpath 路径表达式可以同时使用,其语法如下:

xpath表达式1 | xpath表达式2 | xpath表达式3

示例应用:

匹配内容:

45元

Xpath 提供 100 多个内建函数,这些函数给我们提供了很多便利,比如实现文本匹配、模糊匹配、以及位置匹配等,下面介绍几个常用的内建函数。

Xpath内建函数

函数名称

xpath表达式示例

示例说明

text()

./text()

文本匹配,表示值取当前节点中的文本内容。

contains()

//div[contains(@id,'stu')]

模糊匹配,表示选择 id 中包含“stu”的所有 div 节点。

last()

//*[@class='web'][last()]

位置匹配,表示选择@class='web'的最后一个节点。

position()

//*[@class='site'][position()<=2]

位置匹配,表示选择@class='site'的前两个节点。

start-with()

"//input[start-with(@id,'st')]"

匹配 id 以 st 开头的元素。

ends-with()

"//input[ends-with(@id,'st')]"

匹配 id 以 st 结尾的元素。

concat(string1,string2)

为了帮助大家快速掌握 Xpath 表达式的使用,这里给大家推荐一款 Xpath 表达式匹配助软件,它就是 Xpath Helper。

Xpath Helper 是一款谷歌应用商店推出的免费工具,因此您需要在谷歌商店进行下载。下载完毕后,谷歌浏览器会将其作为插件自动安装在扩展程序中,如下所示:

图 1:Xpath Helper助手

点击扩展程序入口,进入管理扩展程序界面,如下图所示:

图 2:Chrome浏览器插件管理界面

您也可以通过以下步骤进入上述管理界面:浏览器设置 -> 更多工具 ->扩展程序 ->开发者模式。注意:此时右上角的开发者模式应处于开启状态。

安装完毕后,在需要匹配数据的页面处,使用快捷键打开助手工具(快捷键:ctrl+shift+x),使用示意图如下:

将鼠标悬停在需要选取数据的文本上,并按下shift按键就会自动出现 Xpath 表达式,然后再根据您自己的需求对表达式稍微修改即可。如果您没有谷歌应用商店账号,您也可以在网上搜索免费的下载资源。为了节省您的时间,下面提供了资源下载链接:

下载解压后,将文件夹直接拖入 Chrome 扩展程序即可完成安装。

谷歌开发者调试工具也内置了 Xpath 表达式匹配功能,首先打开调试工具,在下方的调试工作区内使用快捷键ctrl+F打开 Xpath 匹配功能,如下图所示:

lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 Xpath 表达式提供了良好的支持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。

lxml 属于 Python 第三方库,因此需要使用如下方法安装:

pip3 install lxml

在 CMD 命令行验证是否安装成功。若引入模块,不返回错误则说明安装成功。

>>> import lxml

>>>

lxml 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面我们简单介绍一下 lxml 库的使用流程,如下所示:

from lxml import etree

调用 etree 模块的 HTML() 方法来创建 HTML 解析对象。如下所示:

HTML() 方法能够将 HTML 标签字符串解析为 HTML 文件,该方法可以自动修正 HTML 文本。示例如下:

输出结果如下:

上述 HTML 字符串存在缺少标签的情况,比如“C语言中文网”缺少一个 </li> 闭合标签,当使用了 HTML() 方法后,会将其自动转换为符合规范的 HTML 文档格式。

最后使用第二步创建的解析对象调用 xpath() 方法,完成数据的提取,如下所示:

下面通过一段 HTML 代码实例演示如何使用 lxml 库提取想要的数据。HTML 代码如下所示:

输出结果:

['website product', '编程', '微博', '百度贴吧', '天猫淘宝', '京东购物', '编程', '安全卫士', '视频娱乐', '年轻娱乐', '搜索引擎']

输出结果:

输出结果:

首先明确要抓取信息的网页元素结构,比如电影名称、主演演员、上映时间。通过简单分析可以得知,每一部影片的信息都包含在<dd>标签中,而每一<dd>标签又包含在<dl>标签中,因此对于dd标签而言,dl标签是一个更大的节点,也就是它的父辈节点,如下所示:

图1:分析元素结构

当一个<dd>标签内的影片信息提取完成时,您需要使用同样的 Xpath 表达式提取下一影片信息,直到所有影片信息提取完成,这种方法显然很繁琐。那么有没有更好的方法呢?

因为每一个节点对象都使用相同 Xpath 表达式去匹配信息,所以很容易想到 for 循环。我们将 10 个<dd>节点放入一个列表中,然后使用 for 循环的方式去遍历每一个节点对象,这样就大大提高了编码的效率。通过<dd>节点的父节点<dl>可以同时匹配 10 个<dd>节点,并将这些节点对象放入列表中。我们把匹配 10个<dd>节点的 Xpath 表达式称为“基准表达式”。如下所示:

xpath_bds='//dl[@class="board-wrapper"]/dd'

下面通过基准表达式匹配 <dd> 节点对象,代码如下:

输出结果:

[<Element dd at 0x36c7f80>, <Element dd at 0x36c7d50>, <Element dd at 0x36c7940>, <Element dd at 0x36c7d28>, <Element dd at 0x36c7bc0>, <Element dd at 0x36c7f58>, <Element dd at 0x36c7f30>, <Element dd at 0x36cc468>, <Element dd at 0x36cc170>, <Element dd at 0x37382b0>]

因为我们想要抓取的信息都包含在<dd>节点中,接下来开始分析<dd>节点包含的 HTML 代码,下面随意选取的一段<dd>节点包含的影片信息,如下所示:

分析上述代码段,写出待抓取信息的 Xpath 表达式,如下所示:

提取电影名信息:xpath('.//p[@class="name"]/a/text()')

提取主演信息:xpath('.//p[@class="star"]/text()')

提取上映时间信息:xpath('.//p[@class="releasetime"]/text()')

上述内容介绍了编写程序时用到的 Xpath 表达式,下面正式编写爬虫程序,代码如下所示:

输出结果如下:

几乎所有浏览器都提供了抓取数据包的功能,因为浏览器为抓包提供了一个专门的操作界面,因此这种抓包方式也被称为“控制台抓包”。本节以 Chrome 浏览器为例进行抓包演示。

控制台抓包指的是利用浏览器开的发者调试工具抓取客户端与后端服务器交互的数据,它能够将网络传输中发送与接收的数据进行截获、重发和编辑。

图 1:开发者调试工具

下面对上图 1 中控制台的常用选项做简单介绍:

该选项主要用于抓取网络数据包,比如查看请求信息、响应信息等。它有三个常用选项卡,分别是 All、XHR、JS,其作用如下:

该选项主要用于查看页面的 HTML 、JavaScript 、CSS 的源代码,除此之外,最重要的是它还可以调试 JS 源代码,可以给 JS 代码打断点调试,有助于分析爬虫程序中的一些参数。

交互模式,能够执行 JavaScript 代码,一般用于对当前程序中 JS 代码进行测试,同时也可以查看 JavaScript 对象,或者调试日志、异常信息等。

该选项用于查看、修改本地存储(Local Storage)以及会话存储(Session Stroage)等,同时它也可以用来查看 Cookie 信息。Cookie 是网站服务器为了辨别用户身份,而储存在客户端浏览器上一段加密字符串。某些网站需要用户登录后才可以看到相应的数据。如果想要爬取此类网站的数据,就需要使用 Cookie 模拟用户登录。

有道翻译采用了 JS 异步加载的方式获取翻译结果,并将该结果渲染到指定的输出框内。所谓异步加载,即不需要刷新页面,就可实现页面的局部渲染。对于这样数据,可以通过 NetWork 的中 XHR 选项来抓取数据包,并选择查看最后一个数据包,如下图 2 所示:

图2:抓取数据包

因为异步加载几乎是实时响应的,所以当您在输入框内输入“hello world”的过程中,每输出一个单词都会向服务器发送一次异步请求(若输出很慢时,一个字母都会发送一次请求),除非您事先将要查询的单词复制好,一次性粘贴到输入框内,只有这样才会得到一个数据包。因此,在这里选择了最后一个数据包进行分析。接下来,对上图 2 中常用选项做简单介绍:Headers 用来描述整个请求信息,Preview 用来对响应内容进行预览,Response 用于查看响应内容,Cookies 用于查看客户端 Cookie 信息。

图3:预览响应内容

在有道翻译的输入框内多输入几个单词或者汉字,查看 Form Data 的变换规律。你会发现有些参数的值总是变化的,而有些参数值没有变化,比如 salt、sign、lts 总是变化的,而 bv 等参数是不变化的,而参数 i 代表用户输入的单词。如下所示:

i: hello world   #你输入的单词

salt: 16161405904876

sign: a6f9d57d297acc79f31b049e2a542519

lts: 1616140590487

bv: cda1e53e0c0eb8dd4002cefc117fa588

图1:有道翻译POST请求参数

其中 data 是字典格式参数,它用来构建 POST 请求方法的参数和参数值。

salt、sign 加密有两种实现方式:一种是通过前端 JS 实现,另一种是后台服务器生成加密串,并在返回响应信息时,将加密信息交给接浏览器客户端。但是,通过预览响应信息可知,并没有涉及 salt、sign 的信息,因此可以排除这种方法。

图2:预览响应信息

那么要如何找到关于salt、sign 的 JS 代码呢?此时就要用到另外一个调试工具选项卡—— JS。如下图所示:

图3:js文件

点击上图所示的搜索按钮来检索 JS 代码,输入 "salt",结果如图所示:

图5:Sources选项卡应用

通过上述方法就找到了 salt 与 sign(两个参数项是在一起的)JS 代码,如下所示:

注意,找到上述代码是解决本节问题的关键,大家一定要要掌握方法。

通过上述 JS 代码的简单分析可知: r 变量等同于 lts,salt 变量等同于 i,而 sign 是一个经过 md5 加密的字符串。接下来使用 Python 代码来表示上述参数,如下所示:

完整代码如下所示:

输出结果:

请输入要翻译的单词:大家好,这里是C语言中文网Python爬虫教程

lts,salt,sign 输出结果:

1616472092090 16164720920902 fcc592626aee42e1067c5195cf4c4576

html 响应内容:

{'type': 'ZH_CN2EN', 'errorCode': 0, 'elapsedTime': 25, 'translateResult': [[{'src': '大家好,这里是C语言中文网Python爬虫教程', 'tgt': 'Everybody is good, here is the Chinese Python crawler C language tutorial'}]]}

翻译结果: Everybody is good, here is the Chinese Python crawler C language tutorial

剧情|喜剧|动作|爱情|科幻|动画|悬疑|惊悚|恐怖|纪录片|短片|情色|同性|音乐|歌舞|家庭|儿童|传记|历史|战争|犯罪|西部|奇幻|冒险|灾难|武侠|古装|运动|黑色电影|

你想了解什么类型电影:犯罪

{'name': '肖申克的救赎', 'score': 9.7}

{'name': '控方证人', 'score': 9.6}

...

电影总数量:302部

首先要明确豆瓣电影网站的类型,即是动态还是静态。检查方法:右键查看网页源码 —> 搜索“辛德勒的名单”关键字,如下图所示:

图1:分析网站类型

最终发现源码页中没有出现想要抓取的数据,只有一大堆的 JS 代码,由此确定该网站为动态网站。

接下来,使用快捷键 F12 打开控制台进行抓包,点击NetWork选项卡 —>XHR选项 —> Preview选项卡 —> 刷新当前页面抓取数据包,如下图所示:

图2:抓取动态网站数据包

图3:分析Headers信息

从上图可以得知请求的基准 URL (由于还未拼接查询参数,所以称之为基准 URL),如下所示:

继续滚动鼠标滑轮可知查询参数具有如下规律:

type: 4  # 电影类型

interval_id: 100:90  #代表网页上滑动条的百分比(好于100%-90%的历史片)

action: ''  # 空

start: 0  # 每次加载电影的起始索引值 0 20 40 60

limit: 20 # 每次加载的电影数量,1为初始值,后续加载时20固定不变

注意:寻找规律时,后加载出来的数据包会排在最前面,除去第一个数据包外,其余数据包如下所示:

图4:寻找查询参数值的规律

注意:第一个数据包反映了每个类型中电影的总数量,其 url 与响应信息如下:

Response信息:{"playable_count":41,"total":104,"unwatched_count":104}

影片的类型与类型码包含在电影排行榜的主界面中,如下所示:

图5:影片类型与类型码

分析上述页面结构,然后使用正则表达式来提取想要的数据,并定义选择菜单“menu”,代码如下所示:

完成上述分析后,下面开始编写 Python 爬虫程序,代码如下:

输出示例:

剧情|喜剧|动作|爱情|科幻|动画|悬疑|惊悚|恐怖|纪录片|短片|情色|同性|音乐|歌舞|家庭|儿童|传记|历史|战争|犯罪|西部|奇幻|冒险|灾难|武侠|古装|运动|黑色电影|

你想了解什么类型电影:科幻

{'name': '盗梦空间', 'score': 9.3}

{'name': '星际穿越', 'score': 9.3}

{'name': '楚门的世界', 'score': 9.3}

{'name': '机器人总动员', 'score': 9.3}

{'name': '蝙蝠侠:黑暗骑士', 'score': 9.2}

{'name': '超感猎杀:完结特别篇', 'score': 9.2}

{'name': '新世纪福音战士 第0:0话 诞生之始', 'score': 9.2}

{'name': '少年骇客:变身之谜', 'score': 9.2}

...

...

电影总数量:147部

最后我们对抓取动态网站数据做简单地总结:

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,遵循欧洲计算机协会制定的 JavaScript 规范(简称 ECMAScript)。JSON 易于人阅读和编写,同时也易于机器解析和生成,能够有效的提升网信息的传输效率,因此它常被作为网络、程序之间传递信息的标准语言,比如客户端与服务器之间信息交互就是以 JSON 格式传递的。简单地说,JSON 可以将 JavaScript 对象表示的一组数据转换为字符串格式,以便于在网络、程序间传输这个字符串。并且在需要的时候,您还可以将它转换为编程语言所支持的数据格式。本节主要介绍如何实现 JSON 数据与 Python 数据类型间的相互转换。Python 语言内置了专门处理 JOSN 数据的模块 —— jons 模块,通过该模块就可以完成 JSON 与 Python 两种数据格式的相互转换。

该方法可以将 json 格式的字符串转换成 Python 对象(比如列表、字典、元组、整型以及浮点型),其中最常用的是转换为字典类型。示例如下:

输出结果:

python字典数据格式:{'name': 'c语言中文网', 'PV': '50万', 'UV': '20万', 'create_time': '2010年'};数据类型:<class 'dict'>

注意:上述示例中 JSON 字符串看上去和 Python 字典非常相似,但是其本质不同,JOSN 是字符串类型,而 Python 字典是 dict 类型。

参数说明如下:

示例示例如下:

"name": "c语言中文网",

"PV": "50万",

"UV": "20万",

"create_time": "2010年"

您也可以将 Python 列表转换成 JSON 字符串,并保存至 json 文件中,如下所示:

该方法用于操作文件流对象,不过它与 dump() 恰好相反,它表示从  json 文件中读取 JSON 字符串,并将读取内容转换为 Python 对象。使用示例如下:

输出结果如下:

该方法可以将 Python 对象转换成 JSON 字符串。示例如下:

输出结果如下:

转换之后的数据类型为: <class 'str'>

最后对上述方法做简单地总结,如下表所示:

JSON方法总结

方法

作用

将 Python 对象转换成 JSON 字符串。

将 JSON 字符串转换成 Python 对象。

将 Python 中的对象转化成 JSON 字符串储存到文件中。

将文件中的 JSON 字符串转化成 Python 对象提取出来。

在使用爬虫采集数据的规程中,我们会遇到许多不同类型的网站,比如一些网站需要用户登录后才允许查看相关内容,如果遇到这种类型的网站,又应该如何编写爬虫程序呢?Cookie 模拟登录技术成功地解决了此类问题。Cookie 是一个记录了用户登录状态以及用户属性的加密字符串。当你第一次登陆网站时,服务端会在返回的 Response Headers 中添加 Cookie, 浏览器接收到响应信息后,会将 Cookie 保存至浏览器本地存储中,当你再次向该网站发送请求时,请求头中就会携带 Cookie,这样服务器通过读取 Cookie 就能识别登陆用户了。

提示:我们所熟知的“记住密码”功能,以及“老用户登陆”欢迎语,这些都是通过 Cookie 实现的。

首先你要注册一个人人网的账号,注册过中要填写个人资料,以便后续抓取数据使用。注册成功后点击上方头像进入我的主页(或左侧主页选项卡),如下图所示:

图1:人人网主界面

然后使用 F12 打开调试工具,刷新页面来抓取登录时的数据包(包名:timeline...开头), 并在 Headers 选项中找到请求头中的 Cookie 信息,将 Cookie 值拷贝下来,以备后续使用。如下所示:

图2:浏览Headers信息

确定了 Cookie 信息后,接下来分析页面元素结构。通过调试工具审查如图 1 所示的个人信息栏,其元素结构如下:

由此可知其 Xpath 表达式为:

完成程序如下所示:

最后关闭“人人网”网站,运行上述程序,其结果如下:

['就读于电子科技大学']

['男生', ',7月7日']

{'hometown': '来自 北京 西城区', 'address': '现居 上海'

网络爬虫程序是一种 IO 密集型程序,程序中涉及了很多网络 IO 以及本地磁盘 IO 操作,这些都会消耗大量的时间,从而降低程序的执行效率,而 Python 提供的多线程能够在一定程度上提升 IO 密集型程序的执行效率。

Python 提供了两个支持多线程的模块,分别是 _thread 和 threading。其中 _thread 模块偏底层,它相比于 threading 模块功能有限,因此推荐大家使用 threading 模块。 threading 中不仅包含了  _thread 模块中的所有方法,还提供了一些其他方法,如下所示:

线程的具体使用方法如下所示:

创建多线程的具体流程:

除了使用该模块外,您也可以使用  Thread  线程类来创建多线程。在处理线程的过程中要时刻注意线程的同步问题,即多个线程不能操作同一个数据,否则会造成数据的不确定性。通过 threading 模块的 Lock 对象能够保证数据的正确性。比如,使用多线程将抓取数据写入磁盘文件,此时,就要对执行写入操作的线程加锁,这样才能够避免写入的数据被覆盖。当线程执行完写操作后会主动释放锁,继续让其他线程去获取锁,周而复始,直到所有写操作执行完毕。具体方法如下所示:

对于 Python 多线程而言,由于 GIL 全局解释器锁的存在,同一时刻只允许一个线程占据解释器执行程序,当此线程遇到 IO 操作时就会主动让出解释器,让其他处于等待状态的线程去获取解释器来执行程序,而该线程则回到等待状态,这主要是通过线程的调度机制实现的。由于上述原因,我们需要构建一个多线程共享数据的模型,让所有线程都到该模型中获取数据。queue(队列,先进先出) 模块提供了创建共享数据的队列模型。比如,把所有待爬取的 URL 地址放入队列中,每个线程都到这个队列中去提取 URL。queue 模块的具体使用方法如下:

图1:小米应用商城

抓取下来的数据 demo 如下所示:

通过搜索关键字可知这是一个动态网站,因此需要抓包分析。刷新网页来重新加载数据,可得知请求头的 URL 地址,如下所示:

其中查询参数 pageSize 参数值不变化,page 会随着页码的增加而变化,而类别 Id 通过查看页面元素,如下所示

基准表达式:xpath_bds = '//ul[@class="category-list"]/li'

点击开发者工具的 response 选项卡,查看响应数据,如下所示:

count: 2000,

data: [

appId: 1348407,

displayName: "天气暖暖-关心Ta从关心天气开始",

level1CategoryName: "居家生活",

},

appId: 1348403,

displayName: "贵斌同城",

level1CategoryName: "居家生活",

},

...

...

通过上述响应内容,我们可以从中提取出 APP 总数量(count)和 APP (displayName)名称,以及下载详情页的 packageName。由于每页中包含了 30 个 APP,所以总数量(count)可以计算出每个类别共有多少页。

pages = int(count) // 30 + 1

下载详情页的地址是使用 packageName 拼接而成,如下所示:

完整程序如下所示:

运行上述程序后,打开存储文件,其内容如下:

Beautiful Soup 简称 BS4(其中 4 表示版本号)是一个 Python 第三方库,它可以从 HTML 或 XML 文档中快速地提取指定的数据。Beautiful Soup 语法简单,使用方便,并且容易理解,因此您可以快速地学习并掌握它。本节我们讲解 BS4 的基本语法。

图1:BS4官网LOGO图

由于 Bautiful Soup 是第三方库,因此需要单独下载,下载方式非常简单,执行以下命令即可安装:

pip install bs4

由于 BS4 解析页面时需要依赖文档解析器,所以还需要安装 lxml 作为解析库:

pip install lxml

pip install html5lib

该解析器生成 HTML 格式的文档,但速度较慢。

“解析器容错”指的是被解析的文档发生错误或不符合格式时,通过解析器的容错性仍然可以按照既定的正确格式实现解析。

创建 BS4 解析对象是万事开头的第一步,这非常地简单,语法格式如下所示:

输出结果:

如果是外部文档,您也可以通过 open() 的方式打开读取,语法格式如下:

下面对爬虫中经常用到的 BS4 解析方法做详细介绍。Beautiful Soup 将 HTML 文档转换成一个树形结构,该结构有利于快速地遍历和搜索 HTML 文档。下面使用树状结构来描述一段 HTML 文档:

树状图如下所示:

图1:HTML文档树结构图

文档树中的每个节点都是 Python 对象,这些对象大致分为四类:Tag , NavigableString , BeautifulSoup , Comment 。其中使用最多的是 Tag 和 NavigableString。

标签(Tag)是组成 HTML 文档的基本元素。在 BS4 中,通过标签名和标签属性可以提取出想要的内容。看一组简单的示例:

输出结果如下:

soup.p输出结果:

soup.p.b输出结果:

{'class': ['Web', 'site', 'url']}

type(soup.p)输出结果:

soup.p['class']输出结果:

['Web', 'site', 'url']

class属性重新赋值:

Tag 对象提供了许多遍历 tag 节点的属性,比如 contents、children 用来遍历子节点;parent 与 parents 用来遍历父节点;而 next_sibling 与 previous_sibling 则用来遍历兄弟节点 。示例如下:

输出结果:

<body>

<p class="website">一个学习编程的网站</p>

</body>

#以列表的形式输出

Tag 的 children 属性会生成一个可迭代对象,可以用来遍历子节点,示例如下:

输出结果:

#注意此处已将换行符"\n"省略

<p class="website">一个学习编程的网站</p>

find_all() 与 find() 是解析 HTML 文档的常用方法,它们可以在 HTML 文档中按照一定的条件(相当于过滤器)查找所需内容。find() 与 find_all() 的语法格式相似,希望大家在学习的时候,可以举一反三。

BS4 库中定义了许多用于搜索的方法,find() 与 find_all() 是最为关键的两个方法,其余方法的参数和使用与其类似。

find_all() 方法用来搜索当前 tag 的所有子节点,并判断这些节点是否符合过滤条件,最后以列表形式将符合条件的内容返回,语法格式如下:

find_all( name , attrs , recursive , text , limit )

参数说明:

find_all() 使用示例如下:

最后以列表的形式返回输出结果,如下所示:

按照标签属性以及属性值查找 HTML 文档,如下所示

输出结果:

[<p class="website">一个学习编程的网站</p>]

正则表达式、列表,以及 True 也可以当做过滤条件,使用示例如下:

输出结果如下:

第一个print输出:

第二个print输出:

第三个print输出:

第四个print输出:

html head title body p b p a a a p a

最后一个输出:

body b

BS4 为了简化代码,为 find_all() 提供了一种简化写法,如下所示:

上述两种的方法的输出结果是相同的。

find() 方法与 find_all() 类似,不同之处在于 find_all() 会将文档中所有符合条件的结果返回,而 find() 仅返回一个符合条件的结果,所以 find() 方法没有limit参数。使用示例如下:

输出结果如下:

a标签:

title:

<title>"c语言中文网"</title>

正则匹配:

#attrs参数值

<p class="vip">加入我们阅读所有教程</p>

使用 find() 时,如果没有找到查询标签会返回 None,而 find_all() 方法返回空列表。示例如下:

输出结果如下:

None

[]

BS4 也为 find()提供了简化写法,如下所示:

两种写法的输出结果相同,如下所示:

<title>"c语言中文网"</title>

<title>"c语言中文网"</title>

BS4 支持大部分的 CSS 选择器,比如常见的标签选择器、类选择器、id 选择器,以及层级选择器。Beautiful Soup 提供了一个 select() 方法,通过向该方法中添加选择器,就可以在 HTML 文档中搜索到与之对应的内容。应用示例如下:

输出结果:

第一个输出:

[<title>"c语言中文网"</title>]

第二个输出:

第三个输出:

[<p class="vip">加入我们阅读所有教程</p>]

第四个输出:

[<title>"c语言中文网"</title>]

第五个输出:

第六个输出:

第七个输出:

第八个输出:

最后的print输出:

首先判网站属于静态网站,因此您的主要任务是分析网页元素的组成,然后使用 BS4 提取所需的信息。如下所示:

图1:网页元素分析

提取到 a 标签是解决本程序的重点,a 标签的页面代码结构如下所示:

从上述代码可以看出,a 标签包含了目录名称以及详情页的地址链接。那么如何获取 a 标签呢?经过简单分析后可知 a 标签属于 div > ul > li 的子节点,因此可以使用 BS4 的 select() 获取。如下所示:

最后一步是提取具体的内容。通过分析详情页的元素构成可知,我们想要的内容都包含在以下标签中:

<div class="chapter_content">

具体内容

</div>

因此使用 BS4 的 find() 方法就可以获取所需内容,如下所示:

之后把获取的内容写入到 txt 文件中就可以了。下面我使用之前学习过的 urllib 模块与 BS4 模块编写爬虫程序,这样才能做到温故而知新。

代码如下所示,程序中已经做了详细的注释:

程序运行结果:

正在下载:-**--自序--**-......

结束下载:-**--自序--**-

正在下载:-**--第一回 祀南郊司马开基 立东宫庸雏伏祸--**-......

结束下载:-**--第一回 祀南郊司马开基 立东宫庸雏伏祸--**-

正在下载:-**--第二回 堕诡计储君纳妇 慰痴情少女偷香--**-......

....

由于生成的 .txt 文件中内容过多,这里就不再做展示了。

Selenium 是一个用于测试 Web 应用程序的自动化测试工具,它直接运行在浏览器中,实现了对浏览器的自动化操作,它支持所有主流的浏览器,包括 IE,Firefox,Safari,Chrome 等。Selenium 支持所有主流平台(如,Windows、Linux、IOS、Android、Edge、Opera等),同时,它也实现了诸多自动化功能,比如软件自动化测试,检测软件与浏览器兼容性,自动录制、生成不同语言的测试脚本,以及自动化爬虫等。本节及后续两节主要围绕自动化爬虫展开讲解。

图1:Python Selenium

Selenium 提供了一个工具集,包括 Selenium WebDriver(浏览器驱动)、Selenium IDE(录制测试脚本)、Selenium Grid(执行测试脚本)。后面两个主要用于测试脚本的录制、执行,因此不做介绍。我们只对 Selenium WebDriver 做重点讲解。

Selenium 安装非常简单,Linux、Mac 用户执行以下命令即可:

sudo pip install Selenium

Windows 用户执行以下命令即可实现安装:

python -m pip install selenium

若想使 Selenium 能够调用浏览器,那么必须通过 webdriver 驱动来实现。不同的浏览器需要使用不同驱动程序,下面列出了不同浏览器驱动程序的下载地址:

各种浏览器的驱动安装规程基本一致。不过需要注意:安装 Chrome、Firefox 驱动时,需要下载与浏览器版本相匹配的驱动程序,否则不能驱动浏览器。而 IE 较为特殊,您需要下载与 Selenium 版本相匹配的驱动文件,如下所示:

图1:IE 驱动下载

where python

您需要根据自己安装路径进行配置,我的环境变量配置如下:

图2:配置环境变量

上述操作完成后,在 CMD 命令行启动驱动程序,如下所示:

图3:驱动开启成功

开启成功后,驱动程序会在后台运行。

编写如下代码,实现自动化访问百度。

截取了运行中的显示结果,如下所示:

图4:Selenium自动化访问百度

经过上述代测试,说明我们安装的浏览器驱动可以正常工作。Selenium WebDriver 实现了许多操作浏览器功能。比如实现自动点击、自动输入、自动搜索、自动登录等等。毫不夸张的说,Selenium 自动化爬虫是一种万能的爬虫程序,它可以仿照人的样子去打开网站,并拿到你想要的数据,因此你无须在意反爬措施。不过它最致命的缺点就是效率很低,因为每次点击、输入等操作都需要花费一定的时间,因此它仅适用于小批量的数据抓取。

Selenium 作为一款 Web 自动化测试框架,提供了诸多操作浏览器的方法,本节对其中的常用方法做详细介绍。

Selenium 提供了 8 种定位单个节点的方法,如下所示:

定位节点方法

方法

说明

find_element_by_id()

通过 id 属性值定位

find_element_by_name()

通过 name 属性值定位

find_element_by_class_name()

通过 class 属性值定位

find_element_by_tag_name()

通过 tag 标签名定位

find_element_by_link_text()

通过<a>标签内文本定位,即精准定位。

find_element_by_partial_link_text()

通过<a>标签内部分文本定位,即模糊定位。

find_element_by_xpath()

通过 xpath 表达式定位

find_element_by_css_selector()

通过 css 选择器定位

假设下面代码某个页面的代码片段,如下所示:

下面使用表格中提供的方法定位 input 输出框。如下所示:

通过 a 标签内的文本内容定位节点,如下所示:

示例如下:

如果您想定位一组元素,方法如下所示:

find_elements_by_id()

find_elements_by_name()

find_elements_by_class_name()

find_elements_by_tag_name()

find_elements_by_link_text()

find_elements_by_partial_link_text()

find_elements_by_xpath()

find_elements_by_css_selector()

定位一组元素的方法与定位单个元素类似,唯一的区别就是 element 后面多了一个 s(表示复数),因此上述方法的返回值是一个列表,您可以使用 for 循环拿到所有的元素节点。

Selenium 可以操控浏览器的窗口大小、刷新页面,以及控制浏览器的前进、后退等

上文中介绍了如何定位元素,以及如何设置浏览的大小、位置。 定位元素节点只是第一步, 定位之后还需要对这个元素进行操作, 比如单击按钮,或者在输入框输入文本 , 下面介绍 WebDriver 中的最常用方法:

# 请求url

get(url)

# 模拟键盘输入文本

send_keys (value)

# 清除已经输入的文本

clear():

# 单击已经定位的元素

click():

# 用于提交表单,比如百度搜索框内输入关键字之后的“回车” 操作

submit():

#返回属性的属性值,返回元素的属性值,可以是id、name、type 或其他任意属性

get_attribute(name)

# 返回布尔值,检查元素是否用户可见,比如 display属性为hidden或者none

is_displayed()

示例如下:

除了上述方法外, WebDriver 还有一些常用属性,如下所示:

输出结果:

©2015 Baidu 使用百度前必读 意见反馈 京 ICP 证 030173 号

{'width': 500, 'height': 22}

Selenium WebDriver 提供了一些事件处理函数(鼠标、键盘等),下面我们对常用的事件函数做简单介绍。

Selenium WebDriver 将关于鼠标的操作方法都封装在 ActionChains 类中,使用时需要引入 ActionChains 类,如下所示:

该类包含了鼠标操作的常用方法:

鼠标事件

方法

说明

ActionChains(driver)

构造 ActionChains 鼠标对象。

click()

单击

click_and_hold(on_element=None)

单击鼠标左键,不松开

context_click()

右击

double_click()

双击

drag_and_drop()

拖动

move_to_element(above)

执行鼠标悬停操作

context_click()

用于模拟鼠标右键操作, 在调用时需要指定元素定位。

perform()

将所有鼠标操作提交执行。

示例如下:

Selenium  WebDriver 的 Keys 模块提供了模拟键盘输入的 send_keys() 方法,除此之外,该模块也提供了操作键盘的其他方法,比如复制、粘贴等等。在使用之前,首先需要导入 Keys 类,如下所示:

下面列举了一些常用方法:

键盘操作

方法

说明

删除键(BackSpace)

空格键(Space)

制表键(Tab)

回退键(Esc)

回车键(Enter)

全选(Ctrl+A)

复制(Ctrl+C)

剪切(Ctrl+X)

粘贴(Ctrl+V)

send_keys(Keys.F1…Fn)

键盘 F1…Fn

按下键盘上的某个键

松开键盘上的某个键

示例如下:

其它键盘操作方法,如下所示:

Chromedriver 每一次运行都要打开浏览器,并执行相应的输入、搜索等操作,这样会导致浏览器交互能力变差,浪费许多时间。 Selenium 为了增强浏览器的交互能力,允许您使用无头浏览器模式,也就是无界面浏览器,它被广泛的应用于爬虫和自动化测试中。通过以下代码可以设置无头浏览器模式:

除了可以设置无头界面之外,Selenium 还支持其他一些浏览器参数设置,如下所示:

proxy_host='host',

proxy_port='port',

proxy_username="username",

proxy_password="password"

))# 设置有账号密码的代理

WebDriver 提供了 execute_script() 方法来执行 JavaScript 代码,比如控制浏览器的滚动条。示例如下:

{'name': 'Python编程 从入门到实践 第2版 人民邮电出版社', 'price': '¥52.50', 'count': '200+条评价', 'shop': '智囊图书专营店'}

{'name': 'Python编程 从入门到实践 第2版(图灵出品)', 'price': '¥62.10', 'count': '20万+条评价', 'shop': '人民邮电出版社'}

...

Selenium 框架的学习重点在于定位元素节点,关于如何定位,我们已经介绍了 8 种方法,其中 Xpath 表达式适用性强,并且便捷。因此,建议大家多多熟悉 Xpath 表达式的相关语法规则。本节案例中很大一部分采用了 Xpath 表达式定位元素,希望帮助您温故知新。本节案例中涉及了几个技术难点:第一,如何下拉滚动条下载商品,第二,如何实现翻页,也就是抓取下一页的内容,第三,如何判断数据已经抓取完毕,即终止页。下面我们逐步讲解。

实现自动输出、自动搜索是最基础的一步。首先定位输入框的的节点,其次定位搜索按钮节点,这与实现百度自动搜索思路一致,最关键就是要正确定位元素节点。通过开发者调试工具检查相应的的位置,可得如下 Xpath 表达式:

输入框表达式://*[@id="key"]

搜索按钮表达式://*[@class='form']/button

代码如下所示:

实现了自动搜索后,接下来就是要抓取页面中的商品信息,而您会发现只有将滑动条滚动至底部,商品才会全部加载完毕。滚动滑轮操作的代码如下:

之后在通过 Xpath 表达式匹配所有商品,并将它们放入一个大列表中,通过循环列表取出每个商品,最后提取出想要的信息。

如何实现翻页抓取数据,并判断数据数据已经抓取完毕呢?这其实并不难想到,我们可以先跳至终止页(即最后一页)。此时最后一页的“下一页”处于不可用状态,其元素节点如下:

终止页下一页class属性:<a class="pn-next disabled"><em>下一页</em><i> > </i></a>

如果页面源码中有上述代码存在,则证明此页是最后一页,若没有则不是。因此通过 if ...else 语句即可实现上述需求,如下所示:

完整程序代码如下所示:

输出结果如下:

{'name': 'Python编程 从入门到实践 第2版(图灵出品) 人民邮电出版社', 'price': '¥52.50', 'count': '200+条评价', 'shop': '智囊图书专营店'}

{'name': 'Python编程 从入门到实践 第2版(图灵出品)', 'price': '¥62.10', 'count': '20万+条评价', 'shop': '人民邮电出版社'}

{'name': 'Python编程三剑客:Python编程从入门到实践第2版+快速上手第2版+极客编程(套装共3册)', 'price': '¥206.90', 'count': '5万+条评价', 'shop': '人民邮电出版社'}

{'name': 'Python数据分析从入门到实践(excel高效办公)(3全彩版)', 'price': '¥46.10', 'count': '10万+条评价', 'shop': '明日科技京东自营旗舰店'}

{'name': '零基础学Python(编程入门 项目实践 同步视频)(3全彩版)', 'price': '¥37.50', 'count': '10万+条评价', 'shop': '明日科技京东自营旗舰店'}

{'name': 'Python编程快速上手 让繁琐工作自动化 第2版', 'price': '¥44.50', 'count': '10万+条评价', 'shop': '人民邮电出版社'}

{'name': '现货包邮Python学习手册(原书第5版)上下册2本/计算机编程设计|8053406', 'price': '¥142.30', 'count': '100+条评价', 'shop': '互动创新图书专营店'}

{'name': '零基础入门学习Python(第2版)', 'price': '¥70.30', 'count': '1万+条评价', 'shop': '清华大学出版社'}

{'name': '超简单:用Python让Excel飞起来', 'price': '¥34.90', 'count': '2万+条评价', 'shop': '机械工业出版社自营官方旗舰店'}

{'name': '流畅的Python(图灵出品)', 'price': '¥109.80', 'count': '2万+条评价', 'shop': '人民邮电出版社'}

{'name': 'Python编程从入门到实践第二版 python编程从入门到实战零基础自学教程计算机基础语言数据分析', 'price': '¥49.80', 'count': '5000+条评价', 'shop': '墨马图书旗舰店'}

{'name': 'Python深度学习:基于PyTorch', 'price': '¥73.40', 'count': '5万+条评价', 'shop': '机械工业出版社自营官方旗舰店'}

{'name': 'Python自然语言处理实战:核心技术与算法 自然语言处理教程', 'price': '¥48.30', 'count': '37条评价', 'shop': '芝麻开门图书专营店'}

{'name': 'Effective Python:编写高质量Python代码的90个有效方法(原书第2版)', 'price': '¥110.60\n¥105.10', 'count': '2万+条评价', 'shop': '机械工业出版社自营官方旗舰店'}

...

Selenium 自动化爬虫让你无须关心网站的类型(静态或者动态),只需您按部就班的寻找元素节点,并依此点击,即可实现数据抓取。不过  Selenium 最大的缺点就是效率低,因此它只适合做小规模的数据采集工作。

Scrapy 是一个基于 Twisted 实现的异步处理爬虫框架,该框架使用纯 Python 语言编写。Scrapy 框架应用广泛,常用于数据采集、网络监测,以及自动化测试等。

提示:Twisted 是一个基于事件驱动的网络引擎框架,同样采用 Python 实现。

Scrapy 支持常见的主流平台,比如 Linux、Mac、Windows 等,因此你可以很方便的安装它。本节以 Windows 系统为例,在 CMD 命令行执行以下命令:

python -m pip install Scrapy

C:\Users\Administrator>python

Python 3.7.4 (tags/v3.7.4:e09359112e, Jul  8 2019, 19:29:22) [MSC v.1916 32 bit (Intel)] on win32

Type "help", "copyright", "credits" or "license" for more information.

>>> import scrapy

>>> exit()

如果可以正常执行exit()操作,并且没有出现 ERROR 错误,则说明安装成功。

Scrapy 框架提供了一些常用的命令用来创建项目、查看配置信息,以及运行爬虫程序。常用指令如下所示:

常用指令

命令

格式

说明

startproject

scrapy startproject <项目名>

创建一个新项目。

genspider

scrapy genspider <爬虫文件名> <域名>

新建爬虫文件。

runspider

scrapy runspider <爬虫文件>

运行一个爬虫文件,不需要创建项目。

crawl

scrapy crawl <spidername>

运行一个爬虫项目,必须要创建项目。

list

scrapy list

列出项目中所有爬虫文件。

view

scrapy view <url地址>

从浏览器中打开 url 地址。

shell

csrapy shell <url地址>

命令行交互模式。

settings

scrapy settings

查看当前项目的配置信息。

下面创建名为 Baidu 的爬虫项目,打开 CMD 命令提示符进行如下操作:

C:\Users\Administrator>cd Desktop

C:\Users\Administrator\Desktop>scrapy startproject Baidu

New Scrapy project 'Baidu', using template directory 'd:\python\python37\lib\site-packages\scrapy\templates\project', created in:

C:\Users\Administrator\Desktop\Baidu

# 提示后续命令操作

You can start your first spider with:

cd Baidu

打开新建的项目“Baidu”会有以下项目文件,如图所示:

图1:项目文件

接下来,创建一个爬虫文件,如下所示:

C:\Users\Administrator\Desktop>cd Baidu

Created spider 'baidu' using template 'basic' in module:

下面呈现了项目的目录树结构,以及各个文件的作用:

Baidu                   # 项目文件夹

├── Baidu               # 用来装载项目文件的目录

│   └── spiders         # 用来装载爬虫文件的目录

从上述目录结构可以看出,Scrapy 将整个爬虫程序分成了不同的模块,让每个模块负责处理不同的工作,而且模块之间紧密联系。因此,您只需要在相应的模块编写相应的代码,就可以轻松的实现一个爬虫程序。

Scrapy 框架由五大组件构成,如下所示:

Scrapy 五大组件

名称

作用说明

Engine(引擎)

整个 Scrapy 框架的核心,主要负责数据和信号在不同模块间传递。

Scheduler(调度器)

用来维护引擎发送过来的 request 请求队列。

Downloader(下载器)

接收引擎发送过来的 request 请求,并生成请求的响应对象,将响应结果返回给引擎。

Spider(爬虫程序)

处理引擎发送过来的 response, 主要用来解析、提取数据和获取需要跟进的二级URL,然后将这些数据交回给引擎。

Pipeline(项目管道)

用实现数据存储,对引擎发送过来的数据进一步处理,比如存  MySQL 数据库等。

在整个执行过程中,还涉及到两个 middlewares 中间件,分别是下载器中间件(Downloader Middlewares)和蜘蛛中间件(Spider Middlewares),它们分别承担着不同的作用:

Scrapy 工作流程示意图如下所示:

图1:工作流程示意图

上述示意图描述如下,当一个爬虫项目启动后,Scrapy 框架会进行以下工作:

上述过程会一直循环,直到没有要爬取的 URL 为止,也就是 URL 队列为空时才会停止。

在使用 Scrapy 框架时,还需要对配置文件进行稍微改动。下面使用 Pycharm 打开刚刚创建的“Baidu”项目,对配置文件进行如下修改:

# 1、定义User-Agent

USER_AGENT = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)'

# 2、是否遵循robots协议,一般设置为False

ROBOTSTXT_OBEY = False

# 3、最大并发量,默认为16

CONCURRENT_REQUESTS = 32

DOWNLOAD_DELAY = 1

其余常用配置项介绍:

# 设置日志级别,DEBUG < INFO < WARNING < ERROR < CRITICAL

LOG_LEVEL = ' '

# 将日志信息保存日志文件中,而不在终端输出

LOG_FILE = ''

# 设置导出数据的编码格式(主要针对于json文件)

FEED_EXPORT_ENCODING = ''

# 非结构化数据的存储路径

IMAGES_STORE = '路径'

# 请求头,此处可以添加User-Agent、cookies、referer等

DEFAULT_REQUEST_HEADERS={

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',

'Accept-Language': 'en',

# 项目管道,300 代表激活的优先级 越小越优先,取值1到1000

ITEM_PIPELINES={

# 添加下载器中间件

DOWNLOADER_MIDDLEWARES = {}

在 CMD 命令行执行以下命令创建项目以及爬虫文件:

# 创建项目

1) scrapy startproject Title

# 进入项目

2) cd Title

# 创建爬虫文件

下面修改 settings 文件的配置项,如下所示:

USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1'

ROBOTSTXT_OBEY = False

DEFAULT_REQUEST_HEADERS = {

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',

'Accept-Language': 'en',

# scrapy 框架运行时输出的日志,包含很多信息,比如版本信息,执行过程等等

...

...

# 此处是我们要的信息

--------------------------------------------------

C语言中文网:c语言程序设计门户网站(入门教程、编程软件)

--------------------------------------------------

{'downloader/request_bytes': 231,

...

在 Scrapy 框架中,每个模块之间既紧密联系,但又相互独立,这样的设计减少了代码之间耦合度,是代码简洁易懂。

最后,我们使用 Scrapy 框架完成一个完整的案例:抓取猫眼电影 Top100 榜。

scrapy startproject Maoyan100

#进入项目目录

cd Maoyan100

# 创建爬虫文件,注意url 一定要是网站域名

注意:指定 -o 参数,可以将数据以特定的文件格式保存,比如 csv、txt、josn 等。

最后修改配置文件,主要有修改以下内容:添加日志输出、激活管道 pipelines、定义数据库常量,以及其他一些常用选项,如下所示:

ROBOTSTXT_OBEY = False

#设置日志级别: DEBUG < INFO < WARNING < ERROR < CRITICAL

#日志需要自己添加,配置文件中没有,在空白处添加即可

LOG_LEVEL='DEBUG'

#定义日志输出文件

#设置导出数据的编码格式

FEED_EXPORT_ENCODING='utf-8'

DOWNLOAD_DELAY = 1

#请求头,添加useragent等信息

DEFAULT_REQUEST_HEADERS = {

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',

'Accept-Language': 'en',

'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1'

#激活管道,并添加数据存放mysql的类,200为执行优先级

ITEM_PIPELINES = {

# 执行数据存储mysql

#在配置文件末尾添加mysql常用变量

MYSQL_HOST='localhost'

MYSQL_USER='root'

MYSQL_PWD='123456'

MYSQL_DB='maoyandb'

MYSQL_CHARSET='utf8'

...

{'name': '肖申克的救赎',

'star': '主演:蒂姆·罗宾斯,摩根·弗里曼,鲍勃·冈顿',

THE END
0.豆瓣读书去购买 10. 空腹力 [日] 石原结实 去购买 豆瓣图书250更多» 南京大屠杀 有电子书 梦里花落知多少 上学记 王尔德童话 诗经 置身事内 有电子书 大明王朝1566 有电子书 國史大綱(上下) 球状闪电 联系我们 合作联系: 关注我们 豆瓣小站 微博 微信jvzq<84fqwhbp7hqo1hpqt
1.童书出版物排行榜电子书在线阅读美国国家地理肉食植食排行榜(套装全两册) 刘大灰 ¥93.99 肉食恐龙科普书,54种肉食恐龙聚集于此;这也是一个好玩儿的排行榜,比一 比这些肉食恐龙的战斗力谁强谁弱。书中在介绍肉食恐龙的过程中,还穿插了大量关于 恐龙常识、*挖掘故事等描述,旨在以生动的内容引起小恐龙迷的兴趣。 植食恐龙科普书,54种植食恐龙聚集jvzq<84g0fgoimfpi0ipo8qkuv3UU6sgygyu/92;;0nuou
2.图书馆小东西自己上来斯洛文尼亚美国电影全集高清在线观看重置筛选 已选 电影 类型 全部 动作片 喜剧片 爱情片 科幻片 恐怖片 剧情片 战争片 剧情 全部 喜剧 爱情 恐怖 动作 科幻 剧情 战争 警匪 犯罪 动画 奇幻 武侠 冒险 枪战 恐怖 悬疑 惊悚 经典 青春 文艺 微电影 古装 历史 运动 农村 儿童 网络电影 jvzq<84yyy464>hjg0ipo7hp1xueuqty133./62///3./7mvon
3.calllast):File"D:\Anaconda\Scripts\jupyter首先,用户的问题是关于解决Jupyter Notebook启动时的PermissionError错误,具体错误是“Permission denied”发生在写入server-info文件和browser_open_file时。用户引用了几个站内引用,但这些引用是示例,我需要基于用户的问题来回答。 用户描述的错误是:启动Jupyter Notebook时,出现PermissionError: [Errno 13] Permission dejvzquC41ygtlw7hufp4og}4cpu}ft86z4i9uq=~l
4.⏮️大地二在线观看免费版电视剧下载免费下载v3.2.3安卓版打开“大地二在线观看免费版电视剧下载”手机浏览器(例如百度浏览器)。在搜索框中输入您想要下载的应用的全名,点击下载链接【cyzxs.cn】网址,下载完成后点击“允许安装”。 ②使用自带的软件商店 打开“大地二在线观看免费版电视剧下载”的手机自带的“软件商店”(也叫应用商店)。在推荐中选择您想要下载的软件,或者jvzq<84yyy4d{ƒ}u0et0ejycnqm/j}rn
5.whitepaper/tex/lib.bib·MindSpore/mindquantumbooktitle = {Proceedings of the Twenty-Fourth International Conference on Architectural Support for Programming Languages and Operating Systems}, pages = {1001--1014}, year = {2019}, url = {https://dl.acm.orgjvzquC41ikzfg7hqo1sjpmxrqtk0orsfswgov~r1dnuc1m76hckg2==c92k95jjg92?gck;fe264::
6.Yi34BChat🤖 Yi 系列模型是由01.AI从零开始训练的下一代开源大型语言模型。 🙌 作为一款面向双语的语言模型,并在3T多语言语料上进行训练,Yi 系列模型已成为全球最强劲的LLM之一,在语言理解、常识推理、阅读理解等方面展示出巨大潜力。例如, Yi-34B-Chat模型在AlpacaEval排行榜上位列第二(仅次于GPT-4 Turbo),超越了其他jvzquC41yy}/oxignuiprn3ep1spfnqu127bk8^k/5:C/Lmcv/>ck}x1uwsnc{~
7.StableSolidElectrolyteInterphaseFormationInducedbyMonoThe lithium (Li) metal anode is considered to be a promising candidate for next-generation batteries but is impeded by Li dendrites and the resulting poor reversibility. Here, we introduce monoquatjvzquC41rwht0jhu0qxh1mtk136/39731citgwjti{rfv}33e2639=
8.#892664/facebook.github.io/zstd/[2]https://salsa.debian.org/rbalint/dpkg/commits/zstd [0001-dpkg-Add-Zstandard-compression-support.patch(text/x-patch, attachment)] [0002-Add-test-for-zstd-decompression.patch(text/x-patch, attachment)] [0003-dpkg-Support-Zstandard-compressed-packages-with-mult.patchjvzquC41dwmt0mjdkct/q{l1eio.drs1dwmsgyttv0ihkHgwi?>:4?;6
9.MacbookPro201713inchKernalPanicHardware Information: MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports) MacBook Pro Model: MacBookPro14,1 2.3 GHz Dual-Core Intel Core i5 (i5-7360U) CPU: 2-core 8 GB RAM - Not upgradeable BANK 0/DIMM0 - 4 GB LPDDR3 2133 BANK 1/DIMM0 - 4 GB LPDDR3 2133 Battery: HealthjvzquC41fkydw|xkqpy/cyung0ipo8yjtgge1;:494782BDuqtzC{Fgguv
10.→🚀2025·极致启航·卓越体验💫入口🌿官网💎平台“我们书店里每本书只有一本,没有重复的。”书店老板赵华说,“我们没有做特别细致的分类陈列,这反而是我们的特色,书本覆盖全类型,在淘书过程中读者永远不知道下一本会遇到什么惊喜。”这家开业不到两年的旧书店,被很多网友称为“旧书天堂”。 除了去线下旧书店、参加旧书市集,也有不少人去线上淘旧书。 胡淼的jvzq<84o0fjeprhg0et0c{ykenk04977336:1@>4864tj}rn
11.Node.jsv15.9.0(Current)node.lib 55318a8cb06567cbea1cfc6b142fac72bf542a54a17a103e52224f9cb52e1dc6 win-x64/node_pdb.7z 1841543eb6428448b2f2b5d20c62b3a6417374dc71117bb0debb33e5a8ed338d win-x64/node_pdb.zip a1a1dbed3c71823859579c2d21736b183c15277c64ad3de73088b9c0746f38ab win-x86/node.exe 6cec3adfe0cbf4jvzquC41pqjfl|3qti5fp8gnqi5sgujcug5w3>3;025
12.LIBSVMToolsTo use LIBLINEAR, you need the following modifications MATLAB: Copy plotroc.m to the matlab directory (note that matlab interface is included in LIBLINEAR). Replace svmtrain and svmpredict with train and predict, respectively. Authors: Tingfan Wu (svm [at] future.csie.org), Chien-Chih jvzquC41yy}/e|ng0pzv0niw0v}0€lonkp5mkkxxovupn|4
13.成功解决OSError:libcusparse.so.11:cannotopenshared在/home/cenghaolong/anaconda3/envs/BIONIC/lib(你建的虚拟环境的 lib 文件夹) 中放入缺少的 libcusparse.so.11 文件。 如果仍然报错,则在 /home/user/.bashrc 文件最下面,加入下述一行。注意,此路径下需包含 libcusparse.so.11 文件。 具体操作如下: 代码语言:javascripjvzquC41enuvf7ygpekov7hqo1jfxnqqrgx0c{ykenk04:8;738
14.Z本站爱达杂货铺提供的Z-Library都来源于网络,不保证外部链接的准确性和完整性,同时,对于该外部链接的指向,不由爱达杂货铺实际控制,在2022年2月20日 下午4:05收录时,该网页上的内容,都属于合规合法,后期网页的内容如出现违规,可以直接联系网站管理员进行删除,爱达杂货铺不承担任何责任。jvzquC41cf€ir7hp1uoug|477;8/j}rn
15.ChinYiFangFingerprintDive into the research topics where Chin-Yi Fang is active. These topic labels come from the works of this person. Together they form a unique fingerprint. Sort by Weight Alphabetically INIS efficiency 100% performance 92% data 86% restaurants 83% hotels 53% taiwan 46% output 45jvzq<84uejumc{3nkd4ovwz0gf{/v€4gp1vft|tpu1iikw2{k/lbpp4hkpmftywkpvy0