爬虫教程由浅入深,由自己学习经历编写的快速学习以及使用指南(从简单爬虫到scrapy框架)及例子

目录

1、requests 模块

2、无头浏览器or需要js加载的界面(暂时只放selenium了之后可能会更新Pyppeteer)

二、数据解析

1、xpath使用方法及基本语法

2、JSONPath使用和学习

3、BeautifulSoup

三、数据导出

四、简单爬虫

五、scrapy框架学习

1、项目创建

2、简单创建爬虫及执行

3、完整使用scrapy框架进行爬虫过程


1、requests 模块

  1. response的属性以及类型

    response.text : 获取网站源码
    response.encoding :访问或定制编码方式
    response.url :获取请求的url
    response.content :响应的字节类型
    response.status_code :响应的状态码
    response.headers :响应的头信息
    类型 :models.Response
  2. get请求

    import requests
    #请求地址
    url = 'http://www.baidu.com/s?'
    #请求头
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0'
    }
    #请求参数(path参数是可以的)
    data = {
        'wd':'北京'
    }
    print(requests.get(url,params=data,headers=headers))
  3. post请求

    import requests
    post_url = 'https://fanyi.baidu.com/sug'
    headers={
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0'
    }
    data = {
    'kw': 'eye'
    }
    r = requests.post(url = post_url,headers=headers,data=data)
    print(r.text)
    #get请求的参数名字是params post请求的参数的名字是data
  4. 代理

    #在请求中设置proxies参数
    #参数类型是一个字典类型 其实就是get的多一个参数
    import requests
    url = 'http://www.baidu.com/s?'
    headers = {
    'user‐agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML,
    like Gecko) Chrome/65.0.3325.181 Safari/537.36'
    }
    data = {
    'wd':'ip'
    }
    proxy = {
    'http':'219.149.59.250:9797'
    }
    r = requests.get(url=url,params=data,headers=headers,proxies=proxy)
    with open('proxy.html','w',encoding='utf‐8') as fp:
    fp.write(r.text)
  5. 验证码

    #要根据特殊的特殊对待
    #先给一个例子,一点一点剖析
    ​
    # 通过登陆  然后进入到主页面
    # 通过找登陆接口我们发现 登陆的时候需要的参数很多
    # _VIEWSTATE: /m1O5dxmOo7f1qlmvtnyNyhhaUrWNVTs3TMKIsm1lvpIgs0WWWUCQHl5iMrvLlwnsqLUN6Wh1aNpitc4WnOt0So3k6UYdFyqCPI6jWSvC8yBA1Q39I7uuR4NjGo=
    # __VIEWSTATEGENERATOR: C93BE1AE
    # from: http://so.gushiwen.cn/user/collect.aspx
    # email: 595165358@qq.com
    # pwd: action
    # code: PId7
    # denglu: 登录
    ​
    # 我们观察到_VIEWSTATE   __VIEWSTATEGENERATOR  code是一个可以变化的量
    ​
    # 难点:(1)_VIEWSTATE   __VIEWSTATEGENERATOR  一般情况看不到的数据 都是在页面的源码中
    #     我们观察到这两个数据在页面的源码中 所以我们需要获取页面的源码 然后进行解析就可以获取了
    #     (2)验证码
    ​
    import requests
    # 这是登陆页面的url地址
    url = 'https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx'
    ​
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
    }
    ​
    # 获取页面的源码
    response = requests.get(url = url,headers = headers)
    content = response.text
    ​
    # 解析页面源码  然后获取_VIEWSTATE   __VIEWSTATEGENERATOR
    from bs4 import BeautifulSoup
    ​
    soup = BeautifulSoup(content,'lxml')
    ​
    # 获取_VIEWSTATE
    viewstate = soup.select('#__VIEWSTATE')[0].attrs.get('value')
    ​
    # 获取__VIEWSTATEGENERATOR
    viewstategenerator = soup.select('#__VIEWSTATEGENERATOR')[0].attrs.get('value')
    ​
    ​
    # 获取验证码图片
    code = soup.select('#imgCode')[0].attrs.get('src')
    code_url = 'https://so.gushiwen.cn' + code
    ​
    # 有坑
    # import urllib.request
    # urllib.request.urlretrieve(url=code_url,filename='code.jpg')
    # requests里面有一个方法 session()  通过session的返回值 就能使用请求变成一个对象
    ​
    session = requests.session()
    # 验证码的url的内容
    response_code = session.get(code_url)
    # 注意此时要使用二进制数据  因为我们要使用的是图片的下载
    content_code = response_code.content
    # wb的模式就是将二进制数据写入到文件
    with open('code.jpg','wb')as fp:
        fp.write(content_code)
    ​
    ​
    # 获取了验证码的图片之后 下载到本地 然后观察验证码  观察之后 然后在控制台输入这个验证码 就可以将这个值给
    # code的参数 就可以登陆
    ​
    code_name = input('请输入你的验证码')
    ​
    ​
    # 点击登陆
    url_post = 'https://so.gushiwen.cn/user/login.aspx?from=http%3a%2f%2fso.gushiwen.cn%2fuser%2fcollect.aspx'
    ​
    data_post = {
        '__VIEWSTATE': viewstate,
        '__VIEWSTATEGENERATOR': viewstategenerator,
        'from': 'http://so.gushiwen.cn/user/collect.aspx',
        'email': '595165358@qq.com',
        'pwd': 'action',
        'code': code_name,
        'denglu': '登录',
    }
    ​
    response_post = session.post(url = url, headers = headers, data = data_post)
    ​
    content_post = response_post.text
    ​
    with open('gushiwen.html','w',encoding= ' utf-8')as fp:
        fp.write(content_post)
    ​
    ​
    # 难点
    # (1) 隐藏域
    # (2) 验证码
    #验证码基本都用第三方,第三方的也蛮便宜

