0%

Python

2022 年最新 Python3 网络爬虫教程

大家好,我是崔庆才,由于爬虫技术不断迭代升级,一些旧的教程已经过时、案例已经过期,最前沿的爬虫技术比如异步、JavaScript 逆向、安卓逆向、智能解析、WebAssembly、大规模分布式、Kubernetes 等技术层出不穷,我最近新出了一套最新最全面的 Python3 网络爬虫系列教程。

博主自荐:截止 2022 年,可以将最前沿最全面的爬虫技术都涵盖的教程,如异步、JavaScript 逆向、安卓逆向、智能解析、WebAssembly、大规模分布式、Kubernetes 等,市面上目前就这一套了。

最新教程对旧的爬虫技术内容进行了全面更新,搭建了全新的案例平台进行全面讲解,保证案例稳定有效不过期。

教程请移步:

【2022 版】Python3 网络爬虫学习教程

如下为原文。

前言

大家有没有发现之前我们写的爬虫都有一个共性,就是只能爬取单纯的 html 代码,如果页面是 JS 渲染的该怎么办呢?如果我们单纯去分析一个个后台的请求,手动去摸索 JS 渲染的到的一些结果,那简直没天理了。所以,我们需要有一些好用的工具来帮助我们像浏览器一样渲染 JS 处理的页面。 其中有一个比较常用的工具,那就是 PhantomJS

Full web stack No browser required

PhantomJS is a headless WebKit scriptable with a JavaScript API. It has fast andnative support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG.

PhantomJS 是一个无界面的,可脚本编程的 WebKit 浏览器引擎。它原生支持多种 web 标准:DOM 操作,CSS 选择器,JSON,Canvas 以及 SVG。 好,接下来我们就一起来了解一下这个神奇好用的库的用法吧。

安装

PhantomJS 安装方法有两种,一种是下载源码之后自己来编译,另一种是直接下载编译好的二进制文件。然而自己编译需要的时间太长,而且需要挺多的磁盘空间。官方推荐直接下载二进制文件然后安装。 大家可以依照自己的开发平台选择不同的包进行下载 下载地址 当然如果你不嫌麻烦,可以选择 下载源码 然后自己编译。 目前(2016/3/21)最新发行版本是 v2.1, 安装完成之后命令行输入

1
phantomjs -v

如果正常显示版本号,那么证明安装成功了。如果提示错误,那么请重新安装。 本文介绍大部分内容来自于官方文档,博主对其进行了整理,学习更多请参考 官方文档

快速开始

第一个程序

第一个程序当然是 Hello World,新建一个 js 文件。命名为 helloworld.js

1
2
console.log('Hello, world!');
phantom.exit();

命令行输入

1
phantomjs helloworld.js

程序输出了 Hello,world!程序第二句话终止了 phantom 的执行。 注意:phantom.exit();这句话非常重要,否则程序将永远不会终止。

页面加载

可以利用 phantom 来实现页面的加载,下面的例子实现了页面的加载并将页面保存为一张图片。

1
2
3
4
5
6
7
8
var page = require('webpage').create();
page.open('http://cuiqingcai.com', function (status) {
console.log("Status: " + status);
if (status === "success") {
page.render('example.png');
}
phantom.exit();
});

首先创建了一个 webpage 对象,然后加载本站点主页,判断响应状态,如果成功,那么保存截图为 example.png 以上代码命名为 pageload.js,命令行

1
phantomjs pageload.js

发现执行成功,然后目录下多了一张图片,example.png example 因为这个 render 方法,phantom 经常会用到网页截图的功能。

测试页面加载速度

下面这个例子计算了一个页面的加载速度,同时还用到了命令行传参的特性。新建文件保存为 loadspeed.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var page = require('webpage').create(),
system = require('system'),
t, address;

if (system.args.length === 1) {
console.log('Usage: loadspeed.js <some URL>');
phantom.exit();
}

