网络爬虫简介
一、什么是爬虫
爬虫:爬虫就是模拟浏览器进行获取数据
网络爬虫可分为 通用爬虫 和 聚焦爬虫 两种
(1)、通用爬虫
将互联网上的网页下载到本地,形成一个互联网内容的镜像备份
1、抓取网页:
网络爬虫的基本工作流程如下:
-
首先选取一部分的种子URL,将这些URL放入待抓取URL队列
-
取出待抓取URL,解析DNS得到主机的IP,并将URL对应的网页下载下来,存储进已下载网页库中,并且将这些URL放进已抓取URL队列
-
分析已抓取URL队列中的URL,分析其中的其他URL,并且将URL放入待抓取URL队列,从而进入下一个循环…
2、数据存储:
搜索引擎通过爬虫爬取到的网页,将数据存入原始页面数据库。其中的页面数据与用户浏览器得到的HTML是完全一样的
搜索引擎蜘蛛在抓取页面时,也做一定的重复内容检测,一旦遇到访问权重很低的网站上有大量抄袭、采集或者复制的内容,很可能就不再爬行
3、预处理:
搜索引擎将爬虫抓取回来的页面,进行各种步骤的预处理
- 提取文字
- 中文分词
- 消除噪音(比如版权声明文字、导航条、广告等……)
- 索引处理
- 链接关系计算
- 特殊文件处理
除了HTML文件外,搜索引擎通常还能抓取和索引以文字为基础的多种文件类型,如 PDF、Word、WPS、XLS、PPT、TXT 文件等。我们在搜索结果中也经常会看到这些文件类型
但搜索引擎还不能处理图片、视频、Flash 这类非文字内容,也不能执行脚本和程序
(2)、聚焦爬虫
聚焦爬虫在实施网页抓取时会对内容进行处理筛选,尽量保证只抓 取与需求相关的网页信息
(3)、str和bytes的区别
bytes: bytes对象只负责以二进制字节序列的形式记录所需记录 的对象,至于该对象到底表示什么(比如到底是什么字符)则由相 应的编码格式解码所决定
bytes是Python 3中特有的,Python 2 里不区分bytes和str。
python3中:
str 使用encode编码方法转化为 bytes
bytes通过decode解码转化为str
在Python 2中由于不区分str和bytes所以可以直接通过encode()和 decode()方法进行编码解码
二、Request,让HTTP服务人类
- 安装request
pip install requests
-
url:统一资源定位符
-
作用:定位互联网上的任意资源的位置。
-
组成:
http://www.baidu.com:80/index.html?a=10&c=10#top
- http:协议
- www.baidu.com:网络地址–ip
- 80:端口
- index.html:路由–path路径
- ?a=10&c=10:请求参数
- #后面是锚点
-
get:获取,从服务器获取数据 ,获取什么(可以通过参数取告诉服务),请求参数是拼接的url里面的—不安全和大小受限的缺陷
-
使用requests发送get请求
(1)导入requests模块
import requests(2)发送请求,获取响应
response = requests.get( url=请求url地址, headers = 请求头字典, params=请求参数字典)
-
response对象的属性
1、字符串响应内容
response.text
2、二进制响应内容
response.content
3、json响应内容
response.json()
4、响应状态码
response.status_code
5、响应头
response.headers
6、设置编码格式
(1)第一种方式
response.encoding
(2)第二种方式
response.content.decode(‘正确的编码’)
-
post:提交,向服务器传递数据,提交数据放在客户端请求的请求数据的位置,更安全了而且大小是不受限的
-
什么是长连接:数据传输完成了保持TCP连接不断开(不发RST包、不四次握手),等待在同域名下继续用这个通道传输数据;相反的就是短连接
三、浏览器输入url回车到加载出页面,都做了哪些操作
1、第一步:浏览器中输入url地址并确认
2、第二步:这个时候会根据输入的url域名到DNS域名解析系统中解析到具体的IP地址
3、第三步:拿到IP地址之后会根据这个IP地址链接到具体的服务器。并建立TCP的链接
4、第四步:此时发起Http请求到服务器
5、第五步:服务器在接收到http请求之后,会根据http请求的邀请,进行响应请求结果,并将响应结果放在http请求中返回给浏览器
6、第六步:浏览器在接收到http响应之后,在进行解析渲染响应结果
7、第七步:浏览器进行显示渲染结果
四、爬虫案列
(1)新浪新闻搜索的爬取
import requests
def get_news1(key_word):
'''
使用requests.get方法的params参数来进行带参数的get请求的数据爬取。
:param key_word:
:return:
'''
# 确定基础url:?及其之前的内容
base_url = 'https://search.sina.com.cn/?'
# 准备参数字典
params = {
'q': key_word,
'range': 'all',
'c': 'news',
'sort': 'time',
}
# 发送请求获取响应
response = requests.get(url=base_url, params=params)
with open(f'sina_{key_word}1.html', 'w', encoding='utf-8') as fp:
fp.write(response.text)
def get_news2(key_word):
'''
通过拼接的方式
这种方式比较好用,但是当参数比较多的时候,建议使用第一种。
:param key_word:
:return:
'''
base_url = 'https://search.sina.com.cn/?q=%s&range=all&c=news&sort=time'
# 发送请求获取响应
response = requests.get(base_url % key_word)
with open(f'sina_{key_word}2.html', 'w', encoding='utf-8') as fp:
fp.write(response.text)
if __name__ == '__main__':
key_word = input('请输入要爬取的新闻关键字:')
get_news2(key_word)
(2)百度贴吧分页的爬取
import requests, os
# 批量的爬取:分页,get请求的参数中的一个参数来控制的。
# pn =0 1
# pn=50 2
# pn=100 3
def get_page(kw, page):
'''
获取一页贴把数据
:param kw: 贴吧的名称
:param page: 页码 1,2...
:return:
'''
# 确定url
base_url = 'https://tieba.baidu.com/f?'
params = {
'kw': kw,
'ie': 'utf-8',
'pn': (page - 1) * 50,
}
response = requests.get(base_url, params=params)
dirname = f'./tieba/{kw}'
if not os.path.exists(dirname):
os.mkdir(dirname)
with open(f'{dirname}/{page}.html', 'w', encoding='utf-8') as fp:
fp.write(response.text)
print(f'{dirname}/{page}.html下载完成!')
if __name__ == '__main__':
kw = input('请输入关键字:')
for i in range(1, 11):
get_page(kw, i)
(3)百度翻译的爬取
import requests
# 什么样的代码是好代码?
def translate_word(word):
'''
翻译单词
:param word: 单词
:return: 中文解释
'''
# 确定url
base_url = 'https://fanyi.baidu.com/sug'
# 准备参数
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36',
'x-requested-with': 'XMLHttpRequest',
'content-length': str(len(word) + 3),
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
}
data = {
'kw': word,
}
response = requests.post(base_url, headers=headers, data=data)
# print(response.json())
# return response.json()
# print(type(response.json()))
result = ''
for data in response.json()['data']:
result += data['v'] + '\n'
return result
def main():
# 1、确定翻译内容
word = input('请求输入单词:')
# 2、翻译
result = translate_word(word)
# 3、显示
print(result)
if __name__ == '__main__':
main()