Python 爬虫笔记

两个解析 HTML 文档的有力工具:lxml & BeautifulSoup4,一切暴露在互联网中的数据,都不是绝对安全的,但绝对是需要费脑筋才需要得到的,爬虫很简单学,真正难的是反爬。

urllib

  • get 请求

    from urllib import request
    
    # 请求的 URL(百度翻译页面的爬取)
    url = 'https://fanyi.baidu.com/'
    
    # 请求头
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) '
                      'AppleWebKit/537.36 (KHTML, like Gecko) '
                      'Chrome/72.0.3626.121 Safari/537.36',
    }
    
    # 封装 URL 、请求头,并得到新的请求信息 req
    req = request.Request(url=url, headers=headers, )
    
    # 根据拿到的请求信息,进行数据爬取,并接收响应值
    ret = request.urlopen(req)
    
    # 拿到返回值进行读取,解码并打印
    print(ret.read().decode())
    
  • post 请求

    from urllib import request, parse
    
    # 请求的 URL
    url = 'https://fanyi.baidu.com/sug'
    
    # 请求头
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) '
                      'AppleWebKit/537.36 (KHTML, like Gecko) '
                      'Chrome/72.0.3626.121 Safari/537.36',
    }
    
    # POST 请求数据(bytes)
    data = parse.urlencode(
        {
            'kw': '你好'
        }
    ).encode()
    
    # 封装 URL 、请求头,并得到新的请求信息 req
    req = request.Request(url=url, headers=headers, data=data)
    
    # 根据拿到的请求信息,进行数据爬取,并接收响应值
    ret = request.urlopen(req)
    
    # 拿到返回值进行读取,解码并打印
    print(ret.read().decode())
    

requests

requests 模块常用方法

  1. 单次请求(每发送一次请求,就需要调用一次)

    • get()
    • post()
    • request()
  2. 多次请求(可以重复调用任何请求方法)

    • Session()

      多用于 COOKIE 操作,会自动更新 COOKIE,需要实例化一个对象

以上两种所包含的任何方法或者类,除去 get() 和 post() 等,以请求类型命名的方法不需要传递请求类型这个参数,对于其他的则需要。其他参数都可以传递,比如(#号标记是必须参数):

  • #method > String:请求类型(GET, POST…)
  • #url > String:请求地址
  • *params > Dictionary:GET 请求所携带的数据
  • *data > Dictionary:POST 请求所携带的数据
  • *json:
  • *headers > Dictionary:请求头信息
  • *cookies > Dictionary or CookieJar:请求时所携带的 COOKIE,
  • *files:
  • *auth:
  • *timeout > Float or Tuple:请求超时时间
  • *allow_redirects:
  • *proxies > Dictionary:请求代理
  • *verify > Boolean
  • *stream:
  • *cert:
  • get 请求

    import requests
    
    # 请求的 URL
    url = 'https://www.baidu.com/s'
    
    # GET 请求所需数据
    params = {
        'wd': 'ip',
        'ie': 'utf-8',
    }
    
    # 请求头
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) '
                      'AppleWebKit/537.36 (KHTML, like Gecko) '
                      'Chrome/72.0.3626.121 Safari/537.36',
    }
    
    # 开始一个 GET 请求
    res = requests.get(url=url, params=params, headers=headers)
    
    # 对返回的数据进行解码
    res.encoding = res.apparent_encoding
    
    # 输出内容
    print(res.text)
    

    对于 GET 请求的数据传递方式有两种,以上代码中使用的是其中一种,就是将数据封装到一个字典中,第二种就是直接拼装到 URL 中,如以下:

    url = 'https://www.baidu.com/s?ie=utf-8&wd=ip'
    

    即可省去 params

  • post 请求

    import requests
    
    # 请求的 URL
    url = 'https://accounts.douban.com/j/mobile/login/basic'
    
    # POST 请求所需数据
    data = {
        'ck': '',
        'name': '账号',
        'password': '密码',
        'remember': False,
        'ticket': '',
    }
    
    # 请求头
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) '
                      'AppleWebKit/537.36 (KHTML, like Gecko) '
                      'Chrome/72.0.3626.121 Safari/537.36',
    }
    
    # 开始一个 POST 请求(登录豆瓣)
    res = requests.post(url=url, data=data, headers=headers)
    
    # 对返回的数据进行解码
    res.encoding = res.apparent_encoding
    
    # 输出内容
    print(res.text)
    
    # 验证是否登录成功,并携带 POST 请求响应时的 COOKIE
    res = requests.get('https://www.douban.com/mine/', headers=headers, cookies=res.cookies)
    
    # 输出内容
    print(res.text)
    
  • 代理

    import requests
    
    # 请求的 URL
    url = 'http://www.baidu.com/s'
    
    # GET 请求所需数据
    params = {
        'wd': 'ip',
        'ie': 'utf-8',
    }
    
    # 请求头
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) '
                      'AppleWebKit/537.36 (KHTML, like Gecko) '
                      'Chrome/72.0.3626.121 Safari/537.36',
    }
    
    # 代理
    proxies = {
        'http': '119.180.166.14:8060',
    }
    
    # 实例化一个 Session 对象
    with requests.Session() as s:
        # 开始一个 GET 请求
        res = s.request(method='GET', url=url, params=params, headers=headers, proxies=proxies)
        
        # 对返回的数据进行解码
        res.encoding = res.apparent_encoding
        
        # 输出内容
        print(res.text)
    
  • cookies

    import requests
    
    # 请求的 URL
    url = 'https://accounts.douban.com/j/mobile/login/basic'
    
    # POST 请求所需数据
    data = {
        'ck': '',
        'name': 17778022262,
        'password': 'Yan092399.',
        'remember': False,
        'ticket': '',
    }
    
    # 请求头
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) '
                      'AppleWebKit/537.36 (KHTML, like Gecko) '
                      'Chrome/72.0.3626.121 Safari/537.36',
    }
    
    # 实例化一个 Session 对象
    with requests.Session() as s:
        # 开始一个 POST 请求(登录豆瓣)
        res = s.request(method='POST', url=url, data=data, headers=headers)
    
        # 对返回的数据进行解码
        res.encoding = res.apparent_encoding
    
        # 输出内容
        print(res.text)
    
        # 验证是否登录成功,并携带 POST 请求响应时的 COOKIE
        res = requests.get('https://www.douban.com/mine/', headers=headers, cookies=s.cookies)
    
        # 输出内容
        print(res.text)
    

