欢迎来到十九分快乐的博客

生死看淡,不服就干。

1. 爬虫基础

爬虫基础

1.简介

爬虫:通过编写程序模拟浏览器上网,然后让其去互联网上抓取数据的过程

应用分类:

1.通用爬虫:抓取一整页面源码内容
2.聚焦爬虫:抓取页面中局部的指定数据
3.增量式:监测网站数据更新的情况。
4.分布式

2.requests:模拟浏览器上网

编码流程:

1.指定url
2.发起请求
3.获取响应数据
4.持久化存储

requests 基本使用

import requests
# 请求路径
url = 'https://www.sogou.com/'
# get请求返回响应对象
response = requests.get(url=url)

# 获取相应数据
page_text = response.text #text返回的是字符串形式的相应数据
print(page_text)

# 储存数据
with open('./sogou.html','w',encoding='utf-8') as fp:
    fp.write(page_text)

异常访问请求

- 异常的访问请求:
    - 非浏览器发起的请求。
    - 网站的后台是如何监测请求是否为异常请求?
        - 请求头信息:User-Agent
            - UA:请求载体的身份标识
- 反爬机制:UA监测
- 反反爬策略:UA伪装
抓包工具(浏览器检查) -- Network中 -- 请求头有本机的User-Agent
# 制作一个简易的网页采集器 -- 搜狗搜索

import requests

url = 'https://www.sogou.com/web'

word = input('输入搜索关键字:')
# 请求参数
params = {
    'query':word
}
# User-Agent伪装
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36'
}

response = requests.get(url=url,params=params,headers=headers)


filename = word+'.html'

with open(filename,'w',encoding='utf-8') as fp:
    fp.write(response.text)

获取图片数据

import requests

# 网址
url = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fuserimage5.360doc.com%2F14%2F0601%2F02%2F14256129_201406010211550401.jpg&refer=http%3A%2F%2Fuserimage5.360doc.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1621499086&t=21d6a3fded64dd6af2dba9b6507e5d45'

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

response = requests.get(url=url,headers=headers)

# 获取图片的batys数据:content
json_data = response.content

# 保存
with open('舒畅.jpg','wb') as fp:
    fp.write(json_data)

3.动态加载数据

流程:

- 动态加载数据
    - 概念:通过对浏览器地址栏的url发起请求获取不到的数据
    - 动态加载数据的监测
        - 基于抓包工具进行局部搜索
    - 如何捕获动态加载数据?
        - 基于抓包工具进行全局搜索,定位动态加载数据对应的数据包,从数据包中可以提取
            - url
            - 请求方式
            - 请求参数
            - 请求头信息

示例1:get请求

# 豆瓣电影数据

import requests

headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36',
}
url = 'https://movie.douban.com/j/chart/top_list'

# get请求携带的参数
params = {
    'type': '25',
    'interval_id': '100:90',
    'action':'' ,
    'start': '0',
    'limit': '20',
}

# 获取响应的数据
json_data = requests.get(url=url,headers=headers,params=params).json()
print(json_data)

示例2:post请求

# 肯德基线下门店查询
# http://www.kfc.com.cn/kfccda/storelist/index.aspx

import requests

url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword'

headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36'
}
# 获取前5页的数据
for index in range(1,6):
    # post请求携带的参数:
    data = {
        'cname': '',
        'pid': '',
        'keyword': '北京',
        'pageIndex': index,
        'pageSize': 10,
    }
    # 获取请求数据
    response = requests.post(url=url,data=data,headers=headers)

    json_data = response.json()['Table1']

    for i in json_data:
        # 打印点名 -- 地址
        print(i['storeName'],i['addressDetail'])

示例3:多次请求联合获取数据

# 药监总局网站 http://scxk.nmpa.gov.cn:81/xk/

# 查询公司详细信息:

import requests

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

list_id = []
# 1.获取公司的id地址
url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList'

# post请求携带数据
data = {
    'on': 'true',
    'page': 1,
    'pageSize': 15,
    'productName': '',
    'conditionType': 1,
    'applyname': '',
}

# 发送post请求获取响应数据
json_data = requests.post(url,data=data,headers=headers).json()['list']

for i in json_data:
    list_id.append(i['ID'])

# 2.基于公司id获取获取公司的详细信息

