作业4:网页前端基础(HTTP请求方式与过程、HTTP状态码、HTTP头部信息)及静态网页爬取(urllib3库、requests库、Xpath解析网页、Beautiful Soup解析网页)

网页前端基础及静态网页爬取


目录

网页前端基础及静态网页爬取

一、网页前端基础

1、HTTP请求方式与过程

2、常见HTTP状态码

3、HTTP头部信息

二、静态网页爬取

1、使用urllib3库实现

2、使用requests库实现

3、使用Xpath解析网页

4、使用Beautiful Soup解析网页

三、作业


一、网页前端基础

1、HTTP请求方式与过程

(1)请求方法

在HTTP/1.1协议中共定义了8种方法(也叫“动作”)来以不同方式操作指定的资源,常用的方法有GET、HEAD、POST等。

请求方法方法描述
GET请求指定的页面信息,并返回实体主体。GET可能会被网络爬虫等随意访问,因此GET方法应该只用在读取数据,而不应当被用于产生“副作用”的操作中,例如在Web Application中。
HEAD与GET方法一样,都是向服务器发出指定资源的请求。只不过服务器将不传回具体的内容,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中该资源的相关信息(元信息或称元数据)
POST向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据会被包含在请求中,这个请求可能会创建新的资源或者修改现有资源,或二者皆有。
PUT从客户端上传指定资源的最新内容,即更新服务器端的指定资源

(2)请求(request)与响应(response)

HTTP协议采用了请求/响应模型。

  • 客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。
  • 服务器以一个状态作为响应,响应的内容包括协议的版本、响应状态、服务器信息、响应头部和响应数据。

客户端与服务器间的请求与响应的具体步骤如下:

  • 连接Web服务器:由一个HTTP客户端发起连接,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。
  • 发送HTTP请求:客户端经TCP套接字向Web服务器发送一个文本的请求报文。
  • 服务器接受请求并返回HTTP响应:Web服务器解析请求,定位该次的请求资源。之后将资源复本写至TCP套接字,由客户端进行读取。
  • 释放TCP连接:若连接的connection模式为close,则由服务器主动关闭TCP连接,客户端将被动关闭连接,释放TCP连接;若connection模式为keepalive,则该连接会保持一段时间。
  • 客户端解析HTML内容:客户端首先会对状态行进行解析,之后解析每一个响应头,然后读取响应数据。

请求(Request)

  • 请求方式:主要有GET、POST两种类型,另外还有HEAD、PUT、DELETE、OPTION等。
  • 请求URL:URL全称为统一资源定位符,如一个网页文档、一张图片、一个视频等都可以用URL唯一确定。
  • 请求头:包含请求头时的头部信息,如User-Agent、Host、Cookies等信息。
  • 请求体:请求时额外携带的数据,如表单提交时的表单数据。

响应(Response)

  • 响应状态:有多种响应状态,如200代表成功、301跳转、404找不到页面、502服务器错误。
  • 响应头:如内容类型、内容长度、服务器信息、设置Cookie等。
  • 响应体:最主要的部分,包含了请求资源的内容,如网页HTML、图片二进制数据等。

2、常见HTTP状态码

(1)HTTP状态码种类

HTTP状态码是用来表示网页服务器响应状态的3位数字代码,按首位数字分为5类状态码。

状态码类型状态码意义
1XX表示请求已被接受,需接后续处理。这类响应是临时响应,只包含状态行和某些可选的响应头信息,并以空行结束
2XX

表示请求已成功被服务器接收、理解并接受

3XX表示需要客户端采取进一步的操作才能完成请求。通常用来重定向,重定向目标需在本次响应中指明
4XX表示客户端可能发生了错误,妨碍了服务器的处理
5XX表示服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器以当前的软硬件资源无法完成对请求的处理

(2)常见的HTTP状态码

HTTP状态码共有67种状态码,常见的状态码如下。

常见状态码状态码含义
200 OK请求成功,请求所希望的响应头或数据体将随此响应返回
400 Bad Request由于客户端的语法错误、无效的请求或欺骗性路由请求,服务器不会处理该请求 
403 Forbidden

