爬虫 - 请求服务器数据

上一篇文章中我们了解了关于爬虫的基础知识,那么在这一篇文章中我们来看看如何让程序模仿浏览器获取服务器数据。

在进入爬虫的殿堂之前我们先了解一下网络爬虫道德:尽量放慢你的速度、尽量遵循robots、不要公开你的爬虫源码、不要分享你的爬虫数据。

ok 下面就正式开始我们的学习。

既然要获取服务器数据,没有服务器可不行,我们可以自己弄一个简单的“服务器”,这样学起来会更加透彻。我们可以使用 Flask 写一个简单的 app (或者使用 Django 也可以),生产环境中的服务器一般都是 apache。

首先创建一个虚拟环境,然后建立 Flask 项目,在 app 里面写上下面的代码:

from flask import Flask, request
import os

app = Flask(__name__)


@app.route('/')
def HelloWorld():
    print(request.headers)
    return '你好!访问成功!'

@app.route('/get')
def getdata1():
    print(request.headers)
    return request.url

@app.route('/post', methods=['POST'])
def getdata():
    username = request.form['name']
    userage = request.form['age']
    print(request.headers)
    return '你好!{}岁的{}!'.format(userage, username)

@app.route('/file', methods=['POST'])
def file():
    f = request.files['file']
    dir = os.path.abspath(os.path.dirname(__name__))
    f.save(os.path.join(dir, f.filename))
    return '文件已经成功保存!'+ os.path.join(dir,f.filename)


@app.route('/proxy')
def proxy():
    return request.remote_addr  # 获取本机 ip


if __name__ == '__main__':
    app.run(debug=True)

启动应用,


我们先使用浏览器测试一下,在浏览器里面输入上面的地址就会出现:


这个 ’服务器‘ 是可以在局域网上访问的,公网就不行啦,毕竟没有域名,具体的含义在后面用到的时候再解释吧,我们的重点还是放在爬虫上面。

1. Requests 概述

首先说一下网页爬虫的整个思路方法:

  • 先爬取整个网页,也就是将网页的源代码给获取下来
  • 爬取下来的网页再通过文本解析提取,找到我们需要的信息,可以是图片或者文字

以上基本就是爬虫的思路步骤了,非常的简单,简化成了两条,今天要讲的这个requests就是来完成第一步的。
requests是python的一个HTTP客户端库,非常非常的简单易学。

在说起 Requests 之前呢,我们不得不提一下 urllib3 库,它是 python 的内置模块,urllib3 提供了一系列用于操作 URL 的功能。其实 Requests 的底层就是 urllib3 但是因为它过于底层了,直接使用它会比较繁琐,所以人们开发了 request ,当然简洁的代价就是我们可以直接操纵的东西变少了。

requests 库中文文档 中提到

所以我们就先使用这个库进行我们的学习啦。

request 一共有七个方法,除一个通用的方法外剩下的六个分别对应六种请求。我们主要关注 GET 请求和 POST 请求。如果不了解这两个请求可以看一下这篇文章

2. 基本的 GET 请求

首先使用 response = requests.get(url) 或者 response = requests('get', url)创建一个 response 对象,response 有一些常用的方法:

方法 描述
response.text 获取 str 类型的响应(一般来说就是相应网站的 html 文件)
response.content 获取 bytes 类型的响应
response.staus_code 获取状态码
response.headers 获取响应头
response.request 获取响应对应的请求

例如我们使用 requests 对 http://www.baidu.com 进行访问。

import requests
resp = requests.get('http://www.baidu.com')
print(resp)
# <Response [200]>
# 也可以这么写
response = requests.request("get", "http://www.baidu.com")
print(response)
# <Response [200]>
print(response.status_code)
# 200
print(response.text)
# <!DOCTYPE html><!--STATUS OK--><html> <head><meta ...
print(type(response.text))
# <class 'str'>
print(response.cookies)
# <RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>

在往下继续之前呢我们需要注意一下:response.textresponse.content 的区别:

  • response.text
  1. 类型:str
  2. 解码类型:根据 HTTP 头部对响应的编码推测的文本编码
  3. 如何修改编码方式:response.encoding="gbk"
  • response.content
  1. 类型:bytes
  2. 解码类型:没有指定
  3. 如何修改编码方式:response.content.decode("utf8")

