爬虫

爬虫

爬虫的概念

爬虫是模拟浏览器发送请求,获取响应

爬虫的定义

网络爬虫(又称为网页蜘蛛,网络机器人)就是模拟客户端发送网络请求,接收请求相应,一种按照一定的规则,自动地抓取换联网信息的程序

只要是浏览器能做的事情,原则上,爬虫都能做。

爬虫的流程

1.url–>发送请求获取响应—>提取数据–>保存
2.发送请求,获取响应---->提取url

import json
t = json.loads("{}")

URL的形式

形式: scheme://host[:port#]/path/…/[?query-string][#anchor]

scheme:协议(例如:http,https,ftp)
host:服务器的IP地址或者域名
port:服务器的端口(如果走协议默认端口,80 or 443)
path:访问资源的路径
query-string:参数,发送给http服务器的数据
anchor:锚/主播名(跳转到网页的指定锚点位置)

HTTP的请求形式

在这里插入图片描述

以百度网站为例:

在这里插入图片描述
Connection: keep-alive (常链接),避免三次挥手四次握手,提高浏览器打开的效率

在这里插入图片描述
用户代理分析:(或者称为浏览器使用的标识)

Mozilla/5.0:浏览器的 内核版本
(Windows NT 10.0; Win64; x64) : 电脑的信息
AppleWebKit/537.36: 苹果浏览器的内核版本名字和版本号
Chrome/90.0.4430.93:谷歌浏览器的内核版本和版本号

每个浏览器都有自己的内核版本和版本号,这导致网页打开的效果是不一样的。

我们来做一个简单的实验:
由切换设备工具栏来在电脑上打开一个手机的浏览界面。(左上角可知我们切换到的是iphone 5/5se)
在这里插入图片描述

这时的用户代理:
在这里插入图片描述
此时的浏览器内核版本变成了:iPhone; CPU iPhone OS 10_3_1 like Mac OS X

问题: 为什么网页url都是一样的,显示却不是同一样的内容
回答: 通过用户代理,来模仿或伪装成一个手机浏览器,我们只需要把useragent变成手机版的就可以了

在这里插入图片描述

Upgrade-Insecure-Requests: 告诉浏览器支持将一些不安全的请求转换成安全的请求—>http转换成https

在这里插入图片描述

Accept-Encoding: 表示浏览器告诉服务端要接受什么样的数据压缩格式(压缩:减小数据体积,提高效率)
Accept-Language: 可以接收什么样的数据(q = ??表示接收的权重)

在这里插入图片描述
Cookie:保存在浏览器本地的用户数据(不安全,有存储上限)
反爬虫和反反爬虫都用Cookie来解决: 因为爬虫并不会启用网站下的Cookie

常见的请求方法

GET:把参数包含在URl中,一般都用GET请求
POST:适合在数据比较大的时候,提交表单,图片,翻译(数据比较多的大文本)

响应状态码(status code)

200:成功
302:临时转移至新的url
307:临时转移至新的url
404:not found
500:服务器内部错误

爬虫的分类

通用爬虫:通常是指搜索引擎的爬虫
聚焦爬虫:针对特定网站的爬虫

通用搜索引擎的工作原理:
想一想:
  如果自己要实现一个和百度新闻一样的网站需要怎么做?

替换数据库里的数据为新闻。写爬虫爬取新闻。发送请求,得到url,提取数据。

在这里插入图片描述

为什么会有从响应中提取url地址: 只能拿到标题和标题地址,要获取新闻内容需要重新爬取,发送一个请求。(也就是重新爬)

爬虫的更多用途

12306抢票
网站上的投票
短信轰炸

搜索引擎的工作原理及robots协议

网站点击数、相关性
pagerank算法

通用搜索引擎的局限性:

通用搜索引擎所返回的网页里90%的内容无用
图片、音频、视频多媒体的内容通用搜索引擎无能为力
不同用户搜索的目的不同,但是返回内容相同