服务器已经理解该请求,但是拒绝执行,将在返回的实体内描述拒绝的原因,也可以不描述仅返回404 Not Found响应

404 Not Found请求失败,请求所希望得到的资源未被在服务器上发现,但允许用户的后续请求
500 Internal Server Error通用错误消息,服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理,不会给出具体错误信息
503 Service Unavailable由于临时的服务器维护或者过载,服务器当前无法处理请求。这个状况是暂时的,并将在一段时间以后恢复

3、HTTP头部信息

HTTP头部信息(HTTP header fields)是指在超文本传输协议(HTTP)的请求和响应消息中的消息头部分。头部信息定义了一个超文本传输协议事务中的操作参数。在爬虫需要使用头部信息向服务器发送模拟信息,通过发送模拟的头部信息将自己伪装成一般的客户端。

HTTP头部类型,按用途可分为:通用头请求头响应头实体头

  • 通用头:既适用于客户端的请求头,也适用于服务端的响应头。与HTTP消息体内最终传输的数据是无关的,只适用于要发送的信息。
  • 请求头:提供更为精确的描述信息,其对象为所求的资源或请求本身。新版HTTP增加的请求头不能在更低版本的HTTP中使用,但服务器和客户端若都能对相关头进行处理,则可以在请求中使用。
  • 响应头:为响应消息提供了更多信息。例如,关于资源位置的描述Location字段,以及关于服务器本身的描述使用Server字段等。与请求头类似,新版增加的响应头也不能在更低版本的HTTP中使用。
  • 实体头:提供了关于信息的描述。如消息的长度Content-Length,消息体的MIME类型Content-Type。新版的实体头可以在更低版本的HTTP版本中使用。
字段名说明
Accept可接受的响应内容类型(Content-Tpyes)
Accept-Charset可接受的字符集
Accept-Encoding可接受的响应内容的编码方式
Accept-Language可接受的响应内容语言列表
Cookie由之前服务器通过Set-Cookie设置的一个HTTP协议Cookie
Referer设置前一个页面的地址,并且前一个页面中的连接指向当前请求,意思就是如果当前请求是在A页面中发送的,那么referer就是A页面的URL地址
User-Agent用户代理的字符串值

二、静态网页爬取

在网站设计中,纯粹HTML格式的网页通常被称为“静态网页”,静态网页是网站建设的基础,早期的网站一般都是由静态网页制作的。静态网页是相对于动态网页而言,是指没有后台数据库不含程序不可交互的网页。

爬虫基本流程:

  • 发起请求:通过HTTP库向目标站点发起请求,即发送一个Request,请求可以包含额外的headers等信息,等待服务器响应。
  • 获取响应内容:如果服务器能正常响应,会得到一个Response,Response的内容便是所要获取的页面内容,类型可能有HTML、Json字符串、二进制数据(图片视频)等类型。
  • 解析内容:得到的内容可能是HTML,可以用正则表达式、网页解析库进行解析。可能是Json,可以直接转为Json对象解析,可能是二进制数据,可以做保存或者进一步处理。
  • 保存数据:保存形式多样,可以存为文本,也可以保存至数据库,或者保存特定格式的文件。

1、使用urllib3库实现

许多python的原生系统已经开始使用urllib3库,其提供了很多python标准库里所没有的重要特性。包括:线程安全、客户端SSL/TLS验证、协助处理充分请求和HTTP重定位、支持HTTP和SOCKS代理、管理连接池、使用分部编码上传文件、支持压缩编码和测试覆盖率达到100%。

(1)生成请求

通过request方法即可创建一个请求,该方法返回一个HTTP响应对象。其语法格式为:

                                     urllib3.request(method, url, fields=None, header=None, **urlopen_kw)

参数说明
method接收string.表示请求的类型,如“GET”、“HEAD”、“DELETE”等,无默认值
URL接收string.表示字符串形式的网站,无默认值
fields接收dict.表示请求类型所带的参数,默认None
headers接收dict.表示请求头所带的参数,默认None
**urlopen_kw接收dict或者其他python中的类型的数据。依据具体需要及请求的类型可添加的参数,通常参数赋值为字典类型或为具体数据。无默认值

(2)请求头处理

