zoukankan      html  css  js  c++  java
  • 爬虫请求模块

    模块名及导入

    1、模块名:urllib.request
    2、导入方式:
       1、import urllib.request
       2、from urllib import request

    常用方法详解

    (一)urllib.request.urlopen()方法

    1.作用

      向网站发起请求并获取响应对象

    2.参数

    1、URL:需要爬取的URL地址
    2、timeout: 设置等待超时时间,指定时间内未得到响应抛出超时异常

    3.第一个爬虫程序

      打开浏览器,输入百度地址(http://www.baidu.com/),得到百度的响应

    # 导入请求模块(python标准库模块)
    import urllib.request
    
    url = 'http://www.baidu.com/'
    
    # 向百度发请求,得到响应对象
    response = urllib.request.urlopen(url)
    # 获取响应对象内容(网页源代码)
    # read() 是bytes类型 需要decode()转换成string 
    # 读取百度页面HTML内容
    print(response.read().decode('utf-8'))

    4.相应对象(response)方法

      提取相应对象
    1、bytes = response.read() #read()结果为bytes类型 2、string = response.read().decode('utf-8') #read().decode()结果为string类型 3、url = response.geturl() #返回实际数据的url地址(重定向问题) 4、code = response.getcode() #返回http响应码 # 补充 5、string.encode() #转字节串bytes类型 6、bytes.decode() #转字符串string类型

    思考:网站如何来判定是人类正常访问还是爬虫程序访问???

    # 向测试网站: http://httpbin.org/get 发请求,通过获取响应内容查看自己请求头
    import urllib.request
    
    url = 'http://httpbin.org/get'
    response = urllib.request.urlopen(url)
    print(response.read().decode('utf-8'))
    
    # 结果中请求头中的User-Agent竟然是: "Python-urllib/3.7"!!!!!!!!!
    # 我们需要重构User-Agent

    (二)urllib.request.Request()

    1.作用

      创建请求对象(包装请求,重构User-Agent,使程序更像正常人类请求)

    2.参数

    1、URL:请求的URL地址
    2、headers:添加请求头(爬虫和反爬虫斗争的第一步)

    3.使用流程

    #1、构造请求对象(重构User-Agent)
      req = urllib.request.Reuqest(
        url='http://httpbin.org/get',
        headers={'User-Agent':'Mozilla/5.0'}
      )
    #2、发请求获取响应对象(urlopen)
      res = urllib.request.urlopen(req)
    #3、获取响应对象内容
      html = res.read().decode('utf-8')

    4.示例

    向测试网站(http://httpbin.org/get)发起请求,构造请求头并从响应中确认请求头信息

    from urllib import request
    
    # 定义常用变量
    url = 'http://httpbin.org/get'
    headers = {'User-Agent':'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3)'}
    
    # 1.构建请求对象
    req = request.Request(url,headers=headers)
    # 2.发请求获取响应对象
    res = request.urlopen(req)
    # 3.读取响应对象内容
    html = res.read().decode('utf-8')
    print(html)

    URL地址编码模块

    (一)模块名及导入

    # 模块名
    urllib.parse
    # 导入
    import urllib.parse
    from urllib import parse

    (二)作用

      给URL地址中查询参数进行编码

    编码前:https://www.baidu.com/s?wd=美女
    编码后:https://www.baidu.com/s?wd=%E7%BE%8E%E5%A5%B3

    (三)常用方法

    1.urllib.parse.urlencode({dict})

    (1)URL地址中 ==一个== 查询参数

    # 查询参数:{'wd' : '美女'}
    # urlencode编码后:'wd=%e7%be%8e%e5%a5%b3'
    
    # 示例代码
    query_string = {'wd' : '美女'}
    result = parse.urlencode(query_string)
    # result: 'wd=%e7%be%8e%e5%a5%b3'

    (2)URL地址中 ==多个== 查询参数

    from urllib import parse
    query_string_dict = {
        'wd' : '美女',
        'pn' : '50'
    }
    query_string = parse.urlencode(query_string_dict)
    url = 'http://www.baidu.com/s?{}'.format(query_string)
    print(url)

    拼接URL地址的3种方式

    #1、字符串相加
        baseur1 = 'http://www.baidu.com/s?'
        params = 'wd=%E7xxxx&pn=20'
        url = baseur1+params
    #2、字符串格式化(占位符)
        params ='wd=%E7xxxx&pn=20'
        url = 'http://www.baidu.com/s?%s'%params
    #3、format()方法
        url = 'http://www.baidu.com/s?{}'
        params ='wd=%E7xxxx&pn=20'
        url = url.format(params)

    练习: 在百度中输入要搜索的内容,把响应内容保存到本地文件

    from urllib import request
    from urllib import parse
    
    
    def get_url(word):
        baseurl = 'http://www.baidu.com/s?'
        params = parse.urlencode({'wd':word})
        url = baseurl + params
    
        return url
    
    def request_url(url,filename):
        headers = {'User-Agent': 'Mozilla/5.0'}
        req = request.Request(url, headers=headers)
        res = request.urlopen(req)
        html = res.read().decode('utf-8')
        # 保存到本地文件
        with open(filename, 'w') as f:
            f.write(html)
    
    if __name__ == '__main__':
        word = input('请输入搜索内容:')
        url = get_url(word)
        filename = '{}.html'.format(word)
        request_url(url,filename)

    2.quote(string)编码

    from urllib import parse
    
    string = '美女'
    print(parse.quote(string))
    # 结果: %E7%BE%8E%E5%A5%B3

    改写之前urlencode()代码,使用quote()方法实现

    from urllib import parse
    
    url = 'http://www.baidu.com/s?wd={}'
    word = input('请输入要搜索的内容:')
    query_string = parse.quote(word)
    print(url.format(query_string))

    3.unquote(string)解码

    from urllib import parse
    
    string = '%E7%BE%8E%E5%A5%B3'
    result = parse.unquote(string)
    print(result)

    总结:

    #1.urllib.request
        1,req=urllib.request.Request(url,headers)    # 请求对象
        2.res= urllib.request.urlopen(req)    # 二字节的形式打开文件
        3.html=res.read().decode('utf-8')    # 读取文件 并转换为字符串
    #2.res方法
        res.read() # 读取网络
        res.getcode() # 返回响应码
        res.geturl() # 重定向
    #3.urllib.parse
      #编码
      urllib.parse.urlencode({})   urllib.parse.quote(srting)
      #解码   urllib.parse.unquote()

    抓取步骤

    1、确定所抓取数据在响应中是否存在(右键 - 查看网页源码 - 搜索关键字)
    2、数据存在: 查看URL地址规律
    3、写正则表达式,来匹配数据
    4、程序结构
        1、使用随机User-Agent
        2、每爬取1个页面后随机休眠一段时间
    # 程序结构
    class xxxSpider(object):
        def __init__(self):
            # 定义常用变量,url,headers及计数等
            
        def get_html(self):
            # 获取响应内容函数,使用随机User-Agent
        
        def parse_html(self):
            # 使用正则表达式来解析页面,提取数据
        
        def write_html(self):
            # 将提取的数据按要求保存,csv、MySQL数据库等
            
        def main(self):
            # 主函数,用来控制整体逻辑
            
    if __name__ == '__main__':
        # 程序开始运行时间戳
        start = time.time()
        spider = xxxSpider()
        spider.main()
        # 程序运行结束时间戳
        end = time.time()
        print('执行时间:%.2f' % (end-start))
    程序结构

    案例:百度贴吧数据抓取

    要求:

    1、输入贴吧名称
    2、输入起始页
    3、输入终止页
    4、保存到本地文件:
      例如:赵丽颖吧-第1页.html、赵丽颖吧-第2页.html ...

    实现步骤:

    (1)查看是否为静态页面

      通过右键-查看网页源代码-搜索数据关键字

    (2)找url规律

      第一页:http://tieba.baidu.com/f?kw=??&pn=0

      第二页:http://tieba.baidu.com/f?kw=??&pn=0

      第n页:  http://tieba.baidu.com/f?kw=??&pn=(n-1)*50

    (3)获取网页内容

    (4)保存(本地文件,数据库)

    (5)实现代码

    from urllib import request
    from urllib import parse
    import time
    import random
    from useragents import ua_list
    
    
    class BaiduSpider(object):
      def __init__(self):
        self.url = 'http://tieba.baidu.com/f?kw={}&pn={}'
    
      # 获取相应内容
      def get_html(self, url):
        headers = {
          'User-Agent': random.choice(ua_list)
        }
        req = request.Request(url=url, headers=headers)
        res = request.urlopen(req)
        html = res.read().decode('utf-8')
        print(headers)
        return html
    
      # 解析相应内容(提取所需数据)
      def parse_html(self):
        pass
    
      # 保存
      def write_html(self, filename, html):
        with open(filename, 'w', encoding='utf-8') as f:
          f.write(html)
    
      # 主函数
      def main(self):
        # 拼接每一页的地址
        # 接收用户的输入(例如贴吧名,第几页)
        name = input('请输入贴吧名:')
        begin = int(input('请输入起始页'))
        end = int(input('请输入终止页'))
        # url 缺两个数据: 贴名吧  pn
        params = parse.quote(name)
        for page in range(begin, end + 1):
          pn = (page - 1) * 50
          url = self.url.format(params, pn)
          filename = '{}-第{}页.html'.format(name, page)
    
          # 调用类内函数
          html = self.get_html(url)
          self.write_html(filename, html)
          # 每爬取1个页面随机休眠1-3秒钟
          time.sleep(random.randint(1, 3))
          print('第%d页爬取完成' % page)
    
    
    if __name__ == '__main__':
      start = time.time()
      spider = BaiduSpider()
      spider.main()
      end = time.time()
      print('执行时间:%.2f' % (end-start))
    实现代码
    ua_list = [
      'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1',
      'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0',
      'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
      'Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.9.168 Version/11.50',
    
    ]
    useragents.py配置文件

    正则解析模块re

    (一)re模块使用流程

    方法一:

      r_list=re.findall('正则表达式',html,re.S)

    方法二:

      创建正则编译对象
      pattern = re.compile(r'正则表达式',re.S)
      r_list = pattern.findall(html)

    (二)正则表达式元字符

    元字符含义
    . 任意一个字符(不包括 )
    d 一个数字
    s 空白字符
    S 非空白字符
    [] 包含[]内容
    * 出现0次或多次
    + 出现1次或多次

    思考:请写出匹配任意一个字符的正则表达式?

    import re
    # 方法一
    pattern = re.compile('.',re.s)
    # 方法二
    pattern = re.compile('[sS]')

    (三)贪婪匹配和非贪婪匹配

    贪婪匹配(默认)

    1、在整个表达式匹配成功的前提下,尽可能多的匹配 *
    2、表示方式:.*  .+  .?

    非贪婪匹配

    1、在整个表达式匹配成功的前提下,尽可能少的匹配 *
    2、表示方式:.*?  .+?  .??

    示例:

    import re
    
    html = '''
    <html>
        <div><p>九霄龙吟惊天变</p></div>
        <div><p>风云际会浅水游</p></div>
    </html>
    '''
    # 贪婪匹配
    pattern = re.compile('<div><p>.*</p></div>',re.S)
    r_list = pattern.findall(html)
      #['<div><p>九霄龙吟惊天变</p></div>
        <div><p>风云际会浅水游</p>']
    # 非贪婪匹配 pattern = re.compile('<div><p>.*?</p></div>',re.S) r_list = pattern.findall(html) print(r_list)
      #['<div><p>九霄龙吟惊天变</p>', '<div><p>风云际会浅水游</p>']
    pattern = re.compile('<div><p>(.*?)</p></div>',re.S)
    r_list = pattern.findall(html)
    print(r_list)
      #['九霄龙吟惊天变', '风云际会浅水游']

    (四)正则表达式分组

    作用: 在完整的模式中定义子模式,将每个圆括号中子模式匹配出来的结果提取出来

    示例:

    import re
    
    s = 'A B C D'
    p1 = re.compile('w+s+w+')
    print(p1.findall(s))
    # 分析结果是什么???['A B','C D']
    
    p2 = re.compile('(w+)s+w+')
    print(p2.findall(s))
    # 分析结果是什么???
    #第一步:把()去掉,先匹配完整 ['A B','C D']
    #第二步:提取分组()中内容 ['A','C']
    p3 = re.compile('(w+)s+(w+)') print(p3.findall(s)) # 分析结果是什么???
    # 第一步:把()去掉,先匹配完整 ['A B','C D']
    # 第二部:提取分组()中内容 [('A','B'),('C','D')]

    分组总结:

    1、在网页中,想要什么内容,就加()

    2、先按整体正则匹配,然后再提取分组()中的内容

      如果有2个及以上分组(),则结果中以元组形式显示 [(),(),()]

    练习1:页面结构如下

    <div class="animal">
        <p class="name">
            <a title="Tiger"></a>
        </p>
        <p class="content">
            Two tigers two tigers run fast
        </p>
    </div>
    
    <div class="animal">
        <p class="name">
            <a title="Rabbit"></a>
        </p>
    
        <p class="content">
            Small white rabbit white and white
        </p>
    </div>

    从以上html代码结构中完成如下内容信息的提取:

    问题1 :[('Tiger',' Two...'),('Rabbit','Small..')]
    问题2 :
        动物名称 :Tiger
        动物描述 :Two tigers two tigers run fast
        **********************************************
        动物名称 :Rabbit
        动物描述 :Small white rabbit white and white
    # r = r'title="(.*?)".*?class="content">s+(.*?)s+</p>'
    r = r'<div class="animal">.*?<a title="(.*?)".*?<p class="content">s+(.*?)s+</p>'
    
    pattern = re.compile(r, re.S)
    r_list = pattern.findall(html)
    print(r_list)
    #遍历方法1
    for i, j in r_list:
      print('动物名称:',i,'动物描述:',j)
      print("*"*20)
    #遍历方法2
    for r in r_list:
      print('动物名称:',r[0].strip())
      print('动物描述:',r[1].strip())
      print("*" * 20)

    练习2:爬取猫眼电影信息 :猫眼电影-榜单-top100榜

    第1步完成:
        猫眼电影-第1页.html
        猫眼电影-第2页.html
        ... ... 
    
    第2步完成:
        1、提取数据 :电影名称、主演、上映时间
        2、先打印输出,然后再写入到本地文件
    from urllib import request, parse
    import re
    import time
    import random
    from useragents import ua_list
    
    
    class MaoyanSpider(object):
      def __init__(self):
        self.url = 'https://maoyan.com/board/4?offset={}'
        #计数
        self.num=0
    
      def get_html(self, url):
        headers = {
          'User-Agent': random.choice(ua_list)
        }
        req = request.Request(url=url, headers=headers)
        res = request.urlopen(req)
        html = res.read().decode('utf-8')
        #直接调用解析函数
        self.parse_html(html)
    
      def parse_html(self,html):
        #创建正则的编译对象
        re_='<div class="movie-item-info">.*?title="(.*?)".*?<p class="star">(.*?)</p>.*?<p class="releasetime">(.*?)</p> '
        pattern = re.compile(re_,re.S)
        #film_list:[('霸王别姬','张国荣','1993')]
        film_list = pattern.findall(html)
        self.write_html(film_list)
    
      def write_html(self,film_list):
        film_dict={}
        for film in film_list:
          film_dict['name']=film[0].strip()
          film_dict['star']=film[1].strip()
          film_dict['time']=film[2].strip()[5:15]
          print(film_dict)
          self.num += 1
      def main(self):
        for offset in range(0, 91, 10):
          url = self.url.format(offset)
    
          self.get_html(url)
          time.sleep(random.randint(1,2))
        print('共抓取数据',self.num,"")
    
    
    if __name__ == '__main__':
      start = time.time()
      spider = MaoyanSpider()
      spider.main()
      end = time.time()
      print('执行时间:%.2f' % (end - start))
    爬取猫眼电影信息
    ua_list = [
      'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)',
      'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0',
      'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.41 Safari/535.1 QQBrowser/6.9.11079.201',
      'Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.9.168 Version/11.50',
    
    ]
    useragents.py配置文件
  • 相关阅读:
    欧拉项目第十题;用筛法做,
    欧拉第十题 求2000000以内的素数之和
    求1000数字中13个相乘最大值
    筛法求10000以内的质数
    判断回文且寻找三位数乘三位数里最大的回文
    分解质因数
    输入一个正整数n,将其转换为二进制后输出。要求定义并调用函数dectobin(n),它的功能是输出
    hdu1863最小生成树krus模板&prim模板
    hdu 3870 最小割转化为最短路径2
    UVALive 3661 最小割转化为最短路径
  • 原文地址:https://www.cnblogs.com/maplethefox/p/11319952.html
Copyright © 2011-2022 走看看