t = Date.now();
address = system.args[1];
page.open(address, function(status) {
if (status !== 'success') {
console.log('FAIL to load the address');
} else {
t = Date.now() - t;
console.log('Loading ' + system.args[1]);
console.log('Loading time ' + t + ' msec');
}
phantom.exit();
});

程序判断了参数的多少,如果参数不够,那么终止运行。然后记录了打开页面的时间,请求页面之后,再纪录当前时间,二者之差就是页面加载速度。

1
phantomjs loadspeed.js http://cuiqingcai.com

运行结果

1
2
Loading http://cuiqingcai.com
Loading time 11678 msec

这个时间包括 JS 渲染的时间,当然和网速也有关。

代码评估

To evaluate JavaScript code in the context of the web page, use evaluate() function. The execution is “sandboxed”, there is no way for the code to access any JavaScript objects and variables outside its own page context. An object can be returned from evaluate(), however it is limited to simple objects and can’t contain functions or closures.

利用 evaluate 方法我们可以获取网页的源代码。这个执行是“沙盒式”的,它不会去执行网页外的 JavaScript 代码。evalute 方法可以返回一个对象,然而返回值仅限于对象,不能包含函数(或闭包)

1
2
3
4
5
6
7
8
9
var url = 'http://www.baidu.com';
var page = require('webpage').create();
page.open(url, function(status) {
var title = page.evaluate(function() {
return document.title;
});
console.log('Page title is ' + title);
phantom.exit();
});

以上代码获取了百度的网站标题。

1
Page title is 百度一下,你就知道

任何来自于网页并且包括来自 evaluate() 内部代码的控制台信息,默认不会显示。 需要重写这个行为,使用 onConsoleMessage 回调函数,示例可以改写成

1
2
3
4
5
6
7
8
9
10
11
var url = 'http://www.baidu.com';
var page = require('webpage').create();
page.onConsoleMessage = function (msg) {
console.log(msg);
};
page.open(url, function (status) {
page.evaluate(function () {
console.log(document.title);
});
phantom.exit();
});

这样的话,如果你用浏览器打开百度首页,打开调试工具的 console,可以看到控制台输出信息。 重写了 onConsoleMessage 方法之后,可以发现控制台输出的结果和我们需要输出的标题都打印出来了。

1
2
3
4
5
6
7
8
9
10
一张网页,要经历怎样的过程,才能抵达用户面前?
一位新人,要经历怎样的成长,才能站在技术之巅?
探寻这里的秘密;
体验这里的挑战;
成为这里的主人;
加入百度,加入网页搜索,你,可以影响世界。

请将简历发送至 %c ps_recruiter@baidu.com( 邮件标题请以“姓名-应聘XX职位-来自console”命名) color:red
职位介绍:http://dwz.cn/hr2013
百度一下,你就知道

啊,我没有在为百度打广告!

屏幕捕获

Since PhantomJS is using WebKit, a real layout and rendering engine, it can capture a web page as a screenshot. Because PhantomJS can render anything on the web page, it can be used to convert contents not only in HTML and CSS, but also SVG and Canvas.

因为 PhantomJS 使用了 WebKit 内核,是一个真正的布局和渲染引擎,它可以像屏幕截图一样捕获一个 web 界面。因为它可以渲染网页中的人和元素,所以它不仅用到 HTML,CSS 的内容转化,还用在 SVG,Canvas。可见其功能是相当强大的。 下面的例子就捕获了 github 网页的截图。上文有类似内容,不再演示。

1
2
3
4
5
var page = require('webpage').create();
page.open('http://github.com/', function() {
page.render('github.png');
phantom.exit();
});

除了 png 格式的转换,PhantomJS 还支持 jpg,gif,pdf 等格式。 测试样例 其中最重要的方法便是 viewportSize 和 clipRect 属性。 viewportSize 是视区的大小,你可以理解为你打开了一个浏览器,然后把浏览器窗口拖到了多大。 clipRect 是裁切矩形的大小,需要四个参数,前两个是基准点,后两个参数是宽高。 通过下面的小例子感受一下。