因为保存文件的时候我们也需要使用二进制传输,所以一般 response.content 用在需要保存的场合。

3. 添加 headers (headers 参数)

请求带上 header 可以模拟浏览器,欺骗服务器,获取和浏览器一致的内容,我们先来看一下不加 header 服务器看到的效果:

r = requests.get('http://127.0.0.1:5000/get')
print(r.text)
Host: 127.0.0.1:5000
User-Agent: python-requests/2.22.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive

直接暴露自己是爬虫,有很多不欢迎爬虫的网站,那么我们就无法请求到它的数据。比如说知乎网,我们稍后再说它的例子。

另外加请求头还有一个好处,就是可以很大程度上避免动态加载,这对编写爬虫的我们来说省了很多事。如果你了解 JavaScript 你就知道,在之前的一段时间,JavaScript 被滥用了,这导致很多人禁止它的加载,另外还有很多低版本浏览器的使用者。网站编写者为了照顾这些人,一般对于不能加载 JS 的浏览器都有一个“备用网页”。所以如果我们使用一个低版本浏览器的请求头就可以避免动态加载(当然这是在它有备用网页的情况下)

我们来看一下怎么加请求头:

请求头使用的数据结构是字典,在requests.get 中的参数是 headers
我们可以像这样添加 headers:

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
# 用法:
requests.get(url,headers=headers)

我们可以右键检查,点击下面三个按钮,刷新,找到自己浏览器的 User-Agent 。



我们再次访问我们的服务器试试:

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'
}
r = requests.get('http://127.0.0.1:5000/', headers=headers)
print(r.text)
Host: 127.0.0.1:5000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive

下面我们访问一下知乎试试:首先不添加 headers,然后添加上 headers

import requests
url = 'https://www.zhihu.com'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'
}
r = requests.get(url)
print(r.status_code)
# 400 访问失败
r = requests.get(url, headers=headers)
print(r.status_code)
# 200 访问成功

伪装成功。

4. 发送带有查询参数的请求(params 参数)

我们知道 GET 请求也可以提交参数,get 方式在 url 后面拼接参数,类似于这种:
https://www.baidu.com/s?wd=python&c=b 问号后面的就是参数,

发送带有参数的请求有两种方式,第一种是直接写在 url 里面:

import requests
url = 'http://127.0.0.1:5000/get?name=zhangsan&age=22'
r = requests.get(url)
print(r.text)
# {"age":"22","name":"zhangsan"}

第二种是将 data 写在 一个字典里面,然后传递给参数 params。

data = {
    "name":"zhangsan",
    "age":20
}
# r = requests.get('https://httpbin.org/get', params=data)
r = requests.get('http://127.0.0.1:5000/get', params=data)
print(r.text)
# {"age":"20","name":"zhangsan"}

Ps:如果不想构建服务器可以将此处的 http://127.0.0.1:5000/ 替换为https://httpbin.org 但是返回的结果可能略有差异。

5. 使用 IP 代理爬虫(proxy 参数)

IP代理也就是代理服务器,其功能主要就是代理网络用户去获取网络信息,形象的说就是网络信息的中转站。
为什么爬虫需要使用代理?

  • 让目标服务器以为不是同一个客户端在请求,放置因为ip发送请求过多而被反爬
  • 防止我们的真实地址被泄露,防止被追究


我们可以在一些免费代理网站上,比如https://www.kuaidaili.com/free/上面找到免费的 ip。


下面是一个使用代理的实例:

proxies = {
    "http":'218.95.50.108',
}
r = requests.get('https://httpbin.org/ip', proxies=proxies)
print(r.text)
# {"origin": "120.6.172.142, 120.6.172.142"}

我们使用的是一个高匿名的 ip 代理,所以返回的 ip 跟我们设置的不一样。
如果我们使用的是一个付费代理,那么我们这一这样写:'http':'http://user:pwd@115.223.200.85:9000'

6. 设置相应时间

最后说一个简单是知识点~语法如下: response = requests.get(url,timeout=3) 单位是秒

好吧文章已经很长啦,POST 只好放到下一篇里啦
全文over

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,427评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,551评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,747评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,939评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,955评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,737评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,448评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,352评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,834评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,992评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,133评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,815评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,477评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,022评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,147评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,398评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,077评论 2 355

推荐阅读更多精彩内容