scrapy

  • 安装

    python -m pip install scrapy
    
  • 创建

    # 创建一个项目
    scrapy startproject Scrapy_Demo1
    #创建一个爬虫
    cd Scrapy_Demo1
    scrapy genspider douban www.douban.com
    

    Scrapy_Demo1 项目目录

    spiders: 存放爬虫文件
    scrapy.cfg: 项目的配置信息,主要为Scrapy命令行工具提供一个基础的配置信息
    items.py: 数据存储模板,用于结构化数据
    middlewares.py: 中间件,爬虫中间件,下载中间件,调度中间件
    pipelines.py: 数据处理行为,如:一般结构化的数据持久化
    settings.py: 配置文件

  • 组件

    • 引擎(Scrapy)
      用来处理整个系统的数据流, 触发事务(框架核心)
    • 调度器(Scheduler)
      用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
    • 下载器(Downloader)
      用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
    • 爬虫(Spiders)
      爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
    • 项目管道(Pipeline)
      负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据
    • 下载器中间件(Downloader Middlewares)
      位于Scrapy引擎和下载器之间的框架,主要是处理Scrapy引擎与下载器之间的请求及响应
    • 爬虫中间件(Spider Middlewares)
      介于Scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出
    • 调度中间件(Scheduler Middewares)
      介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应
  • 机制

    scrapy 框架

    1. 引擎从调度器中取出一个链接(URL)用于接下来的抓取
    2. 引擎把URL封装成一个请求(Request)传给下载器
    3. 下载器把资源下载下来,并封装成应答包(Response)
    4. 爬虫解析Response
    5. 解析出实体(Item),则交给实体管道进行进一步的处理
    6. 解析出的是链接(URL),则把URL交给调度器等待抓取
  • 简单爬取

    定位到项目中的 settings.py 文件,修改以下值

    # 修改请求头
    USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:67.0) Gecko/20100101 Firefox/67.0'
    
    # 关闭爬虫规则
    ROBOTSTXT_OBEY = False
    

    编辑爬虫文件(spiders/douban.py

    # -*- coding: utf-8 -*-
    class DoubanSpider(scrapy.Spider):
        # 爬虫名称
        name = 'douban'
    
        # 爬虫范围
        allowed_domains = ['www.douban.com']
    
        # URL 列表
        start_urls = ['http://www.douban.com/']
    
        def parse(self, response):
        	# 该方法主要用来解析页面内容
            # 输出页面内容
            print(response.text)
    

    启动爬虫

    # 带日志输出
    scrapy crawl douban
    
    # 不带日志输出
    scrapy crawl douban --nolog
    

    页面内容的解析

    # -*- coding: utf-8 -*-
    import scrapy
    
    from lxml import etree
    from bs4 import BeautifulSoup
    
    
    class DoubanSpider(scrapy.Spider):
        # 爬虫名称
        name = 'douban'
    
        # 爬虫范围
        allowed_domains = ['www.douban.com']
    
        # URL 列表
        start_urls = ['http://www.douban.com/']
    
        def parse(self, response):
            # 1 scrapy 的 xpath 解析,获取热点图片链接
            print(
                response.xpath('//div[@id="anony-sns"]//div[@class="albums"]//a/@href').extract()
            )
            # or
            print(
                response.xpath('//div[@id="anony-sns"]//div[@class="albums"]//a/@href').getall()
            )
    
            # 2 lxml 的 xpath 解析,获取热点文章链接
            page_etree = etree.HTML(response.text)
            print(
                page_etree.xpath('//div[@id="anony-sns"]//div[@class="notes"]//a/@href')
            )
    
            # 3 BeautifulSoup4 解析,获取热点话题链接
            soup = BeautifulSoup(response.text)
            parents_div = soup.find('div', attrs={'id': 'anony-sns'})
            link_list = parents_div.find_all('a', attrs={'class': 'rec_topics_name'})
            print(
                list(map(lambda link: link.attrs['href'], link_list))
            )
    
  • 数据存储

    改日

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值