1
2
3
4
5
6
7
8
9
10
var page = require('webpage').create();
//viewportSize being the actual size of the headless browser
page.viewportSize = { width: 1024, height: 768 };
//the clipRect is the portion of the page you are taking a screenshot of
page.clipRect = { top: 0, left: 0, width: 1024, height: 768 };
//the rest of the code is the same as the previous example
page.open('http://cuiqingcai.com/', function() {
page.render('germy.png');
phantom.exit();
});

运行结果 germy 就相当于把浏览器窗口拖到了 1024x768 大小,然后从左上角裁切出了 1024x768 的页面。

网络监听

Because PhantomJS permits the inspection of network traffic, it is suitable to build various analysis on the network behavior and performance.

因为 PhantomJS 有网络通信的检查功能,它也很适合用来做网络行为的分析。

When a page requests a resource from a remote server, both the request and the response can be tracked via onResourceRequested and onResourceReceived callback.

当接受到请求时,可以通过改写 onResourceRequested 和 onResourceReceived 回调函数来实现接收到资源请求和资源接受完毕的监听。例如

1
2
3
4
5
6
7
8
9
var url = 'http://www.cuiqingcai.com';
var page = require('webpage').create();
page.onResourceRequested = function(request) {
console.log('Request ' + JSON.stringify(request, undefined, 4));
};
page.onResourceReceived = function(response) {
console.log('Receive ' + JSON.stringify(response, undefined, 4));
};
page.open(url);

运行结果会打印出所有资源的请求和接收状态,以 JSON 格式输出。

页面自动化处理

Because PhantomJS can load and manipulate a web page, it is perfect to carry out various page automations.

因为 PhantomJS 可以加载和操作一个 web 页面,所以用来自动化处理也是非常适合的。

DOM 操作

Since the script is executed as if it is running on a web browser, standard DOM scripting and CSS selectors work just fine.

脚本都是像在浏览器中运行的,所以标准的 JavaScript 的 DOM 操作和 CSS 选择器也是生效的。 例如下面的例子就修改了 User-Agent,然后还返回了页面中某元素的内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var page = require('webpage').create();
console.log('The default user agent is ' + page.settings.userAgent);
page.settings.userAgent = 'SpecialAgent';
page.open('http://www.httpuseragent.org', function(status) {
if (status !== 'success') {
console.log('Unable to access network');
} else {
var ua = page.evaluate(function() {
return document.getElementById('myagent').textContent;
});
console.log(ua);
}
phantom.exit();
});

运行结果

1
2
The default user agent is Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.0 Safari/538.1
Your Http User Agent string is: SpecialAgent

首先打印出了默认的 User-Agent,然后通过修改它,请求验证 User-Agent 的一个站点,通过选择器得到了修改后的 User-Agent。

使用附加库

在 1.6 版本之后允许添加外部的 JS 库,比如下面的例子添加了 jQuery,然后执行了 jQuery 代码。

1
2
3
4
5
6
7
8
9
var page = require('webpage').create();
page.open('http://www.sample.com', function() {
page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
page.evaluate(function() {
$("button").click();
});
phantom.exit()
});
});

引用了 jQuery 之后,我们便可以在下面写一些 jQuery 代码了。

Webpage 对象

在前面我们介绍了 webpage 对象的几个方法和属性,其实它本身还有其它很多的属性。具体的内容可以参考 Webpage Webpage 用例 里面介绍了 webpage 的所有属性,方法,回调。

命令行

Command-line Options PhantomJS 提供的命令行选项有:

