Python网络爬虫笔记(五)——请求库(urllib3),解析库(re) - Go语言中文社区

Python网络爬虫笔记(五)——请求库(urllib3),解析库(re)


本篇博客主要讲解urllib3和re的简单应用,同时简单介绍正则表达式的使用,做一个抓取猫眼电影信息的小程序。

准备

首先我们先相关库导入

import urllib3
import re
import json
import time
import csv

打开网页:https://maoyan.com/board/4
在这里插入图片描述

一、请求库(urllib3)

1、导入库:import urllib3
2、定义请求对象:http = urlli3.PoolManager()
3、进行get请求: resp = http.request('GET',url,headers=ua)
4、查看状态码:resp.status
5、查看网页源代码:resp.data #以二进制形式显示汉字
6、编码转换:resp.data.decode('utf-8')

首先我们要有一个程序入口,也就是mian main:

import urllib3
import re
import json
import time


# 请求网页
def page_def(url, ua):
    http = urllib3.PoolManager()
    resp = http.request('GET', url, headers=ua)
    return resp.data

#程序主入口
if __name__ == '__main__':
    ua = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'}
    url = 'https://maoyan.com/board/4'
    html_info = page_def(url, ua)

这里的ua是客户端信息 (User-Agent),不加容易抓取失败。
你可以选用自己的ua,也可以百度从上面拿几个。
url就是你要抓取的网页地址。
page_def 函数用来请求网页,讲请求结果放在html_info中。

二、解析网页(正则表达式的使用)

正则表达式使用步骤
1)寻找规律
2)用正则符号表示规律
3)提取信息
1> 点号’.
作用:可以代替除换行符以外的任何一个字符
2> 星号 ‘*
作用:一个星号可以表示它前面的一个子表达式0次或无数次。
3> 问号’?
作用:一个问号可以表示前面的子表达式0次或1次
4> .* 贪婪模式的匹配
特点:尽可能多的匹配字符
.*? 非贪婪模式的匹配
特点:尽可能少的匹配字符
5>re.findall(正则,字符串,参数)
参数:re.S (忽略换行符)
6)括号
作用:正则表达式中,用括号括住的就是我们要取的

我们分析一下网页源码:
在这里插入图片描述
先看第一个序号,找到它的特征:
它是在< dd >标签中的。而这个标签是电影信息所特有的。
在分析<i class="board-index board-index-1">1</i>
我们取特征:board-index
< dd>board-index之间隔了一些字符,用.*?非贪婪模式匹配.
我们可以看到序号左右两边都有尖括号,*?>(.*?)< 获取序号信息
结合起来就是:pat = r'<dd>.*?board-index.*?>(.*?)<'
这个就是获取序号的正则。
依此类推:

    pat = r'<dd>.*?board-index.*?>(.*?)<' 
           + r'.*?data-src="(.*?)"' 
           + r'.*?name.*?a.*?>(.*?)<' 
           + r'.*?star.*?:(.*?)<' 
           + r'.*?releasetime.*?:(.*?)<' 
           + r'.*?integer.*?>(.*?)<' 
           + r'.*?fraction.*?>(.*?)<'

分别获取序号、图片地址、电影名、主演、上映时间、评分。
(最后一个评分分为两部分,整数部位和小数部位)
然后就可以写解析网页的函数:

# 解析网页元素
def info_def(html_info):
    html = html_info.decode('utf-8')
    pat = r'<dd>.*?board-index.*?>(.*?)<' 
           + r'.*?data-src="(.*?)"' 
           + r'.*?name.*?a.*?>(.*?)<' 
           + r'.*?star.*?:(.*?)<' 
           + r'.*?releasetime.*?:(.*?)<' 
           + r'.*?integer.*?>(.*?)<' 
           + r'.*?fraction.*?>(.*?)<'
    m_index = re.findall(pat, html, re.S)
    return m_index

将解析结果存入m_index

三、写入本地

1、将数据存入字典,方便操作