# 公司的详细信息地址
url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById'

for id in list_id:
    # post请求携带参数
    data = {
        'id':id
    }
    # 发送post请求获取响应数据
    json_data = requests.post(url,data,headers).json()
    print('>>>',json_data['epsName'])

4.数据解析

1.数据解析作用: 实现聚焦爬虫

2.数据解析方式:

1.正则
2.bs4
3.xpath
4.pyquery

3.原理:

- 数据解析的通用原理
    - html是用作与数据展示。
        - 展示的数据在哪?
            - 标签的属性中
            - 标签中间
    - 原理:
        - 1.标签定位
        - 2.内容提取

4.测试页面数据:

text.html

<html lang="en">
<head>
	<meta charset="UTF-8" />
	<title>测试bs4</title>
</head>
<body>
	<div>
		<p>百里守约</p>
	</div>
	<div class="song">
		<p>李清照</p>
		<p>王安石</p>
		<p>苏轼</p>
		<p>柳宗元</p>
		<a href="http://www.song.com/" title="赵匡胤" target="_self">
			<span>this is span</span>
		宋朝是最强大的王朝,不是军队的强大,而是经济很强大,国民都很有钱</a>
		<a href="" class="du">总为浮云能蔽日,长安不见使人愁</a>
		<img src="http://www.baidu.com/meinv.jpg" alt="" />
	</div>
	<div class="tang">
		<ul>
			<li><a href="http://www.baidu.com" title="qing">清明时节雨纷纷,路上行人欲断魂,借问酒家何处有,牧童遥指杏花村</a></li>
			<li><a href="http://www.163.com" title="qin">秦时明月汉时关,万里长征人未还,但使龙城飞将在,不教胡马度阴山</a></li>
			<li><a href="http://www.126.com" alt="qi">岐王宅里寻常见,崔九堂前几度闻,正是江南好风景,落花时节又逢君</a></li>
			<li><a href="http://www.sina.com" class="du">杜甫</a></li>
			<li><a href="http://www.dudu.com" class="du">杜牧</a></li>
			<li><b>杜小月</b></li>
			<li><i>度蜜月</i></li>
			<li><a href="http://www.haha.com" id="feng">凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘</a></li>
		</ul>
	</div>
</body>
</html>

bs4 基本使用

1.安装:

pip install bs4

2.使用流程

- bs4基本使用流程:
    1.实例化一个BeautifulSoup对象,把即将被解析的页面源码数据加载到该对象中
    2.调用BeautifulSoup对象的属性和方法实现标签定位和数据提取

3.BeautifulSoup对象实例化

方式1: BeautifulSoup(fp,'lxml'):用来解析本地存储的网页文件
        
方式2: BeautifulSoup(page_text,'lxml'):用来解析网络中请求到的数据

4.解析本地存储的网页文件

from bs4 import BeautifulSoup

# 获取本地的文件句柄
fp = open('./test.html','r',encoding='utf-8')

# 实例化BeautifulSoup对象
soup = BeautifulSoup(fp,'lxml')

# 1.标签定位
#soup.tagName(标签名称):可以将第一次出现的该标签定位到
print(soup.div) # 获得一个对象

# 2.属性定位:find(tagName,attrName(属性名称)_='attrValue')
# 注意属性名称后有下划线
print(soup.find('div',class_='song')) # 获得一个对象
print(soup.findAll('div',class_='song')) # 获得对象列表

# 3.选择器定位
print(soup.select('#feng')) # 获取id='feng'的标签对象列表

# 4.层级选择器:>表示一个层级,空格可以表示多个层级
print(soup.select('.tang li > a')) # 获取class='tang'的标签里面的对象列表

# 5.获取标签文本
a_tag = soup.select('#feng')[0]
print(a_tag.string) # string -- 取直系文本

div_tag = soup.select('.song')[0]
print(div_tag.text) # text -- 取所有文本

# 6.获取标签属性
a_tag = soup.select('#feng')[0]
print(a_tag)
print(a_tag['href'])

5.解析网络中请求到的数据

爬取网络小说
import requests
from bs4 import BeautifulSoup

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

url = 'https://www.shicimingju.com/book/sanguoyanyi.html'