--help or -h lists all possible command-line options. Halts immediately, will not run a script passed as argument. [帮助列表] —version or -v prints out the version of PhantomJS. Halts immediately, will not run a script passed as argument. [查看版本] —cookies-file=/path/to/cookies.txt specifies the file name to store the persistent Cookies. [指定存放 cookies 的路径] —disk-cache=[true|false] enables disk cache (at desktop services cache storage location, default is false). Also accepted: [yes|no]. [硬盘缓存开关,默认为关] —ignore-ssl-errors=[true|false] ignores SSL errors, such as expired or self-signed certificate errors (default is false). Also accepted: [yes|no]. [忽略 ssl 错误,默认不忽略] —load-images=[true|false] load all inlined images (default is true). Also accepted: [yes|no]. [加载图片,默认为加载] —local-storage-path=/some/path path to save LocalStorage content and WebSQL content. [本地存储路径,如本地文件和 SQL 文件等] —local-storage-quota=number maximum size to allow for data. [本地文件最大大小] —local-to-remote-url-access=[true|false] allows local content to access remote URL (default is false). Also accepted: [yes|no]. [是否允许远程加载文件,默认不允许] —max-disk-cache-size=size limits the size of disk cache (in KB). [最大缓存空间] —output-encoding=encoding sets the encoding used for terminal output (default is utf8). [默认输出编码,默认 utf8] —remote-debugger-port starts the script in a debug harness and listens on the specified port [远程调试端口] —remote-debugger-autorun runs the script in the debugger immediately: ‘yes’ or ‘no’ (default) [在调试环境下是否立即执行脚本,默认否] —proxy=address:port specifies the proxy server to use (e.g. —proxy=192.168.1.42:8080). [代理] —proxy-type=[http|socks5|none] specifies the type of the proxy server (default is http). [代理类型,默认 http] —proxy-auth specifies the authentication information for the proxy, e.g. —proxy-auth=username:password). [代理认证] —script-encoding=encoding sets the encoding used for the starting script (default is utf8). [脚本编码,默认 utf8] —ssl-protocol=[sslv3|sslv2|tlsv1|any’] sets the SSL protocol for secure connections (default is SSLv3). [SSL 协议,默认 SSLv3] —ssl-certificates-path= Sets the location for custom CA certificates (if none set, uses system default). [SSL 证书路径,默认系统默认路径] —web-security=[true|false] enables web security and forbids cross-domain XHR (default is true). Also accepted: [yes|no]. [是否开启安全保护和禁止异站 Ajax,默认开启保护] —webdriver starts in ‘Remote WebDriver mode’ (embedded GhostDriver): ‘[[:]]’ (default ‘127.0.0.1:8910’) [以远程 WebDriver 模式启动] —webdriver-selenium-grid-hub URL to the Selenium Grid HUB: ‘URLTOHUB’ (default ‘none’) (NOTE: works only together with ‘—webdriver’) [Selenium 接口] —config=/path/to/config.json can utilize a JavaScript Object Notation (JSON) configuration file instead of passing in multiple command-line optionss [所有的命令行配置从 config.json 中读取]

注:JSON 文件配置格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
/* Same as: --ignore-ssl-errors=true */
"ignoreSslErrors": true,

/* Same as: --max-disk-cache-size=1000 */
"maxDiskCacheSize": 1000,

/* Same as: --output-encoding=utf8 */
"outputEncoding": "utf8"

/* etc. */
}

There are some keys that do not translate directly:

* --disk-cache => diskCacheEnabled
* --load-images => autoLoadImages
* --local-storage-path => offlineStoragePath
* --local-storage-quota => offlineStorageDefaultQuota
* --local-to-remote-url-access => localToRemoteUrlAccessEnabled
* --web-security => webSecurityEnabled

以上是命令行的基本配置

实例

在此提供官方文档实例,多对照实例练习,使用起来会更得心应手。 官方实例

结语

以上是博主对 PhantomJS 官方文档的基本总结和翻译,如有差错,希望大家可以指正。另外可能有的小伙伴觉得这个工具和 Python 有什么关系?不要急,后面会有 Python 和 PhantomJS 的综合使用的。

Python

2022 年最新 Python3 网络爬虫教程

大家好,我是崔庆才,由于爬虫技术不断迭代升级,一些旧的教程已经过时、案例已经过期,最前沿的爬虫技术比如异步、JavaScript 逆向、安卓逆向、智能解析、WebAssembly、大规模分布式、Kubernetes 等技术层出不穷,我最近新出了一套最新最全面的 Python3 网络爬虫系列教程。