在request方法中,如果需要传入headers参数,可通过定义一个字典类型实现。

(3)Timeout设置、请求重试设置

为防止因为网络不稳定,服务器不稳定等问题造成连接不稳定时的丢包,可以在请求中增加timeout参数设置,通常为浮点数。

urllib3库可以通过设置retries参数对重试进行控制。默认进行3次请求重试,并进行3次重定向。

(4)生成完整HTTP请求

使用urllib3库实现生成一个完整的请求,该请求应当包含连接、请求头、超时时间和重试次数设置。

2、使用requests库实现

requests库是一个原生的HTTP库,比urllib3库更为容易使用。requests库发送原生的HTTP 1.1请求,无需手动为URL添加查询字串,也不需要对POST数据进行表单编码。相对于urllib3库,requests库拥有完全自动化keep-alive和HTTP连接池的功能。

requests库包含的特性有:keep-alive&连接池、基本/摘要式的身份认证、文件分块上传、国际化域名和URL、优雅的key/value Cookie、流下载、带持久的Cookie的会话、自动解压、连接超时、浏览器式的SSL认证、Unicode响应体、分块请求、自动内容解码、HTTP(S)代理支持和支持.netrc。

(1)生成请求

requests库生成请求的代码非常便利,其使用的request方法的格式为:

                                                                 requests.request.method(url, **kwargs)

参数说明
method接受string.表示请求的类型,如“GET”、“HEAD”、“DELETE”等,无默认值
URL接受string.表示字符串形式的网址,无默认值
**kwargs接受dict或其他python中的类型的数据。依据具体需要及请求的类型可添加的参数,通常参数赋值为字典类型或为具体数据

(2)查看状态码与编码

当requests库猜错编码时,需要手动指定encoding编码,避免返回的网页内容解析出现乱码。

然而,手动指定的方法并不灵活,无法自适应对应爬取过程中不同网页的编码。

而使用chardet库比较简便灵活,chardet库是一个非常优秀的字符串/文件编码检测模块。chardet库使用detect方法检测给定字符串的编码,detect的参数及说明:

参数说明
byte_str接受string.表示需要检测编码的字符串,无默认值,传入参数需要为字节型。

(3)请求头与响应头处理、Timeout设置

requests库中对请求头的处理与urllib3库类似,也使用headers参数在GET请求中上传参数,参数形式为字典。使用headers数学即可查看服务器返回的响应头。

为避免因等待服务器响应造成程序永久失去响应,通常需要给程序设置一个时间作为限制,超过该时间后程序将会自动停止等待。在requests库中通过设置timeout这个参数实现,超过该参数设定的秒数后,程序会停止等待。

(4)生成完整HTTP请求

向网站发送一个完整的GET请求,该请求包括链接、请求头、响应头、超时时间和状态码,并且编码应正确设置。

3、使用Xpath解析网页

XML路径语言(XML Path Language),它是一种基于XML的树状结构,在数据结构树中找寻节点,确定XML文档中某部分位置的语言。

(1)基本语法

使用Xpath需要从lxml库中导入etree模块,还需要使用HTML类对需要匹配的HTML对象进行初始化(Xpath只能处理文档的DOM表现形式)。HTML类的基本语法格式为:

                                               lxml.etree.HTML(text, parser=None, *, base_url=None)

参数名称说明
text接收str.表示需要转换为HTML的字符串,无默认值
parser接收str.表示选择的HTML解析器,无默认值
base_url接收str.表示设置文档的原始URL,用于在查找外部实体的相对路径,默认None

若HTML中的节点没有闭合,etree模块也提供自动补全功能。调用tostring方法即可输出修正后的HTML代码,但是结果为bytes类型,需要使用decode方法转成str类型。

Xpath使用类似正则的表达式来匹配HTML文件中的内容,常用匹配表达式如下

表达式说明
nodename选取nodename节点的所有子节点
/从当前节点选取直接子节点
//从当前节点选取子孙节点
.选取当前节点
..选取当前节点的父节点
@选取属性

(2)谓语

Xpath中的谓语用来查找某个特定的节点或包含某个指定的值的节点,谓语被嵌在路径后的方括号中

