网络数据采集 ----> 爬虫(蜘蛛)(1)

1.基本知识

中小企业是很缺乏数据,要么选择购买数据,要么选择爬虫采集数据

1. 怎么写爬虫程序?

~ 获取页面的代码 ---> HTML ---> 数据放在HTML标签中
 ~ 解析HTML页面 ---> 正则表达式 / XPath / CSS选择器
 ~ 数据的持久化 ---> 文本文件(CVS)/ Excel / 数据库

2. 写爬虫程序违法吗?

~ 灰色地带 ---> 法不禁止即为许可
 ~ 如果被目标网站举证你有破坏别人动产的行为,打官司基本败诉
 ~ 遵循爬虫协议 ---> robots.txt
 ~ 如果不想遵守爬虫协议 ---> 隐匿自己的身份(让目标网站感觉不到你是一个爬虫程序,而是一个来自浏览器的正常请求)

3. 爬虫的分类:

~ 通用爬虫
 ~ 定向爬虫(只关注某领域的数据)

4. HTML

~ Hyper-Text Markup Language -----> 超文本标签语言
 ~ 浏览器就是HTML语言的解释器,它能够执行HTML书写的代码
 ~ HTML页面最核心的就是标签,除了标签之外,还有CSS和JavaScript

网页的头目 ![在这里插入图片描述]()

HTML = Tag(标签)+ CSS(层叠样式表)+ JavaScript(JS)
Tag ----> 数据(content)
CSS ----> 显示(display) —> 选择器(负责页面渲染)
JS ----> 行为(behavior) —> 代码(交互式行为)

练习: 获取搜狐首页HTML代码

1.requests ------>基于HTTP(S)协议联网的三方库

加载方式:在pycharm中打开终端Terminal输入
pip config set global.index-url https://pypi.doubanio.com/simple
给pip改配置,改成国内的豆瓣镜像。再输入pip install requests安装requests

import requests

resp = requests.get('https://www.sohu.com:443/index.html')
print(type(resp), resp.status_code)
# <class 'requests.models.Response'> 200
# response对象,服务器返回的响应对象
"""
response对象有个属性是content可以获取页面二进制的内容
"""
print(resp.text)
# 直接获取返回的文本内容
print(resp.contect.decode('utf-8'))
# 如果直接获取resp.text有乱码的话可以解码字节串
# 有些网站是压缩过的,占空间更小,传输更快

str --------> 字符串 --------> encode() ------->bytes
bytes -------> 字节串 --------->decode() --------> str

5.URL和URI

~ URI ---> 统一资源标识符 ---> Universal Resource Identifier ---> 网络上的一个资源的唯一标识
 ~ URI ---> URL + URN(唯一标识举例:urn:isbn:978-7-5596-0344-9)
 ~ URL ---> 网址 ---> Uniform Resource Locator ---> 统一资源定位符

一个完整的URL
https://username:password@www.sohu.com:443/path1/path2/index.html 协议://用户名:口令@主机(服务器域名或IP地址):端口号/路径/子路径/资源名称

import requests

resp = requests.get('https://www.sohu.com:443/index.html')
print(type(resp), resp.status_code)
print(resp.text)

获取百度的LOGO

import requests
resp = requests.get('https://www.baidu.com/img/PCpad_012830ebaa7e4379ce9a9ed1b71f7507.png')
print(resp.content)# 结果就是图片的二进制数据
with.open('baidu_logo.png', 'wb') as file:
    file.write(resp.content)
# 图片不是纯文本的,图片是二进制文件

6. HTTP —> 超文本传输协议

import requests

resp = requests.get('https://www.sohu.com:443/index.html')
print(type(resp), resp.status_code)
# resp.status响应状态码为 200,则可以访问
~ 请求
   \- 请求行:请求方式 请求路径 协议版本
   \- 请求头:键值对
     ~ Host ---> 请求的主机
     ~ Accept ---> 接受的内容类型
     ~ User-Agent ---> 操作系统和浏览器平台 ---> 如果爬虫要伪装成浏览器,就需要设置该项
     ~ Accept-Language ---> 浏览器的语言设定
     ~ Accept-Encoding ---> 编码和压缩方式
   \- 空行
   \- 消息体:浏览器要发给服务器的数据

~ 响应
\- 响应行:协议版本 响应状态码
  ~ 2xx:成功
  ~ 3xx:重定向
  ~ 4xx:请求有问题
    \- 404:Not Found ---> 找不到对应的资源
    \- 401:Unauthorized ---> 未授权
    \- 403:Forbidden ---> 禁用(没有权限)
    \- 405:Method not Allowd ---> 请求的方式不对
    \- 418:I am a tea pot ---> 服务器给不了你想要的内容
  ~ 5xx:服务器卵了
\- 响应头:键值对!
\- 空行
\- 消息体:服务器给浏览器的内容 ---> (如果请求的是网页,消息体里面就是HTML代码;如果请求的是图片,消息体里面就是图片的二进制数据)

爬虫Process finished with exit code 0_HTML

7. HTTPS

~ HTTP over SSL —> 安全的HTTP
获取搜狐首页

import re
import requests


pattern = re.compile(r'\<a\s+.*?href=\"(.+?)" .*?title=[\'\"](.+?)[\'\"]\>')
resp = requests.get(
      url='https://www.sohu.com/',
      headers={  # headers请求头
              'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/88.0.4324.190 Safari/537.36'
             }
)
print(resp.status_code)
print(resp.text)

获取豆瓣电影Top250电影名称
法一:正则表达式

import re
import time
import random
import requests
# 正则表达式的捕获组:捕获电影标题
pattern = re.compile(r'\<span class="title"\>(.+?)\<\/span\>')
for page in range(10):
    resp = requests.get(
          url='https://movie.douban.com/top250?start={page * 25}/',
                                             # 参数名=参数值,获取25页
          headers={
              'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
                            'AppleWebKit/537.36 (KHTML, like Gecko)'
                            'Chrome/88.0.4324.190 Safari/537.36'
                            # 字符串太长为了美观可以折行,折行注意空格不能变少了
                   }
    )
    print(resp.status_code)
    movie_titles = pattern.findall(resp.text)
    for title in movie_titles:
        print(title)
    time.sleep(random.randint(3, 5))
    # 随机休眠3-5秒