博主自荐:截止 2022 年,可以将最前沿最全面的爬虫技术都涵盖的教程,如异步、JavaScript 逆向、安卓逆向、智能解析、WebAssembly、大规模分布式、Kubernetes 等,市面上目前就这一套了。

最新教程对旧的爬虫技术内容进行了全面更新,搭建了全新的案例平台进行全面讲解,保证案例稳定有效不过期。

教程请移步:

【2022 版】Python3 网络爬虫学习教程

如下为原文。

前言

之前我们用了 urllib 库,这个作为入门的工具还是不错的,对了解一些爬虫的基本理念,掌握爬虫爬取的流程有所帮助。入门之后,我们就需要学习一些更加高级的内容和工具来方便我们的爬取。那么这一节来简单介绍一下 requests 库的基本用法。 注:Python 版本依然基于 2.7

官方文档

以下内容大多来自于官方文档,本文进行了一些修改和总结。要了解更多可以参考 官方文档

安装

利用 pip 安装

1
$ pip install requests

或者利用 easy_install

1
$ easy_install requests

通过以上两种方法均可以完成安装。

引入

首先我们引入一个小例子来感受一下

1
2
3
4
5
6
7
8
import requests

r = requests.get('http://cuiqingcai.com')
print type(r)
print r.status_code
print r.encoding
#print r.text
print r.cookies

以上代码我们请求了本站点的网址,然后打印出了返回结果的类型,状态码,编码方式,Cookies等内容。 运行结果如下

1
2
3
4
<class 'requests.models.Response'>
200
UTF-8
<RequestsCookieJar[]>

怎样,是不是很方便。别急,更方便的在后面呢。

基本请求

requests库提供了http所有的基本请求方式。例如

1
2
3
4
5
r = requests.post("http://httpbin.org/post")
r = requests.put("http://httpbin.org/put")
r = requests.delete("http://httpbin.org/delete")
r = requests.head("http://httpbin.org/get")
r = requests.options("http://httpbin.org/get")

嗯,一句话搞定。

基本GET请求

最基本的GET请求可以直接用get方法

1
r = requests.get("http://httpbin.org/get")

如果想要加参数,可以利用 params 参数

1
2
3
4
5
import requests

payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.get("http://httpbin.org/get", params=payload)
print r.url

运行结果

1
http://httpbin.org/get?key2=value2&key1=value1

如果想请求JSON文件,可以利用 json() 方法解析 例如自己写一个JSON文件命名为a.json,内容如下

1
2
3
["foo", "bar", {
"foo": "bar"
}]

利用如下程序请求并解析

1
2
3
4
5
import requests

r = requests.get("a.json")
print r.text
print r.json()

运行结果如下,其中一个是直接输出内容,另外一个方法是利用 json() 方法解析,感受下它们的不同

1
2
3
4
["foo", "bar", {
"foo": "bar"
}]
[u'foo', u'bar', {u'foo': u'bar'}]

如果想获取来自服务器的原始套接字响应,可以取得 r.raw 。 不过需要在初始请求中设置 stream=True 。

1
2
3
4
5
r = requests.get('https://github.com/timeline.json', stream=True)
r.raw
<requests.packages.urllib3.response.HTTPResponse object at 0x101194810>
r.raw.read(10)
'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03'

这样就获取了网页原始套接字内容。 如果想添加 headers,可以传 headers 参数

1
2
3
4
5
6
import requests

payload = {'key1': 'value1', 'key2': 'value2'}
headers = {'content-type': 'application/json'}
r = requests.get("http://httpbin.org/get", params=payload, headers=headers)
print r.url

通过headers参数可以增加请求头中的headers信息

基本POST请求

对于 POST 请求来说,我们一般需要为它增加一些参数。那么最基本的传参方法可以利用 data 这个参数。

1
2
3
4
5
import requests

payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.post("http://httpbin.org/post", data=payload)
print r.text

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"args": {},
"data": "",
"files": {},
"form": {
"key1": "value1",
"key2": "value2"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "23",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.9.1"
},
"json": null,
"url": "http://httpbin.org/post"
}

可以看到参数传成功了,然后服务器返回了我们传的数据。 有时候我们需要传送的信息不是表单形式的,需要我们传JSON格式的数据过去,所以我们可以用 json.dumps() 方法把表单数据序列化。

1
2
3
4
5
6
7
import json
import requests

url = 'http://httpbin.org/post'
payload = {'some': 'data'}
r = requests.post(url, data=json.dumps(payload))
print r.text

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"args": {},
"data": "{\"some\": \"data\"}",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "16",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.9.1"
},
"json": {
"some": "data"
},
"url": "http://httpbin.org/post"
}

通过上述方法,我们可以POST JSON格式的数据 如果想要上传文件,那么直接用 file 参数即可 新建一个 a.txt 的文件,内容写上 Hello World!

1
2
3
4
5
6
import requests

url = 'http://httpbin.org/post'
files = {'file': open('test.txt', 'rb')}
r = requests.post(url, files=files)
print r.text

可以看到运行结果如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"args": {},
"data": "",
"files": {
"file": "Hello World!"
},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "156",
"Content-Type": "multipart/form-data; boundary=7d8eb5ff99a04c11bb3e862ce78d7000",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.9.1"
},
"json": null,
"url": "http://httpbin.org/post"
}

这样我们便成功完成了一个文件的上传。 requests 是支持流式上传的,这允许你发送大的数据流或文件而无需先把它们读入内存。要使用流式上传,仅需为你的请求体提供一个类文件对象即可

1
2
with open('massive-body') as f:
requests.post('http://some.url/streamed', data=f)

这是一个非常实用方便的功能。

Cookies

如果一个响应中包含了cookie,那么我们可以利用 cookies 变量来拿到

1
2
3
4
5
6
import requests

url = 'http://example.com'
r = requests.get(url)
print r.cookies
print r.cookies['example_cookie_name']

以上程序仅是样例,可以用 cookies 变量来得到站点的 cookies 另外可以利用 cookies 变量来向服务器发送 cookies 信息

1
2
3
4
5
6
import requests

url = 'http://httpbin.org/cookies'
cookies = dict(cookies_are='working')
r = requests.get(url, cookies=cookies)
print r.text

运行结果

1
'{"cookies": {"cookies_are": "working"}}'

可以已经成功向服务器发送了 cookies

超时配置

可以利用 timeout 变量来配置最大请求时间

1
requests.get('http://github.com', timeout=0.001)

注:timeout 仅对连接过程有效,与响应体的下载无关。 也就是说,这个时间只限制请求的时间。即使返回的 response 包含很大内容,下载需要一定时间,然而这并没有什么卵用。

会话对象

在以上的请求中,每次请求其实都相当于发起了一个新的请求。也就是相当于我们每个请求都用了不同的浏览器单独打开的效果。也就是它并不是指的一个会话,即使请求的是同一个网址。比如

1
2
3
4
5
import requests

requests.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
r = requests.get("http://httpbin.org/cookies")
print(r.text)

结果是

1
2
3
{
"cookies": {}
}

很明显,这不在一个会话中,无法获取 cookies,那么在一些站点中,我们需要保持一个持久的会话怎么办呢?就像用一个浏览器逛淘宝一样,在不同的选项卡之间跳转,这样其实就是建立了一个长久会话。 解决方案如下

1
2
3
4
5
6
import requests

s = requests.Session()
s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
r = s.get("http://httpbin.org/cookies")
print(r.text)

在这里我们请求了两次,一次是设置 cookies,一次是获得 cookies 运行结果

1
2
3
4
5
{
"cookies": {
"sessioncookie": "123456789"
}
}

