整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

深入HTTP请求流程

深入HTTP请求流程

X0

HTTP(HyperText Transfer Protocol)超文本传输协议,是web服务器到web浏览器之间传输的通信规则。

0x01

HTTP协议目前最新版本是1.1,HTTP是一种无状态的协议,只能由客户端发起,服务器端不能主动向客户端发送数据。

应答模型:

Request请求

客户端=============》服务端

《============

Response响应

0x02 HTTP请求

包括三个部分:1、请求行; 2、请求头; 3、请求正文。

实例:

GET /notification/notification_count/ HTTP/1.1 请求行

Host: mp.xxxxxx.com 请求头

User-Agent: Mozilla/5.0 (X11; Linux i686; rv:52.0) Gecko/20100101 Firefox/52.0 (User-Agent代表浏览器标识。)

Accept: application/json, text/javascript, */*; q=0.01 正文

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

Referer: http://mp.toutiao.com/profile_v2/publish

X-Requested-With: XMLHttpRequest

图例brupsuite:

使用python socket测试http响应的效果:

import socket

t_host="www.toutiao.com"

t_port=80

client=socket.socket()

client.connect((t_host,t_port))

client.send("GET / HTTP/1.1\r\nHost:toutiao.com\r\n\r\n")

response=client.recv(4096)

print response

HTTP/1.1 502 Bad Gateway //响应行 HTTP的版, 状态码 502,消息是Bad Gateway

Server: Tengine //响应头 由服务器向客户端发送

Content-Length: 0

Connection: keep-alive

Via: cache5.cn218[0,502-257,M], cache4.cn218[14,1,502001]

X-Swift-Error: dns domain not exist

Timing-Allow-Origin: *

EagleId: 790e0d0415057759521686693e

........由于response获取的字节有限下面是响应正文,是服务器向客户端发送的HTML数据。

EOF:下一遍我将讲述HTTP的请求方法,请期待。

码如下:

import requests
from bs4 import BeautifulSoup
import pandas as pd
#下面是请求数据
url="https://www.163.com/" #设置请求网址为搜索网址
response=requests.get(url) #对163网站就行get请求并将请求结果赋值给response
response.encoding="GBK" #设置编码为GBK格式的
html=response.text #获取网页的html源代码并赋值给html
#下面是解析数据
soup=BeautifulSoup(html)
content=soup.findAll('div') #查找所有的div标签内容并赋值给content
print(content) #打印content

代码运行结果如下图所示:

多朋友都听说过Python的大名,而Python也拥有众多的爬虫框架,其中最简单的莫过于requests-html了。它和著名的网络请求库requests是同一个作者,着重于XML数据提取,可以说是最简单的爬虫框架了。



安装requests-html

安装这个类库非常简单,直接通过pip就可以安装了。

pip install requests-html

开始使用

requests-html用起来也十分简单,下面是一个简单例子。照例说明一下,第一段引入了HTMLSession用于创建连接,获取网页数据。第二段创建连接,获取了我的简书用户页面。第三段用xpath语法获取了网页上的用户名,最后打印出来。

from requests_html import HTMLSession

session=HTMLSession()
response=session.get(
    'https://www.jianshu.com/u/7753478e1554')

username=response.html.xpath(
    '//a[@class="name"]/text()', first=True)


print(username)

看起来是不是很简单?没错,确实很简单,接下来还有一些更加有趣的功能。

分析网页

编写爬虫之前还要做一件事情,就是分析网页的结构。这个工作其实也很简单,打开你要访问的网页,按F12打开开发人员工具,可以看到最左边有这么一个按钮。点击这个按钮,然后点击网页上你想要查看的网页元素,然后你就可以发现这个元素对应的相关源代码已经为你定位完毕了。

定位按钮

通过这个功能,我们就可以轻松的分析网页,然后通过它的结构来编写爬虫了。

提取数据

上面的response.html即是网页的根节点HTML节点,在节点对象上可以调用一些方法来检索数据。最常用的方法是find方法,它通过CSS选择器来定位数据。对于上面的例子,可以用find方法改写第三段。

因为所有查找方法返回的结果都是列表,所以如果你确定只需要查找一个,就将first参数设为真来只返回第一个结果。find方法返回的仍然是一个节点,如果只需要节点的内容,调用其text属性即可。

用户名对应的HTML结构如图所示。


代码如下。

username = response.html.find('a.name', first=True).text

除了find方法之外,还可以使用xpath方法用xpath语法来查找节点,正如第一个例子那样。我个人比较喜欢xpath语法,CSS选择器虽然更加流行一些,但是写出来的效果有点怪,不如xpath工整。

同样是这个页面,看看如何获取我的简书的个人简介。网页代码如图所示。


代码如下。

description=response.html.xpath(
    '//div[@class="description"]/div[@class="js-intro"]/text()', first=True)

CSS选择器和XPATH语法都不是本篇的主要内容,如果你这方面不太熟悉,最好去看一下相关的教程。当然如果大家有什么疑问的话,也可以提出来。假如大家想看的话,我也可以专门写一篇文章介绍一下这些语法知识。


渲染网页

有些网页利用了前后端分离技术开发的,需要浏览器渲染才能完整显示。如果用爬虫去看的话,只能显示一部分内容。这时候就需要浏览器渲染页面,才能获取完整的页面。用requests-html的话,这个过程非常简单。

首先先来看看一个需要渲染网页的例子。下面的代码访问了我的简书用户页面,然后尝试获取我的所有文章。但是如果你运行这个例子的话,就会发现只能获取前几项。因为简书的页面正是一个典型的需要浏览器渲染的页面,爬虫获取到的网页是不完整的。

from requests_html import HTMLSession

session=HTMLSession()
headers={
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.119 Safari/537.36'
}

url='https://www.jianshu.com/u/7753478e1554'
r=session.get(url, headers=headers)

for a in r.html.xpath('//ul[@class="note-list"]/li/div[@class="content"]/a[@class="title"]'):
    title=a.text
    link=f'https://www.jianshu.com{a.attrs["href"]}'
    print(f'《{title}》,{link}')

那么如何渲染网页来获取完整的结果呢?其实非常简单,在查询HTML节点之前,调用render函数即可。


render函数来使用浏览器渲染


原理也非常简单,第一次调用render的时候,requests-html会在本地下载一个chromium浏览器,用它来渲染网页。如此一来,我们就可以获取到渲染之后的页面了。


但是对于简书这个例子来说还是有些问题,因为如果你在浏览器里打开这个网页的话,会发现一些文章在浏览器下滑页面的时候才开始渲染。不过聪慧的作者早就考虑到这种情况了,render函数支持下滑的参数,设定之后,就会模拟浏览器下滑操作,从而解决了这个问题。

r.html.render(scrolldown=50, sleep=0.2)

节点对象

不论上面的r.html还是find/xpath函数返回的结果,它们都是节点对象。除了上面介绍的几个提取数据的方法以外,节点对象还有以下一些属性,在我们提取数据的时候也有很大作用。



相较于专业的爬虫框架scrapy,或者仅用于解析XML的解析库BeautifulSoup。requests-html可以是说恰到好处,它没有前者那么难学,也不像后者还需要搭配HTTP请求库才能使用。如果你手头需要临时抓取几个网页,那么requests-html就是你最好的选择。