爬虫基础知识

概述

定义:

  爬虫的本质:通过编写程序模拟浏览器上网,获取页面源码或在动态数据,通过解析返回结果获取想要的数据的过程

分类:

  1. 通用爬虫:获取整张页面的源码数据
  2. 聚焦爬虫:获取指定区域的数据,如页面加载时的一些动态数据
  3. 增量式爬虫:获取网站更新的数据

常见的反扒机制:

  1. robots.txt协议:可以在网页后面加上robots.txt,该协议规定允许哪些服务器爬取数据,但该协议像"无人地摊一样".(解决方法,当作看不到即可)
  2. UA协议:在请求头中有一个User-agent字段,该字段的值是关于浏览器的信息,有些网站没有该字段不让访问(解决方法:复制浏览器的请求ua字段)
  3. 验证码:通过输入验证码才能访问(采用云打码等第三方平台解码,然后填写到验证码输入框
  4. cookie:没有携带cookie的不允许访问(采用自动cookie处理即requests模块的Session实例化的对象代替requests)
  5. 检测ip:对于短期内多次数访问封ip(在requests请求中添加代理ip参数即可)
  6. 动态参数:通过给之前的网页分配一个隐藏的参数,页面请求是需要携带该参数,否则不允许访问(解析源码获取该参数)
  7. 动态加载数据:用户在浏览器的操作加载不同数据,(通过获取动态加载数据的url请求获取队形数据)

requests模块

requses模块是可以通过模拟浏览器发送请求获取页面的响应数据,安装模块:pip install requests

使用步骤:

  1. 指定url,请求头以及请求数据
  2. 向服务器发送数据
  3. 获取和解析数据
  4. 持久化存储

示例

# 需求:爬取搜狗指定词条搜索后的页面数据
import requests

# 1. 指定URL
url = "https://www.baidu.com/"
# 请求头数据
headers = {
    # 从浏览器复制过来的UA
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36"
}
#请求数据,可根据实际情况决定要不要
data = {
    "kw""cat"
}

# 2. 向服务器发送请求,该请求是get请求,如果是pose请求则如注释所示
response = requests.get(url=url, headers=headers,params=data)
# response = requests.post(url=url, data=data, headers=headers)

# 3. 获取响应数据,
page_text = response.text
# 如果返回的是json数据
# data = response.json()
# 如果返回的是视频或者图片等文件数据
# data = response.content


# 4. 持久化存储
with open('./lijie.html', 'w', encoding="utf-8") as f:
    f.write(page_text)

 

页面数据解析

当页面返回json()数据和content数据,可以直接将数据存储到本地,但如果返回的数据是text数据,通常返回的是html源码,这个时候就需要解析源码获取数据,常用的解析源码模块有bs4和lxml,其中,bs4模块是基于lxml模块的,所以想要使用就必须安装两个模块,通过pip install ba4和pip install lxml下载安装

bs4

通过模块的BeautifulSoup类来实例化一个对象soup

常用方法和属性

  1. 根据标签名查找标签:soup.a
  2. 获取标签属性:soup.a.attrs(获取所有属性名和值),soup.a.attrs["href"](获取a标签的href属性),soup.a["href"](获取href属性)
  3. 获取文本内容:soup.string(不能获取标签内部的标签的文本属性),soup.text/soup.get_text()(获取标签下所有文本)
  4. 获取第一个符合要求的标签:soup.find("标签名",属性名=“属性值”),如soup.find("a", class="test")
  5. 查找所有符合要求的标签:soup.find_all("标签名",属性名=“属性值”),如soup.find_all("a", class="test")
  6. 通过选择器查找标签:soup.select(标签选择器) #css中支持的这类基本都支持

案例

# 爬取诗词名句网http://www.shicimingju.com/book/index.html 前100个小说的所有内容, 每一个文章存一个txt文件, 并保存到文件夹中

import requests,os
from bs4 import BeautifulSoup

# 请求url,获取全部书籍都信息
url = "http://www.shicimingju.com/book/index.html"
headers = {
    # UA伪装
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
}
response_text = requests.get(url=url,headers=headers).text

# 实例化一个soup对象
soup = BeautifulSoup(response_text,"lxml")

# 通过选择器获取标签多个列表
book_detail_list = soup.select(".bookmark-list ul li a")
book_title = []

# 获取标签后得到标签的属性和文本
for i in book_detail_list:
    dic = {
        "title":i.text,
        "url":"http://www.shicimingju.com" + i.attrs["href"]
    }
    book_title.append(dic)

# 创建保存数据的目录
if not os.path.exists("./book"):
    os.mkdir("./book")

# 循环获取书籍的内容
for book in book_title:
    # 获取书籍rl
    book_url = book["url"]
    # 获取某本书籍的源码
    book_data = requests.get(url=book_url,headers=headers).text
    
    # 判断之前是否以及爬取过
    if os.path.exists("./book/" + book["title"] + ".txt"):
        continue
    
    # 实例化一个书籍的soup对象
    chapter_soup = BeautifulSoup(book_data,"lxml")
    
    # 查看书籍章节信息
    chapter_detail_list = chapter_soup.select(".book-mulu ul li a")
    filename = "book/"+book["title"] + ".txt"
    f = open(filename,"w",encoding="utf-8")
    # 获取书籍每章内容并保存在本地
    for i in chapter_detail_list:
        chapter_url = "http://www.shicimingju.com" + i.attrs["href"]
        response_data = requests.get(url=chapter_url,headers=headers).text
        soup = BeautifulSoup(response_data,"lxml")
        if len(soup.select(".www-main-container")) > 0:
            continue
        data = soup.select(".www-main-container")[0].text
        f.write(data)
        f.write("\r\n")
    f.close()

 

lxml

通过该模块解析数据好处是通用性强,通过模块提供的etree类实例化一个类对象tree,通过该对象加载数据后的xpath方法可以定位到标签,然后通过方法或属性来得到数据

实例化对象:tree = etree()

加载数据:tree.HTML(response_text)

定位数据:tree.xpath('//div[@id="test"]/div/p/a')

获取文本:tree.xpath('//div[@id="test"]/div/p/a/text()').extract()

获取属性:tree.xpath('//div[@id="test"]/div/p/a/@href').extract()

代码解析://后面的div表示定位到div标签,[]内部写的是标签属性,后面的/div/p/a/表示定位到div标签下的div标签下的p标签下的a标签,text()获取文本属性的对象,@href获取a标签的href属性对象,extract表是将对象转化成列表,通过列表就可以获取值,示例

# 爬取梨视频里面体育版块最热和最新的视频(.mp4的格式)并下载到本地, 保存到文件夹中https://www.pearvideo.com/category_9


import requests,os
from lxml import etree

# 指定url
url = "https://www.pearvideo.com/category_4"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
}

# 获取源码
response_text = requests.get(url=url,headers=headers).text

# 正则表达式
ex = 'srcUrl="(.*?)".*?vdoUrl=srcUrl'
# 实例化etree对象
tree = etree.HTML(response_text)
# 获取所有视频详情页的url, | 代表或运算
tree_list = tree.xpath('//ul[@class="listvideo-list clearfix"]/li/div/a/@href | //ul[@class="category-list clearfix"]/li/div/a/@href')
data_url_list = []
for new_url in tree_list:
    # 获取详情页url
    new_url = "https://www.pearvideo.com/" + new_url
    # 向详情页发送请求获取源码数据
    detail_text = requests.get(url=new_url,headers=headers).text
    
    # 通过正则湖区视频下载url
    data_list = re.findall(ex,detail_text,re.S)
    if len(data_list)>0:
        data_url_list.append(data_list[0])

if not os.path.exists("./video"):
    os.mkdir("./video")


for data_url in data_url_list:
    filename = "video/" + data_url.split("/")[-1]
    print(filename)
    with open(filename,"wb") as f:
        response = requests.get(url=data_url,headers=headers)
        f.write(response.content)

 

 

 

posted @ 2019-10-29 21:23  mark平  阅读(339)  评论(0编辑  收藏  举报