# 获取响应数据
response = requests.get(url)
# 如果获取的数据乱码,指定编码集 utf-8 或 gbk
response.encoding = 'utf-8'
page_text = response.text
# print(page_text)

fp = open('三国.text','w',encoding='utf-8') # 文件对象,保存小说数据

# 实例化BeautifulSoup对象
soup = BeautifulSoup(page_text,'lxml')

# 定位到小说章节标签
tag = soup.select('.book-mulu > ul > li >a')
# print(tag)
# 获取小说章节名称和路径
for i in tag:
    # 获取文章路径
    new_url = 'https://www.shicimingju.com'+i['href']
    # 获取小说章节名称
    title = i.string
    # print(new_url,title)
    # 发起get请求获取数据
    response = requests.get(new_url,headers=headers)
    response.encoding = 'utf-8' # 解决乱码
    p_text = response.text
    # print(article)

    # 实例化BeautifulSoup对象
    soup = BeautifulSoup(p_text, 'lxml')

    # 定位文章内容标签
    # article_tag = soup.select('.chapter_content')[0] # 两者都可以
    article_tag = soup.find('div',class_='chapter_content') #

    # 获取文章内容
    article_text = article_tag.text

    # 保存数据(标题和内容)
    fp.write(title+'\n'+article_text+'\n')
    print(title,'保存成功')

xpath 基本使用

1.安装:

pip install lxml

2.使用流程

- 编码流程 :
 1.实例化一个etree类型的对象,把即将被解析的页面源码数据加载到该对象中
 2.调用xpath方法结合着不同形式的xpath表达式进行标签定位和数据提取

3.etree 对象实例化

1. etree.parse(filePath) -- 用来解析本地存储的网页文件
2. etee.HTML(page_text) -- 用来解析网络中请求到的数据

4.解析本地存储的网页文件

from lxml import etree

# 实例化对象
tree = etree.parse('./test.html')

# 1.标签定位
#最左侧的/:必须从根节点逐层往下定位标签
#最左侧的//:从任意位置定位指定标签

tag = tree.xpath('/html/head/title')
tag = tree.xpath('/html//title')
tag = tree.xpath('//title')

# 2.属性定位
tag = tree.xpath('//div[@class="tang"]')
print(tag)

# 3.索引定位:索引时从1开始
tag = tree.xpath('//div[@class="tang"]/ul/li[3]')
print(tag)

# 4.取文本:/text()--取直系文本  //text()--取所有  
# 获取的都是列表数据 -- 索引取值
div_tag = tree.xpath('//div[@class="tang"]//text()')
print(''.join(div_tag))

# 5.取属性:/@attrName(属性名) -- 获取的也是列表数据
a = tree.xpath('//a[@id="feng"]/@href')[0]
print(a)


5.解析网络中请求到的数据

爬取图片
# 网址: 'https://pic.netbian.com/4kmeinv/'
import requests
from lxml import etree
import os

# 创建储存图片的文件夹
dirname = 'image'
# 判断文件夹是否存在,如果不存在新建目录
if not os.path.exists(dirname):
    os.mkdir(dirname)

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

url = 'https://pic.netbian.com/4kmeinv/index_%d.html'
# 爬取多张页数据
for i in range(1,10):
    if i == 1:
        new_url = 'https://pic.netbian.com/4kmeinv/'
    else:
        new_url = format(url%i)

    response = requests.get(new_url,headers=headers)
    response.encoding = 'gbk' # 防止乱码
    page_text = response.text
    # print(page_text)
    # 实例化对象
    tree = etree.HTML(page_text)

    # 取出li标签对象列表
    li_list = tree.xpath('//*[@id="main"]/div[3]/ul/li')
    # print(li_list)

    # 获取图片地址和名称
    for i in li_list:
        title = i.xpath('./a/b/text()')[0] + '.jpg'
        src = 'https://pic.netbian.com' + i.xpath('./a/img/@src')[0]
        # print(title,src)

        # 获取图片详细数据,保存图片
        response = requests.get(src,headers=headers)
        img_data = response.content # batys流数据
        # 拼接文件路径
        filepath = dirname + '/' + title
        with open(filepath,'wb') as fp:
            fp.write(img_data)
            print(title,'保存成功')

posted @ 2021-04-20 20:59  十九分快乐  阅读(94)  评论(0编辑  收藏  举报