发现可以成功获取到 cookies 了,这就是建立一个会话到作用。体会一下。 那么既然会话是一个全局的变量,那么我们肯定可以用来全局的配置了。

1
2
3
4
5
6
import requests

s = requests.Session()
s.headers.update({'x-test': 'true'})
r = s.get('http://httpbin.org/headers', headers={'x-test2': 'true'})
print r.text

通过 s.headers.update 方法设置了 headers 的变量。然后我们又在请求中设置了一个 headers,那么会出现什么结果? 很简单,两个变量都传送过去了。 运行结果

1
2
3
4
5
6
7
8
9
10
{
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.9.1",
"X-Test": "true",
"X-Test2": "true"
}
}

如果get方法传的headers 同样也是 x-test 呢?

1
r = s.get('http://httpbin.org/headers', headers={'x-test': 'true'})

嗯,它会覆盖掉全局的配置

1
2
3
4
5
6
7
8
9
{
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.9.1",
"X-Test": "true"
}
}

那如果不想要全局配置中的一个变量了呢?很简单,设置为 None 即可

1
r = s.get('http://httpbin.org/headers', headers={'x-test': None})

运行结果

1
2
3
4
5
6
7
8
{
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.9.1"
}
}

嗯,以上就是 session 会话的基本用法

SSL证书验证

现在随处可见 https 开头的网站,Requests可以为HTTPS请求验证SSL证书,就像web浏览器一样。要想检查某个主机的SSL证书,你可以使用 verify 参数 现在 12306 证书不是无效的嘛,来测试一下

1
2
3
4
import requests

r = requests.get('https://kyfw.12306.cn/otn/', verify=True)
print r.text

结果

1
requests.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)

果真如此 来试下 github 的

1
2
3
4
import requests

r = requests.get('https://github.com', verify=True)
print r.text

嗯,正常请求,内容我就不输出了。 如果我们想跳过刚才 12306 的证书验证,把 verify 设置为 False 即可

1
2
3
4
import requests

r = requests.get('https://kyfw.12306.cn/otn/', verify=False)
print r.text

发现就可以正常请求了。在默认情况下 verify 是 True,所以如果需要的话,需要手动设置下这个变量。

代理

如果需要使用代理,你可以通过为任意请求方法提供 proxies 参数来配置单个请求

1
2
3
4
5
6
7
import requests

proxies = {
"https": "http://41.118.132.69:4433"
}
r = requests.post("http://httpbin.org/post", proxies=proxies)
print r.text

也可以通过环境变量 HTTP_PROXY 和 HTTPS_PROXY 来配置代理

1
2
export HTTP_PROXY="http://10.10.1.10:3128"
export HTTPS_PROXY="http://10.10.1.10:1080"

通过以上方式,可以方便地设置代理。

API

以上讲解了 requests 中最常用的参数,如果需要用到更多,请参考官方文档 API API

结语

以上总结了一下 requests 的基本用法,如果你对爬虫有了一定的基础,那么肯定可以很快上手,在此就不多赘述了。 练习才是王道,大家尽快投注于实践中吧。

JavaScript

前言

之前在用jQuery,不过有时候用着用着一些用法发现并没有用到过,比较陌生,现在重新梳理一下,把易忽略的知识点总结一下,长期更新。 参考梳理来源: 慕课网

sele1,sele2,seleN选择器