表达式说明
/html/body/div[1]选取属于body子节点下的第一个div节点
/html/body/div[last()]选取属于body子节点下的最后一个div节点
/html/body/div[last()-1]选取属于body子节点下的倒数第二个div节点
/html/body/div[position()<3]选取属于body子节点下的前两个div节点
/html/body/div[@id]选取属于body子节点下的带有id属性的div节点
/html/body/div[@id="content"]选取属于body子节点下的id属性值为content的div节点
/html/body/div[xx>10.00]选取属于body子节点下的xx元素值大于10的节点

(3)功能函数

Xpath中还提供功能函数进行模糊搜索,有时对象仅掌握了其部分特征,当需要模糊搜索该类对象时,可使用功能函数来实现,具体函数如下。

功能函数示例说明
starts-with//div[starts-with(@id,"co")]选取id值以co开头的div节点
contains//div[contains(@id,"co")]选取id值包含co的div节点
and//div[contains(@id,"co")and contains(@id,"en")]选取id值包含co和en的div节点
text()//li[contains(text(),"first")]选取节点文本包含first的div节点

(4)提取文本及对应链接

使用text方法可以提取某个单独子节点下的文本,若想提取出定位到的子节点及其子孙节点下的全部文本,则需要使用string方法实现。

4、使用Beautiful Soup解析网页

Beautiful Soup是一个可以从HTML或XML文件中提取数据的python库。目前,Beautiful Soup 3已经停止开发,大部分的爬虫选择使用Beautiful Soup 4开发。Beautiful Soup不仅支持python标准库中的HTML解析器,还支持一些第三方的解析器。

解析器语法格式优点缺点
python标准库BeautifulSoup(markup, "html.parser")

python的内置标准库

执行速度适中 

文档容错能力强

python 2.7.3或3.2.2前的版本中文档容错能力差
lxml HTML解析器BeautifulSoup(markup, "lxml")

速度快

文档容错能力强

需要安装C语言库
lxml XML解析器BeautifulSoup(markup, ["lxml-xml"])

速度快

唯一支持XML的解析器

需要安装C语言库
html5libBeautifulSoup(markup, "html5lib")

最好的容错性

以浏览器的方式解析文档

生成HTML5格式的文档

速度慢

不依赖外部扩展

(1)创建BeautifulSoup对象

要使用Beautiful Soup库解析网页首先需要创建BeautifulSoup对象,将字符串或HTML文件传入Beautiful Soup库的构造方法可以创建一个BeautifulSoup对象。使用格式如下:

                                               BeautifulSoup("<html>data</html>")   #通过字符串创建

                                               BeautifulSoup(open("index.html"))      #通过HTML文件创建

生成的BeautifulSoup对象可通过prettify方法进行格式化输出,格式如下:

                                           BeautifulSoup.prettify(self, encoding=None, formatter='minimal')

参数说明
encoding接收string.表示格式化时使用的编码,默认None
formatter接收string.表示格式化的模式,默认minimal,表示按最简化的格式化将字符串处理成有效的HTML/XML

(2)对象类型

Tag对象类型

  • Tag对象为HTML文档中的标签,如“<title> DATA </title>” 或 “<p class="title"><b> DATA </b></p>”
  • 通过Tag的名称属性可以很方便的在文档树中获取需要的Tag对象,通过该方法智能获取文档树中第一个同名的Tag对象,而通过多次调用可获取某个Tag对象下的分支Tag对象。通过find_all方法可以获取文档树中的全部同名Tag对象。
  • Tag有两个非常重要的属性:name和attributes。name属性可通过name方法来获取和修改,修改过后的name属性将会应用至BeautifulSoup对象生成的HTML文档。

NavigableString对象类型

  • NavigableString对象包含在Tag中的文本字符串内容。使用string的方法获取,NavigableString对象无法被编辑,但可以使用replace_with的方法进行替换。

BeautifulSoup对象类型

  • BeautifulSoup对象表示的一个文档的全部内容。大部分时候,可以把它当做Tag对象。BeautifulSoup对象并不是真正的HTML或XML的Tag,所以并没有Tag的name和attribute属性,但其包含了一个值为“[document]”的特殊属性name。