robots协议:网页通过robors协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取。(道德层面的约束,无法真正阻止)
例如:(淘宝)https://www.taobao.com/robots.txt
在这里插入图片描述
图中百度遵循了淘宝的robots协议(也可能没遵守,爬了没显示,哈哈哈

浏览器发送HTTP请求的过程

在这里插入图片描述
爬虫要根据当前url地址对应的相应为准,当前url地址的elements的内容和url的响应不一样,因为js可能会调整页面的内容
页面上的数据在哪里呢?

当前url地址对应的响应中
其他的url地址对应的响应中,例如ajax请求中(局部更新页面)
js生成的,第一种是部分数据在响应中,第二种是全部通过js生成的

发送简单的请求

需求: 通过requests向百度首页发送请求,获取百度首页的数据

response = requests.get(url)

response的常用方法:

response.text
response.content
response.status_code 获取状态码
response.requests.headers
response.hesders

import requests
response = requests.get("http://www.baidu.com")
print(response.status_code)  #打印状态码
print(response.headers)  #响应头信息
print(response.request.headers)  #请求头,没有user-Agent的情况下requsets模块会自动生成一个
print(response.request.url)
print(response.url)
print(response.content.decode())  #由于没设置用于代理,该部分内容很少,容易被识别出为网络爬虫

运行结果:(不是200就失败了,是200有可能请求成功,只代表请求某一个url地址成功,而不是我们想要的url地址成功了)
在这里插入图片描述
判断请求是否成功
可以使用断言判断:(r如果成功返回200则不会报错)

assert:布尔类型,条件为真则断言成功,为假断言失败

assert  response.status_code==200

发送带header的请求

为什么请求需要带上header?

模拟浏览器,欺骗服务器,获取和浏览器内容一致的内容

header的形式:字典
用法:requests.geturl(url,headers = headers)

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36"}
response = requests.get("http://www.baidu.com",headers=headers)
print(response.content.decode())

运行效果:和网页代码量基本一致
tip:若是只带上user-Agent还是不能够欺骗服务器,我们可以多带上几个参数,甚至带上get-cookies

发送带参数的请求

什么叫做请求参数:

例一:http://www.webkaka.com/tutorial/server/2015/021013/   (×)
例二:https://www.baidu.com/s?wd=python&c=b

关键的参数:‘wd’
参数的形式:字典
用法:requests.get(url,params=kw)

import requests

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36"}

p = {'wd':'python'}
url_temp = "https://ww.baidu.com/s?"     #问号可有可无

r = requests.get(url_temp,headers = headers,params=p)
print(r.status_code)

print(r.request.url)   #打印经过url编码的url地址

运行效果:(可以通过在线url解码或得原来的url地址)
在这里插入图片描述
另一种方式,url字符创格式化:(format)

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36"}

url="https://ww.baidu.com/s?wd={}".format('知乎')
r = requests.get(url)
print(r.status_code)
print(r.request.url)

动手尝试

实现认识贴吧的爬虫,保存前一千页到本地

思路:找到url地址的构造规律,循环实现爬取,传入贴吧名字(以百度贴吧为例)

#coding: utf-8
import requests

class Spider():
    def __init__(self,name):
        self.name = name
        self.url_temp = "https://tieba.baidu.com/f?kw="+name+"&ie=utf-8&pn={}"
        self.headers ={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36"}

    def get_url(self):
        return [self.url_temp.format(i*50) for i in range(1000)]

    def get_decode(self,url):
        print(url)
        response = requests.get(url,headers = self.headers)
        return response.content.decode()

    def save(self,html_str,page):
        file_path = "{}--第{}页.html".format(self.name,page)
        with open(file_path,"w",encoding="utf-8") as f:
            f.write(html_str)

    def run(self):
        #构造url列表
        url_list = self.get_url()
        #遍历发送请求,获取响应
        for x in url_list:
            html_str = self.get_decode(x)
        #保存入文件
            self.save(html_str,url_list.index(x)+1)

if __name__ == '__main__':
	tieba_name = input("输入想要获取的贴吧名:")
    spider = Spider(tieba_name)
    spider.run()

运行效果:(部分)
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值