有时需要精确的选择任意多个指定的元素,类似于从文具盒中挑选出多根自已喜欢的笔,就需要调用sele1,sele2,seleN选择器,它的调用格式如下: $(“sele1,sele2,seleN”) 其中参数sele1、sele2到seleN为有效选择器,每个选择器之间用“,”号隔开,它们可以是之前提及的各种类型选择器,如$(“#id”)、$(“.class”)、$(“selector”)选择器等。 例如,通过选择器获取其中的任意两个元素,并将它们显示的内容设为相同,如图所示: 在浏览器中显示的效果: 虽然页面中添加了三个元素,但是通过使用$(“div,p”)选择器方式获取了其中的

元素,并设置它们显示的内容。

prev + next选择器

俗话说“远亲不如近邻”,而通过prev + next选择器就可以查找与“prev”元素紧邻的下一个“next”元素,格式如下: $(“prev + next”) 其中参数prev为任何有效的选择器,参数“next”为另外一个有效选择器,它们之间的“+”表示一种上下的层次关系,也就是说,“prev”元素最紧邻的下一个元素由“next”选择器返回的并且只返回唯的一个元素。 例如,使用prev + next选择器,获取

元素最近邻的下一个元素,如下图所示: 在浏览器中显示的效果:

prev ~ siblings选择器

与上一节中介绍的prev + next层次选择器相同,prev ~ siblings选择器也是查找prev 元素之后的相邻元素,但前者只获取第一个相邻的元素,而后者则获取prev 元素后面全部相邻的元素,它的调用格式如下: $(“prev ~ siblings”) 其中参数prev与siblings两者之间通过“~”符号形成一种层次相邻的关系,表明siblings选择器获取的元素都是prev元素之后的同辈元素。 例如,使用prev ~ next选择器,获取

元素后面相邻的全部元素,并设置它们在页面中显示的内容,如下图所示: 在浏览器中显示的效果: 可以看出,调用$("p~span")选择器代码,获取了

元素下面两个(全部)的元素,该元素不包含

元素上面的元素和不属于同辈范围的元素。

:contains(text)过滤选择器

与上一节介绍的:eq(index)选择器按索引查找元素相比,有时候我们可能希望按照文本内容来查找一个或多个元素,那么使用:contains(text)选择器会更加方便, 它的功能是选择包含指定字符串的全部元素,它通常与其他元素结合使用,获取包含“text”字符串内容的全部元素对象。其中参数text表示页面中的文字。 例如: 在浏览器中显示的效果: 从图中可以看出,调用li:contains('土豪')代码,可以很方便地获取

  • 包含‘土豪’字符内容的全部元素,并且只要与选择的元素中或子元素中包含该字符内容,就可以被选中。 注意:li:contains('土豪') 土豪为什么必须加单引号呢?因为它是一个字符串,而不是一个变量,所以不加单或双引号的话是会报错的。

    :has(selector)过滤选择器

    除了在上一小节介绍的使用包含的字符串内容过滤元素之外,还可以使用包含的元素名称来过滤,:has(selector)过滤选择器的功能是获取选择器中包含指定元素名称的全部元素,其中selector参数就是包含的元素名称,是被包含元素。 例如:获取指定包含某个元素名的全部

  • 元素,并改变它们显示文字的颜色,如下图所示: 在浏览器中显示的效果: 可以看出,通过使用$("li:has('p')")选择器代码,获取了包含

    元素的全部

  • 元素,并通过css方法改变了这些元素在页面中显示的文字样式。

    :hidden过滤选择器

    :hidden过滤选择器的功能是获取全部不可见的元素,这些不可见的元素中包括type属性值为hidden的元素。 例如,调用:hidden选择器获取不可见的

    元素,并将该元素的内容显示在

    元素中,如下图所示: 在浏览器中显示的效果: 从图中可以看出,先调用$("p:hidden")代码获取隐藏的

    元素,并调用该元素的html()方法获取该元素中的内容,最后将该内容显示在

    元素中。

    :visible过滤选择器

    与上一节的:hidden过滤选择器相反,:visible过滤选择器获取的是全部可见的元素,也就是说,只要不将元素的display属性值设置为“none”,那么,都可以通过该选择器获取。 例如,使用:visible选择器获取可见的

    元素,并将该元素的内容显示在

    元素中,如下图所示: 在浏览器中显示的效果: 从图中可以看出,调用$("p:visible")选择器代码,获取那个可见的

    元素,并调用html()方法获取该元素的内容,最后将该内容显示在

    元素中。

    :input表单选择器

    如何获取表单全部元素?:input表单选择器可以实现,它的功能是返回全部的表单元素,不仅包括所有标记的表单元素,而且还包括