2、无头浏览器or需要js加载的界面(暂时只放selenium了之后可能会更新Pyppeteer)

  1. chromedriver

    因为chrome会一直更新,所以这里会放一下如何下载chromedriver

  2. selenium使用

    #1.导入
    from selenium import webdriver
    #2.创建浏览器操作对象
    browser = webdriver.Chrome()
    #3.访问网站
    url = 'https://www.baidu.com/'
    #browser.get(url)
    #4.page_source获取网页源码
    content = browser.page_source
    print(content)
  3. selenium语法

    1.find element by id
        eg:button = browser.find element by_id('su')
    2.find elements by name
        eg:name = browser.find element by name('wd')
    3.find elements by_xpath
        eg:xpath1 = browser.find elements by_xpath('//input[@id="su"]')
    4.find elements by_tag name
        eg:names = browser.find elements by_tag name('input')
    5.find elements by_css selector
        eg:my_input = browser.find elements by_css selector('#kw')[o]
    6.find elements by link text
        eg:browser.find element by link text("新闻")
        
    7.获取元素属性
    get_attribute('class')
    8.获取元素文本
    .text
    9.获取标签名
    tag name
    ​
    10.交互
    点击:click()
    输入:send keys()
    后退操作:browser.back()
    前进操作:browser.forword()
    模拟JS滚动:
    js='document.documentElement.scrollTop=10000browser.execute script(js) 执行js代码
    获取网页代码: page_source
    退出: browser.quit()
  4. headless(无头浏览器)

    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    ​
    def share_brower():
        chrome_options = Options()
        chrome_options.add_argument('--headless')
        chrome_options.add_argument('--disable-gpu')
        # path是你自己的chrome浏览器的文件路径
        path = r'C:\Program Files\Google\Chrome\Application\chrome.exe'
        chrome_options.binary_location = path
        browser = webdriver.Chrome(options=chrome_options)
        return browser
    ​
    browser = share_brower()
    url = 'https://www.baidu.com'
    browser.get(url)

二、数据解析