Comment对象类型

  • Tag、NavigableString、BeautifulSoup几乎覆盖了HTML和XML中的所有内容,但是还有一些特殊对象,文档的注释部分是最容易与Tag中的文本字符串混淆的部分。Beautiful Soup库中将文档的注释部分识别为Comment类型,Comment对象时一个特殊类型的NavigableString对象,但是当其出现在HTML文档中时,Comment对象会使用特殊的格式输出,需调用prettify方法。

(3)搜索特定节点并获取其中的链接及文本

Beautiful Soup定义了很多搜索方法,其中常用的有find方法和find_all方法,两者参数一致,区别为find_all方法返回的结果是值包含一个元素的列表,而find直接返回结果。find_all方法用于搜索文档树中的Tag非常方便,其格式为:

                                         BeautifulSoup.find_all(name, attrs, recursive, string, **kwargs)

参数说明
name接受string.表示查找所以名字为name的tag,字符串对象会被自动忽略,搜索name参数的值可以使用任一类型的过滤器:字符串、正则表达式、列表、方法或True,无默认值
attrs接受string.表示查找符合CSS类名的tag,使用class做参数会导致语法错误,从Beautiful Soup的4.1.1版本开始,可以通过class_参数搜索有指定CSS类名的tag,无默认值
recursive

接受Built-in.表示是否检索当前tag的所有子孙节点,默认True

string接受string.表示搜索文档中匹配传入的字符串的内容,与name参数的可选值一样,string参数也接受多种过滤器,无默认值
**kwargs若一个指定名字的参数不是搜素内置的参数名,搜索时会把该参数当做指定名字tag的属性来搜索

find_all方法可通过多种参数遍历搜索文档树中符合条件的所有子节点。

  • 可通过name参数搜索同名的全部子节点,并接收多种过滤器。
  • 按照CSS类名可模糊匹配或完全匹配。完全匹配class的值时,如果CSS类名的顺序与实际不符,将搜索不到结果。
  • 若tag的class属性是多值属性,可以分别搜索tag中的每个CSS类名。
  • 通过字符串内容进行搜索符合条件的全部子节点,可通过过滤器操作。
  • 通过传入关键字参数,搜索匹配关键字的子节点。

三、作业

一、爬取实习网(https://www.shixi.com),打印出该网站的状态码、编码格式和请求头

二、爬取实习网热门职业的相关信息(职位、地址、学历要求、工资)

PS:这是我的python作业(非参考答案,参考需谨慎)

PSS:不是广告,他题就这样出的题

import requests
from bs4 import BeautifulSoup
import pandas as pd
def modify_panel():# 美化输出格式
    pd.set_option('display.unicode.ambiguous_as_wide', True)
    pd.set_option('display.unicode.east_asian_width', True)
    pd.set_option('display.max_columns', None)
    pd.set_option('display.width', None)

url = 'https://www.shixi.com'
head = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
}

def req():# 连接网站,超时或发生错误时自动重连
    while True:
        try:
            req = requests.get(url, headers = head, timeout=1.0)
            return req
        except:
            print("超时")
            pass

req = req()
print("状态码:", req.status_code)
print("编码格式:", req.encoding)
print("请求头:\n", req.headers)
soup = BeautifulSoup(req.content, 'lxml')
cn_career = [i.text for i in soup.select('.job_content > h3 > a')]
us_career = [i.text for i in soup.select('.job_content > h3 > .title')]
company = [i.text for i in soup.select('.job_content > .job_company')]
print("company:\n",company)
detail = [i.text for i in soup.select('.job_content > p > span')]
re_detail = [detail[i:i+3] for i in range(0, len(detail), 3)]
career = cn_career + us_career
format_1 = pd.DataFrame([career, company])
format_2 = pd.DataFrame(re_detail)
format = format_1.T.join(format_2, lsuffix='_left', rsuffix='_right')
format.columns = ['职位', '公司', '地址', '学历要求', '工资']
modify_panel()
print(format)

最后,这是我的python数据分析与应用的作业(非参考答案,参考需谨慎),内容是上课时候的内容,可能会有错或者可以优化的地方,这些欢迎指出。

今后可能会继续把上课内容及作业写出来。(大概,不懒的话)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值