自动抓取网页数据(什么是爬虫?网络爬虫(又被称为网页蜘蛛))
优采云 发布时间: 2021-11-14 03:05自动抓取网页数据(什么是爬虫?网络爬虫(又被称为网页蜘蛛))
什么是爬虫?
网络爬虫(也称为网络蜘蛛、网络机器人,在 FOAF 社区中,更常见的是网络追逐)是按照某些规则自动抓取万维网上信息的程序或脚本。其他不太常用的名称是蚂蚁、自动索引、模拟器或蠕虫。
其实现在流行的是通过程序在网页上获取你想要的数据,即自动抓取数据。
可以爬到女生的图片,爬到想看的视频。. 等待你要爬取的数据,只要能通过浏览器访问数据,就可以通过爬虫获取
爬行动物的本质
模拟浏览器打开网页,获取网页中我们想要的部分数据
在浏览器中打开网页的过程:
当你在浏览器中输入地址时,通过DNS服务器找到服务器主机,并向服务器发送请求。服务端解析后,将结果发送到用户浏览器,包括html、js、css等文件内容,浏览器解析出来,最后呈现给用户在浏览器上看到的结果
因此,用户看到的浏览器的结果是由 HTML 代码组成的。我们的爬虫就是为了获取这些内容。通过对html代码进行分析和过滤,我们可以从中获取我们想要的资源(文字、图片、视频……)。
爬行的基本过程
发起请求
通过HTTP库向目标站点发起请求,即发送一个Request。请求可以收录额外的标头和其他信息,并等待服务器响应。
获取回复内容
如果服务器可以正常响应,就会得到一个Response。Response的内容就是要获取的页面的内容。类型可以是 HTML、Json 字符串、二进制数据(图片或视频)等。
解析内容
获取的内容可能是HTML,可以通过正则表达式、页面解析库进行解析,也可能是Json,可以直接转成Json对象解析,也可能是二进制数据,可以保存或进一步处理
保存数据
可以以多种形式保存,可以保存为文本,也可以保存到数据库中,也可以保存为特定格式的文件
请求,响应
浏览器向 URL 所在的服务器发送消息。这个过程叫做HTPP Request
服务器收到浏览器发送的消息后,可以根据浏览器发送的消息内容做相应的处理,然后将消息发送回浏览器。这个过程就是 HTTP Response
浏览器收到服务器的Response信息后,会相应地处理信息,然后显示
请求中收录什么?
请求方式
主要包括:GET/POST两种常用的,另外还有HEAD/PUT/DELETE/OPTIONS
GET和POST的区别在于:请求的数据GET在url中,POST存放在header中
GET:向指定资源发送“显示”请求。使用 GET 方法应该只用于读取数据,而不应该用于产生“副作用”的操作,例如在 Web 应用程序中。原因之一是GET可能会被网络蜘蛛等随机访问。
POST:向指定资源提交数据,请求服务器处理(如提交表单或上传文件)。数据收录在请求文本中。此请求可能会创建新资源或修改现有资源,或两者兼而有之。
HEAD:与 GET 方法相同,它向服务器发送对指定资源的请求。只是服务器不会返回资源的文本部分。它的优点是这种方法可以用来获取“关于资源的信息”(元信息或元数据),而不必传输所有的内容。
PUT:将其最新内容上传到指定的资源位置。
OPTIONS:此方法使服务器能够返回资源支持的所有 HTTP 请求方法。使用\'*\'替换资源名,向Web服务器发送OPTIONS请求,测试服务器功能是否正常。
DELETE:请求服务器删除Request-URI标识的资源。
请求网址
URL,即Uniform Resource Locator,也就是我们所说的网址。统一资源定位符是互联网上可用资源的位置和访问方式的简明表示,是互联网上标准资源的地址。Internet 上的每个文件都有一个唯一的 URL,其中收录指示文件位置以及浏览器应如何处理它的信息。
URL格式由三部分组成:
第一部分是协议(或称为服务方法)。
第二部分是存储资源的主机的IP地址(有时包括端口号)。
第三部分是宿主机资源的具体地址,如目录、文件名等。
爬虫在爬取数据时,必须要有目标网址才能获取数据。因此,它是爬虫获取数据的基本依据。
请求头
收录请求的头信息,如User-Agent、Host、Cookies等,下图显示了请求百度时的所有请求头信息参数
请求正文
请求是携带的数据,比如表单数据提交时的表单数据(POST)
响应中收录什么
所有 HTTP 响应的第一行是状态行,后跟当前 HTTP 版本号、3 位状态代码和描述状态的短语,用空格分隔。
响应状态
有多种响应状态,例如:200表示成功、301跳转、404页面未找到、502服务器错误
响应头
比如内容类型,类型长度,服务器信息,设置Cookie,如下图
响应体
最重要的部分收录了请求资源的内容,比如网页HTML、图片、二进制数据等。
可以抓取什么样的数据
网页文本:如HTML文档、Json格式文本等。
图片:获取的二进制文件保存为图片格式
视频:同样是二进制文件
其他:只要要求,就可以得到
如何解析数据直接处理Json解析正则表达式处理BeautifulSoup解析处理PyQuery解析处理XPath解析处理关于抓取到的页面数据和浏览器中看到的区别的问题
出现这种情况是因为网站中的很多数据是通过js和ajax动态加载的,所以直接通过get请求获取的页面和浏览器显示的不一样。
如何解决js渲染的问题?
分析ajax
硒/网络驱动程序
溅
PyV8,Ghost.py
如何保存数据
文本:纯文本、Json、Xml 等。
关系型数据库:结构化数据库如mysql、oracle、sql server等。
非关系型数据库:MongoDB、Redis 等键值存储
什么是请求
Requests 是基于 urllib 用 python 语言编写的,使用 Apache2 Licensed 开源协议的 HTTP 库
如果你看过之前关于urllib库使用的文章文章,你会发现urllib还是很不方便的,而且Requests比urllib方便,可以为我们省去很多工作。(使用requests之后,你基本上就不想使用urllib了。)总之,requests是python实现的最简单易用的HTTP库。建议爬虫使用 requests 库。
默认安装python后,没有安装requests模块,需要通过pip单独安装
请求函数整体功能的详细演示
import requests
response = requests.get("https://www.baidu.com")
print(type(response))
print(response.status_code)
print(type(response.text))
print(response.text)
print(response.cookies)
print(response.content)
print(response.content.decode("utf-8"))
查看代码
可以看到response确实用起来很方便,有一个问题需要注意:
很多情况下,网站直接response.text会导致乱码,所以这里使用response.content
这种方式返回的数据格式其实是二进制格式,然后通过decode()转换成utf-8,解决了通过response.text直接返回显示乱码的问题。
请求发送后,Requests 将根据 HTTP 标头对响应的编码进行有根据的猜测。当您访问 response.text 时,Requests 将使用其推断的文本编码。您可以找出请求使用的编码,并且可以使用 response.encoding 属性来更改它。例如:
response =requests.get("http://www.baidu.com")
response.encoding="utf-8"
print(response.text)
无论是通过response.content.decode("utf-8)还是通过response.encoding="utf-8",都可以避免乱码的问题
多种请求方式
requests中提供了多种请求方式
import requests
requests.post("http://httpbin.org/post")
requests.put("http://httpbin.org/put")
requests.delete("http://httpbin.org/delete")
requests.head("http://httpbin.org/get")
requests.options("http://httpbin.org/get")
问
基本的 GET 请求
import requests
response = requests.get(\'http://httpbin.org/get\')
print(response.text)
带参数的 GET 请求,示例 1
import requests
response = requests.get("http://httpbin.org/get?name=zhaofan&age=23")
print(response.text)
如果我们想在 URL 查询字符串中传递数据,我们通常通过 /get?key=val 传递它。Requests 模块允许使用 params 关键字传递参数,并使用字典来传递这些参数。示例如下:
import requests
data = {
"name":"zhaofan",
"age":22
}
response = requests.get("http://httpbin.org/get",params=data)
print(response.url)
print(response.text)
上面两个的结果是一样的。通过params参数传递字典内容直接构造url
注意:第二种方式通过字典时,如果字典中的参数为None,则不会添加到url
解析json
import requests
import json
response = requests.get("http://httpbin.org/get")
print(type(response.text))
print(response.json())
print(json.loads(response.text))
print(type(response.json()))
从结果可以看出,requests中集成的json实际上执行的是json.loads()方法,两者的结果是一样的
获取二进制数据
在上面提到的response.content中,这种方式得到的数据是二进制数据,同样的方法也可以用来下载图片和
视频资源
添加标题
和我们之前使用 urllib 模块时一样,我们也可以自定义头部信息。比如我们直接通过requests请求知乎网站时,默认是不可访问的。
import requests
response =requests.get("https://www.zhihu.com")
print(response.text)
这将得到以下错误
因为访问知乎需要头部信息,此时我们在谷歌浏览器中输入chrome://version,然后就可以看到用户代理了,在头部信息中添加用户代理
import requests
headers = {
"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
}
response =requests.get("https://www.zhihu.com",headers=headers)
print(response.text)
然后就可以正常访问知乎
基本的 POST 请求
通过在发送post请求时添加一个data参数,这个data参数可以通过字典来构造,所以
非常方便发送post请求
import requests
data = {
"name":"zhaofan",
"age":23
}
response = requests.post("http://httpbin.org/post",data=data)
print(response.text)
同样,在发送 post 请求时,您也可以像发送 get 请求一样通过 headers 参数传递字典类型的数据。
回复
我们可以通过response得到很多属性,例子如下
import requests
response = requests.get("http://www.baidu.com")
print(type(response.status_code),response.status_code)
print(type(response.headers),response.headers)
print(type(response.cookies),response.cookies)
print(type(response.url),response.url)
print(type(response.history),response.history)
结果如下:
状态码判断
Requests 还带有一个内置的状态代码查询对象
主要内容如下:
100: (\'继续\',),
101: (\'switching_protocols\',),
102:(\'处理\',),
103:(\'检查点\',),
122:(\'uri_too_long\',\'request_uri_too_long\'),
200: (\'ok\', \'okay\', \'all_ok\', \'all_okay\', \'all_good\', \'\o/\', \'✓\'),
201: (\'创建\',),
202: (\'接受\',),
203:(\'non_authoritative_info\',\'non_authoritative_information\'),
204: (\'no_content\',),
205:(\'reset_content\',\'reset\'),
206:(\'partial_content\',\'partial\'),
207:(\'multi_status\'、\'multiple_status\'、\'multi_stati\'、\'multiple_stati\'),
208:(\'已经报告\',),
226:(\'im_used\',),
重定向。
300: (\'multiple_choices\',),
301: (\'moved_permanently\', \'moved\', \'\o-\'),
302:(\'找到\',),
303:(\'see_other\',\'其他\'),
304: (\'not_modified\',),
305: (\'use_proxy\',),
306: (\'switch_proxy\',),
307:(\'temporary_redirect\'、\'temporary_moved\'、\'temporary\')、
308:(\'永久重定向\',
\'resume_incomplete\', \'resume\',), #这2个要在3.0中去掉
客户端错误。
400: (\'bad_request\', \'bad\'),
401: (\'未经授权\',),
402: (\'payment_required\', \'payment\'),
403:(\'禁止\',),
404:(\'not_found\',\'-o-\'),
405:(\'method_not_allowed\',\'not_allowed\'),
406: (\'not_acceptable\',),
407:(\'proxy_authentication_required\'、\'proxy_auth\'、\'proxy_authentication\')、
408: (\'request_timeout\', \'timeout\'),
409:(\'冲突\',),
410:(\'不见了\',),
411: (\'length_required\',),
412:(\'前提条件失败\',\'前提条件\'),
413请求实体太大\',),
414:(\'request_uri_too_large\',),
415:(\'unsupported_media_type\'、\'unsupported_media\'、\'media_type\')、
416:(\'requested_range_not_satisfiable\'、\'requested_range\'、\'range_not_satisfiable\'),
417:(\'期望失败\',),
418:(\'im_a_teapot\'、\'teapot\'、\'i_am_a_teapot\')、
421:(\'misdirected_request\',),
422:(\'不可处理的实体\',\'不可处理的\'),
423:(\'锁定\',),
424:(\'failed_dependency\',\'dependency\'),
425:(\'unordered_采集\',\'unordered\'),
426:(\'upgrade_required\',\'upgrade\'),
428:(\'前提条件\',\'前提条件\'),
429:(\'too_many_requests\',\'too_many\'),
431:(\'header_fields_too_large\',\'fields_too_large\'),
444:(\'无响应\',\'无\'),
449:(\'retry_with\',\'retry\'),
450:(\'blocked_by_windows_parental_controls\',\'parental_controls\'),
451:(\'unavailable_for_legal_reasons\',\'legal_reasons\'),
499:(\'client_closed_request\',),
服务器错误。
500: (\'internal_server_error\', \'server_error\', \'/o\\', \'✗\'),
501: (\'not_implemented\',),
502错误的网关\',),
503: (\'service_unavailable\', \'unavailable\'),
504网关超时\',),