1、xpath使用方法及基本语法

  1. 使用方法

    1、导包
        from lxml import etree
    2、etree.parse()解析本地文件
        html tree = etree.parse( 'xx.html')
    3、etree.HTML()服务器响应文件
        html_tree = etree.HTML(response.read().decode('utf-8').html
    4、tree.xpath(xpath路径)
  2. 基本语法

    xpath基本语法
    1.路径查询
        //: 查找所有子孙节点,不考虑层级关系
        / : 找直接子节点
    2.谓词查询
        //div[@id]
        //div[@id="maincontent"]
    3.属性查询
        //@class
    4.模糊查询
        //div[contains(@id,"he")]
        //div[starts-with(@id,"he")]
    5.内容查询
        //div/h1/text()
    6.逻辑运算
        //div[@id="head" and @class="s down"]
        //title | //price

2、JSONPath使用和学习

  1. 使用

    1、导包
        pip install jsonpath
    2、jsonpath的使用:
        obj = json.load(open('<json文件>','r',encoding='utf-8"))
        ret = jsonpath.jsonpath(obj,'<jsonpath语法>')
  2. 基本语法

    秉承站在巨人的肩膀上,我们直接学习这位巨人的讲解:JSONPath-简单入门-CSDN博客

3、BeautifulSoup

  1. 使用

    1.导入
        from bs4 import BeautifulSoup
    2.创建对象
        服务器响应的文件生成对象
            soup = Beautifulsoup(response.read().decode(),lxml')
        本地文件生成对象
            soup = Beautifulsoup(open(1.html'),'lxml')
            注意:默认打开文件的编码格式gbk所以需要指定打开编码格式
  2. 基本语法

    3.节点定位
        (1)根据标签名查找节点
            soup.a[注]只能找到第一个a
                soup.a.name
                soup.a.attrs
        (2)函数   
            <1>.find(返回一个对象)
                    find('a'): 只找到第一个a标签
                    find('a',title=名字)
                    find('a',class_=名字')  注意有下划线哦
            <2>.find all(返回一个列表)
                    find all(a) 查找到所有的a
                    find all(['a’,'span']) 返回所有的a和span
                    find all('a',limit=2) 只找前两个a
        (3)select(根据选择器得到节点对象)[推荐]
            <1>element
                eg:p
            <2>.class
                eg:.firstname
            <3>#id
                 eg:#firstname
            <4>属性选择器
                [attribute]
                    eg:li = soup.select('li[class]')
                [attribute=value]
                    eg:li = soup.select('li[class="hengheng1"]')
            <5>层级选择器
                element element
                  div p
                element>element
                  div>p
                element,element
                  div,p
                     eg:soup = soup.select('a,span')
    4.节点信息
        (1)获取节点内容: 适用于标签中嵌套标签的结构
            obj.string
            obj.get_text()[推荐]
        (2)节点的属性
            tag.name 获取标签名
                eg:tag = find(li)
                   print(tag.nametag.attrs将属性值作为一个字典返回
        (3)获取节点属性
            obj.attrs.get('title')[常用]
            obj.get('title')
            obj['title']

三、数据导出

因为本文的主要内容是爬虫实现已经方便之后使用爬虫时快速阅读,数据存储我就不赘述了,如果想学习的伙伴可以根据下面框架自行学习。(参考自Python 学习路线 by 程序员鱼皮 | 鱼皮的编程宝典 (codefather.cn)

  • 文件

    • Excel

    • CSV

  • 数据库

    • MongoDB

    • MySQL

  • 中间件

    • Redis

四、简单爬虫

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/119.0.0.0 Safari/537.36 Edg/119.0.0.0"
}
for startNum in range(0,250,25):
    response = requests.get(f"https://movie.douban.com/top250?start={startNum }", headers=headers)
    # print(response.status_code)
    if response.ok:
        content = response.text
        soup = BeautifulSoup(content, "html.parser")
        allTitles = soup.find_all("span", attrs={"class": "title"})
        for title in allTitles:
            if "/" not in title.string:
                print(title.string)

五、scrapy框架学习

1、项目创建

  1. spider项目生成

    scrapy startproject <项目名称>

    eg:

    scrapy startproject myspiderproject1
  2. 项目框架介绍

    │- scrapy.cfg             ->项目的配置文件
    │
    └─myspiderproject1
        │  items.py           ->自己预计需要爬取的内容
        │  middlewares.py     ->自定义中间件的文件(代理)
        │  pipelines.py       ->管道,清洗并保存数据
        │  settings.py        ->设置文件,UA,启动管道
        │  __init__.py        
        │
        └─spiders             ->自己定义的spider的文件夹
                __init__.py 

2、简单创建爬虫及执行

  1. 创建爬虫

    先进入创建的文件夹下(注意只进入第一层文件夹)

    cd <项目名称>

    再创建爬虫实体:

    scrapy genspider <爬虫实体名> <要爬虫的域名>

    eg:

    cd myspiderproject1
    
    scrapy genspider itcast itcast.cn

    文件夹结构

    │  scrapy.cfg
    │
    └─myspiderproject1
        │  items.py
        │  middlewares.py
        │  pipelines.py
        │  settings.py
        │  __init__.py
        │
        ├─spiders
        │  │  itcast.py           ->爬虫实体
        │  │  __init__.py
        │  │
        │  └─__pycache__
        │          itcast.cpython-39.pyc
        │          __init__.cpython-39.pyc
        │
        └─__pycache__
                settings.cpython-39.pyc
                __init__.cpython-39.pyc
  2. 爬虫实体文件及其内容

    import scrapy
    ​
    class ItcastSpider(scrapy.Spider):
        name = 'itcast'
        allowed_domains = ['itcast.cn']
        start_urls = ['http://itcast.cn/'] #初始爬虫网页
        def parse(self, response):
            #定义针对文件
            with open("itcast.html","wb") as f:
                f.write(response.body)
  3. 执行爬虫

    注意是在终端里

    scrapy crawl <爬虫实体名字>

    eg:

    scrapy crawl itcast
    response常见方法:
    response.text        ‐‐‐》响应的是字符串
    response.body        ‐‐‐》响应的是二进制文件
    response.xpath()     --‐》xpath方法的返回值类型是selector列表
    response.xpath().extract()           ‐‐‐》提取的是selector对象的是data
    response.xpath().extract_first()      ‐‐‐》提取的是selector列表中的第一个数据

3、完整使用scrapy框架进行爬虫过程

  1. 创建项目

    scrapy startproject <项目名称>

    这里反正框架有点奇怪,他创建完是两层文件夹形式,我们要进入第一层文件夹下再创建下一步的爬虫文件:

    cd <项目名称>
  2. 创建爬虫文件

    scrapy genspider <爬虫实体名> <要爬虫的域名>
  3. 先看看能不能爬取,如果不能爬取,我们把君子协议关掉,在 settings注释掉

  4. 现在items.py文件里创建一个对象,并注明其属性

    eg:
    class MyspiderDemonstrateDangdangwangItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        book_src = scrapy.Field()
        book_name = scrapy.Field()
        book_price = scrapy.Field()
  5. 先在爬虫文件里引入items.py

    from myspider_demonstrate_dangdangwang.items import MyspiderDemonstrateDangdangwangItem

    这个可能会报错,但不用管

  6. 根据网页的结构提取想要的信息,并使用response.xpath()方法提取需要的信息

    response.xpath()使用方法:
    一般要爬取的数据都是重复的结构中,记得先循环提取再把里面需要的各个元素(如标题,图片)分别提取
    
    eg:
        def parse(self, response):
            # li_list = response.xpath('//ul[@id="component_59"]/li')
            #
            # for li in li_list:
                # src = li.xpath('.//img/@data-original').extract_first()
                # # 第一张图片和其他的图片的标签的属性是不一样的
                # # 第一张图片的src是可以使用的  其他的图片的地址是data-original
                # if src:
                #     src = src
                # else:
                #     # src = li.xpath('.//img/@src').extract_first()
                #     print("没有图片")
                # print(src)
                # name = li.xpath('.//img/@alt').extract_first()
                # price = li.xpath('.//p[@class="price"]/span[1]/text()').extract_first()
            book_xpath_list = response.xpath('//ul[@id="component_59"]/li')
    ​
            for book in book_xpath_list:
                book_name = book.xpath('./a/@title').get()
                book_price = book.xpath('.//p[@class="price"]/span[1]/text()').extract_first()
                book_src = book.xpath('.//img/@data-original').get()
    ​
                if book_src:
                    book_src = book_src
                else :
                    book_src = book.xpath('.//img/@src').get()
                # print(book_price)
    ​
                bookall = MyspiderDemonstrateDangdangwangItem(book_src = book_src,book_name = book_name,book_price = book_price)
                # item就是yield返回的对象
                yield bookall
  7. 在管道文件中(pipelines.py)设置,进行数据的清洗和文件的写入

    文件打开要在爬虫前,避免重复打开你和关闭文件,爬虫开启前的函数:def open_spider(self,spider):;爬虫结束函数:def close_spider(self,spider):

    def process_item(self, item, spider):函数中进行文件写入

    eg:
    class MyspiderDemonstrateDangdangwangPipeline:
    ​
        # def process_item(self, item, spider):
        #     with open('book.json', 'a', encoding='utf-8') as f:
        #         f.write(str(item)+'\n')
        #     return item
    ​
        def open_spider(self,spider):
            self.fp = open('book.json','w',encoding='utf-8')
    ​
        def process_item(self, item, spider):
            self.fp.write(str(item))
            return item
    ​
        def close_spider(self,spider):
    ​
            self.fp.close()
  8. 开启多管道:

    • 先在settings文件中,创建新管道类并设置优先级,优先级1-1000 值越小优先级越高

    • 再在管道文件里创建新的类(当然名字要对应上),执行你想执行的操作,下面的例子是下载爬取url对应的图片

      class DangDangImgDownload:
          def download_image(self,url, save_path):
              response = requests.get(url)
      ​
              if response.status_code == 200:
                  with open(save_path, 'wb') as file:
                      file.write(response.content)
                  print(f"Image downloaded successfully and saved at: {save_path}")
              else:
                  print(f"Failed to download image. Status code: {response.status_code}")
          def process_item(self,item,spider):
              # 你的图片URL
              # image_url = "https://img3m6.ddimg.cn/72/20/29420496-1_b_3.jpg"
              # # 保存图片的路径和文件名
              # save_path = "C://Users//Carrot//Desktop//img11111.jpg"
              image_url = 'https:' + item['book_src']
              # 保存图片的路径和文件名
              save_path = 'D://pythonprojectlist//project4//myspider_demonstrate_dangdangwang//myspider_demonstrate_dangdangwang//spiders//bookimg//' + item['book_name'] + '.jpg'
      ​
              # 调用下载函数
              self.download_image(image_url, save_path)
  9. 多页爬取

    • 因为每一页要爬取的内容是一样的,所以只需要将每次url地址进行修改便可,一般url多页都会是有一个baseurl,后面跟着一个page的页码

      base_url = 'https://search.dangdang.com/?key=%E9%9D%92%E6%98%A5&act=input&page_index='
       page = 1
    • 然后我们只需要进行循环,对page++便可,并拼接新的url,并使用scrapy.Request(url=url,callback=self.parse)进行请求便可

       if self.page < 100:
                  self.page = self.page + 1
                  url = self.base_url + str(self.page)
                  #scray.Request就是scrapy的get请求
                  #url就是请求地址
                  #callback是你要执行的那个函数  注意不需要加()
                  yield scrapy.Request(url=url,callback=self.parse)


到这里基本关于文字和图片的爬取,无论是简单爬虫和使用scrapy框架的都基本介绍完毕,为了让大家学习和使用更方便,我也把上面这个爬取xx网的例子的代码上传到git里了

仓库地址:Carrot_L/myspider_demonstrate_dangdangwang (gitee.com)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值