001.01 一般网页爬虫处理范例

001.01 一般网页爬虫处理范例

#

建檔日期: 2019/07/28
更新日期: 2019/03/28 錯誤更正

Win 10 Python 3.7.4

在这里将不使用 BeatifulSoup 来作网页爬虫,并尽可能不使用其他的库来完成件事,使用别人的库来写程序,好处是简单,快捷,程序码短,而且还不一定要懂内部的细节;但是就因为不懂细节,就很容出错,而且不会真正了解真正的作法等等缺点.

网页爬虫预备动作#

  1. 打开网页,比如 https://www.51job.com/, 选上方的职位搜索

001.01 一般网页爬虫处理

  1. 会出现超过十万条的工作信息,我们并不需要这么多资料来供自己处理,因此多加一点条件先行筛选,按下面点选,可以得到较少的数据,比如撰文时的资料有 491 条职位,共分 10 页.

001.01 一般网页爬虫处理

  1. 检查一下,这十页的网址差异,并建立一份十个网址的 utf-8 格式文本文件 url.txt, 每条网址都有一些参数不同,要自己确认. (如下图)

001.01 一般网页爬虫处理

  1. 鼠标指向表格中一开始的字段,右键单击选看” 检查元素”, 检查 HTML 内容

001.01 一般网页爬虫处理

  1. 表格的起始位置及结束位置,并找出表格数据所在的特别的标签或其他可以确认的字符串.

001.01 一般网页爬虫处理

  1. 找出表格数据所在的特别的标签或其他可以确认的字符串.

001.01 一般网页爬虫处理

  1. 在此,我们以’<=”el title”>’为表格标题的起点,再找到 > …. < 中的数据,这就是表格的五项标题。后面每一行的数据,则以两个 a title, 三个 span class 为起点,再找到 > …. < 中的数据,这就是表格的一行中的五项数据.
  2. 注意:不同的系统,浏览器所收到的 HTML 檔会有些差异,比如我的前两笔数据就不是以 a title 为起点,而是以 a target 为起点 其他部份则相同.
  3. 因此找出这网页的数据步骤为
    • 取出 ‘‘ 到 ‘ ‘ 的 HTML
    • 找到 ‘<=”el title”>’, 取出’>’和’<’之间表格的五项标题
    • 读取每一笔数据
      • 找到 ‘a target’, 取出’>’和’<’之间表格的数据,重复两次
      • 找到 ‘span class’, 取出’>’和’<’之间表格的数据,重复三次
    • 重复以上的动作,读取以下每一笔数据
    • 找不到起点的字符串,表示该网页数据已读取完毕,再换下一个网页,直到结束.

程序范例#

import urllib.request
import datetime

# 取现在的时间当作档名
date = datetime.datetime.now()
url_list_file = "url.txt"
data_file_name = "Web Data " + str(date.year) + ("%02d" % date.month) + \
                ("%02d" % date.day) +  ("%02d" % date.hour)  + \
                ("%02d" % date.minute) +  ("%02d" % date.second)  +".csv"

# 读取网页及存盘用的编码`
decoder = "GB18030"

# 网页中表格的起点及终点
table_format = ['<!--列表表格-->','<!--列表表格 END-->']
area_start = table_format[0]
area_stop  = table_format[1]

# 寻找字符串, 并跳过
def find_skip(in_string, string1):
    global pointer, string_found
    pointer = in_string.find(string1, pointer)
    # 确认表格结束
    if pointer < 0:
        string_found = False
    pointer += len(string1)

# 按起始字符串, 读取两个标记中的数据, 标记通常是'>'及'<', 并重复n次
def get_n_data(in_string, string1, string2, string3, n, data_follow):
    global pointer, string_found, table

    # 重复n次
    for i in range(n):

        # 跳过起始字符串
        find_skip(in_string, string1)

        # 表格结束 ?
        if string_found:

            # 找到第一个标记
            find_skip(in_string, string2)
            data_start = pointer

            # 找到第二个标记
            find_skip(in_string, string3)
            data_stop  = pointer - len(string3)

            # 资料放到列表中
            data = in_string[data_start : data_stop]
            table.append(data.strip())

# 将列表的数据, 按CSV文本文件格式, 写入CSV檔中
def save_table(data_file_name, table):

    # 表格是的空的, 不存档
    if len(table) != 0:

        table_data =""
        count = 0

        # 表格所有项目转成字符串
        for item in table:
            count += 1

            # 每一行五个数据, 以','间隔, '\n'为结尾
            if count != 5:
                table_data = table_data+item+','
            else:
                table_data = table_data+item+'\n'
                count = 0

        # 建立档案, 写入数据字符串, 档案开闭
        datafile = open(data_file_name, 'wt', encoding=decoder)
        datafile.write(table_data)
        datafile.close()

table =[]

# 读入网址档案中的每一个网址
with open(url_list_file, mode='rt', encoding='utf-8-sig') as url_list:

    for url in url_list:

        # 解碼读入网页HTML
        try:
            web_page = urllib.request.urlopen(url.strip())
        except urllib.error.URLError:
            print('Web page loading failed !!!')
            exit()
        html = web_page.read().decode(decoder)

        # 网页只保留表格部份处理
        pointer = 0
        data_area_start = html.find(area_start)
        data_area_stop  = html.find(area_stop)
        data_html       = html[data_area_start : data_area_stop]
        del html

        pointer = 0

        '''
        省略全部表格每一栏的标题, 避免多个页标题和数据混在一起
        find_skip(data_html, '<div class="el title">')
        get_n_data(data_html, 'span class', '>', '<',  4, ',')
        get_n_data(data_html, 'span class', '>', '<', 1, 'n')
        '''

        # 找不到间隔字符串, 表示表格结束
        string_found = True

        # 重复取得每一笔的表格数据, 找到起始字中, 再取 >......< 中的资料
        while string_found:

            # 两次的'a target', '< ......>'的资料
            get_n_data(data_html, 'a target', '>', '<', 2, ',')

            # 表格结束 ?
            if string_found:

                # 三次的'span class', '< ......>'的资料
                get_n_data(data_html, 'span class', '>', '<', 3, '\n')

# 存表格
save_table(data_file_name, table)

# 结束
exit()

注意:由于本地变量及全局变量的混淆,容易出错,所以我对常用的变量,使用了 Global 定义。确认了一下,程序读入十个网页,取得 491 笔资料,约 34K 档案大小,结果使用了整整 30 秒.

把得到的数据,转存为以”,” 来分隔每一笔资料的.csv 格式檔,用 Excel 外部输入的方式,插到 Excel 中,就可以得到以下近五百笔的数据,至于你要再作什么处理,就看你自己了,比如用 EXCEL 找出职位名有’经理’的部份.

—- The End —

本作品采用《CC 协议》,转载必须注明作者和本文链接
Jason Yang