def dic_def(m_index):
    l1 = []
    for info_one in m_index:
        info_dirc = {'序号': info_one[0],
                     '图片网址': info_one[1],
                     '电影名': info_one[2],
                     '主演': info_one[3],
                     '放映时间': info_one[4],
                     '评分': info_one[5] + info_one[6]
                     }
        l1.append(info_dirc)
    return l1

2、分别保存为txt、csv、png格式

# 保存文本
def write_def(l1):
    with open(r'D:testmovie_info.txt', 'a', encoding='utf-8') as af:
        for i in l1:
            af.write(json.dumps(i, ensure_ascii=False) + 'n')


# 保存图片
def img_def(m_index):
    for i in m_index:
        img_resp = http.request('GET', i[1])
        with open(r'D:testpng%s.jpg' % (i[2]), 'bw') as imgf:
            imgf.write(img_resp.data)
            
#保存表格
def csv_def(l1):
    with open(r'D:testmovie_info.csv', 'w', encoding='gbk', newline='') as cf:
        writer = csv.DictWriter(cf,fieldnames = ['序号','图片网址','电影名','主演','放映时间','评分'])
        writer.writeheader()
        writer.writerows(l1)


四、完整程序代码

import urllib3
import re
import json
import time
import csv


# 请求网页
def page_def(url, ua):
    http = urllib3.PoolManager()
    resp = http.request('GET', url, headers=ua)
    return resp.data


# 解析网页元素
def info_def(html_info):
    html = html_info.decode('utf-8')
    pat = r'<dd>.*?board-index.*?>(.*?)<' 
          + r'.*?data-src="(.*?)"' 
          + r'.*?name.*?a.*?>(.*?)<' 
          + r'.*?star.*?:(.*?)<' 
          + r'.*?releasetime.*?:(.*?)<' 
          + r'.*?integer.*?>(.*?)<' 
          + r'.*?fraction.*?>(.*?)<'
    m_index = re.findall(pat, html, re.S)
    return m_index


# 把数据写入字典
def dic_def(m_index):
    l1 = []
    for info_one in m_index:
        info_dirc = {'序号': info_one[0],
                     '图片网址': info_one[1],
                     '电影名': info_one[2],
                     '主演': info_one[3],
                     '放映时间': info_one[4],
                     '评分': info_one[5] + info_one[6]
                     }
        l1.append(info_dirc)
    return l1


# 写到本地
def write_def(l1):
    with open(r'D:testmovie_info.txt', 'a', encoding='utf-8') as af:
        for i in l1:
            af.write(json.dumps(i, ensure_ascii=False) + 'n')


# 保存图片
def img_def(m_index):
    http = urllib3.PoolManager()
    for i in m_index:
        img_resp = http.request('GET', i[1])
        with open(r'D:testpng%s.jpg' % (i[2]), 'bw') as imgf:
            imgf.write(img_resp.data)


# 保存表格
def csv_def(l1, i):
    with open(r'D:testmovie_info.csv', 'a', encoding='gbk', newline='') as cf:
        writer = csv.DictWriter(cf, fieldnames=['序号', '图片网址', '电影名', '主演', '放映时间', '评分'])
        if i == 0:
            writer.writeheader()  # 避免重复写头
        writer.writerows(l1)


# 进度条
def progress(n, a):
    m = int(n / a * 100)
    x = int(n / a * 10)
    print("r[%s%s] %s%%" % ("█" * x, " " * (10 - x), m), end="")


if __name__ == '__main__':
    progress(0, a=10)
    ua = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'}

    for j in range(0, 10, 1):
        url = 'https://maoyan.com/board/4?offset=%d' % (10 * j)
        html_info = page_def(url, ua)
        m_index = info_def(html_info)
        l1 = dic_def(m_index)
        write_def(l1)
        img_def(m_index)
        csv_def(l1, j)
        time.sleep(2)  # 让他睡一会,不要频繁抓取,不然容易被反
        progress(j + 1, a=10)

结果展示:
在这里插入图片描述

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/xuanhuangwendao/article/details/104130472
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