python中使用BeautifulSoup模块+CSS选择器获取中彩网福彩3D的开奖数据

        在上篇博客中,我们使用了BeautifulSoup模块获取中彩网福彩3D的开奖数据,在编写爬虫程序的过程中发现,如果只使用BeautifulSoup模块中的find_all函数来匹配标签解析网页时,工作量较大而且容易出错,这和find_all函数本身的工作原理以及输入输出有关。通过查找,我们发现将BeautifulSoup模块和CSS选择器结合起来使用会提高网络爬虫的编写和运行效率,所以,同样以爬取中彩网中福彩3D的开奖数据为例,讲解BeautifulSoup模块如何与CSS选择器结合使用。首先,将介绍CSS选择器的工作原理和使用方法。

CSS选择器的工作原理和使用方法
        CSS选择器的工作原理是:我们在编写CSS时要遵守一些固定的规范,如标签名不加任何修饰符,类名前面加“.”,id名前面加“#”。我们同样可以利用类似的方法筛选元素,用到的方法是soup.select(),返回值的数据类型为列表。
        CSS选择器的使用方法如下:

from bs4 import BeautifulSoup

# html内容
html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
# 创建BeautifulSoup对象用于解析网页
soup = BeautifulSoup(html, 'lxml')

1)通过标签名查找

print(soup.select('title'))
# [<title>The Dormouse's story</title>]
print(soup.select('a'))
"""
[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>,
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
"""
print(soup.select('b'))
# [<b>The Dormouse's story</b>]

2)通过类名查找重点内容

print(soup.select('.sister'))
"""
[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>,
 <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, 
 <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
"""

3)通过id名查找

print(soup.select('#link1'))
# [<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

4)组合查找
        组合查找即为将标签与标签、标签与类名、标签与id名等组合起来进行查找,例如查找p标签中id为link1的元素或查找head标签的子标签title。

print(soup.select('p #link1'))      # 二者之间用空格隔开
# [<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]
print(soup.select('head > title'))      # 二者之间用>隔开,>表示从父标签到子标签
# [<title>The Dormouse's story</title>]

5)属性查找
        进行属性查找时,属性需要用中括号括起来,当属性和标签属于同一个节点时,中间不能加空格,否则无法匹配到;不在同一节点的标签与属性之间用空格隔开。

print(soup.select('a[class="sister"]'))     # 二者之间不用空格隔开
"""
[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>,
 <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, 
 <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
"""
print(soup.select('a[href="http://example.com/elsie"]'))        # 二者之间不用空格隔开
# [<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]
print(soup.select('p a[href="http://example.com/elsie"]'))      # 二者之间用空格隔开
# [<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

        soup.select()方法的返回值为列表类型,可以通过遍历的形式输出,并以get_text()方法或.text属性获取内容,代码如下:

print(soup.select('a'))
"""
[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, 
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, 
<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
"""
# 遍历列表元素
for i in soup.select('a'):
    # 打印标签元素内容的两种方法
    print(i.get_text())
    print(i.text)
"""


Lacie
Lacie
Tillie
Tillie
"""

        网页源代码截图如下:


这里写图片描述

        使用BeautifulSoup模块+CSS选择器对页面进行解析的函数如下:

# 定义使用BeautifulSoup和CSS选择器解析页面的函数
def parse_per_page(url):
    """
    :param url:页面对应的url
    :return: 页面中包含的数据列表
    """
    # 创建Request对象
    req = request.Request(url=url)
    # 传入用户代理
    req.add_header('User-Agent', 'Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166  Safari/535.19')
    # 发送请求,读取打开网页
    response = request.urlopen(req)
    # 读取网页内容,重新编码
    html = response.read().decode('utf-8')
    # 创建BeautifulSoup对象用于解析网页内容
    html_soup = BeautifulSoup(html, 'lxml')
    # 创建存放每个页面数据的列表
    per_page_data = []
    # 遍历tr标签列表
    for item in html_soup.select('tr')[2:-1]:
        # 创建存放每天数据的列表
        per_day_data = []
        # 开奖时间
        time = item.select('td')[0].text
        per_day_data.append(time)
        # 期号
        issue = item.select('td')[1].text
        per_day_data.append(issue)
        # 中奖号码
        digits = int(str(item.select('td > em')[0].text) + str(item.select('td > em')[1].text) + str(item.select('td > em')[2].text))
        per_day_data.append(digits)
        # 单选
        single_selection = item.select('td')[3].text
        per_day_data.append(single_selection)
        # 组选3
        group_selection_3 = item.select('td')[4].text
        per_day_data.append(group_selection_3)
        # 组选6
        group_selection_6 = item.select('td')[5].text
        per_day_data.append(group_selection_6)
        # 销售额
        sales = item.select('td > strong')[0].text
        per_day_data.append(sales)
        # 返奖比例
        return_rates = item.select('td')[7].text
        per_day_data.append(return_rates)
        # 将每天的数据加入每页的数据中
        per_page_data.append(per_day_data)
    # 打印消息
    print('解析页面成功!')
    # 返回二维列表
    return per_page_data

        测试代码和效果如下:

#-*-coding:utf-8-*-
"""
@author:taoshouzheng
@time:2018/7/17 9:07
@email:tsz1216@sina.com
"""

from bs4 import BeautifulSoup
from urllib import request
import numpy as np


# 定义使用BeautifulSoup和CSS选择器解析页面的函数
def parse_per_page(url):
    """
    :param url:页面对应的url
    :return: 页面中包含的数据列表
    """
    # 创建Request对象
    req = request.Request(url=url)
    # 传入用户代理
    req.add_header('User-Agent', 'Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166  Safari/535.19')
    # 发送请求,读取打开网页
    response = request.urlopen(req)
    # 读取网页内容,重新编码
    html = response.read().decode('utf-8')
    # 创建BeautifulSoup对象用于解析网页内容
    html_soup = BeautifulSoup(html, 'lxml')
    # 创建存放每个页面数据的列表
    per_page_data = []
    # 遍历tr标签列表
    for item in html_soup.select('tr')[2:-1]:
        # 创建存放每天数据的列表
        per_day_data = []
        # 开奖时间
        time = item.select('td')[0].text
        per_day_data.append(time)
        # 期号
        issue = item.select('td')[1].text
        per_day_data.append(issue)
        # 中奖号码
        digits = int(str(item.select('td > em')[0].text) + str(item.select('td > em')[1].text) + str(item.select('td > em')[2].text))
        per_day_data.append(digits)
        # 单选
        single_selection = item.select('td')[3].text
        per_day_data.append(single_selection)
        # 组选3
        group_selection_3 = item.select('td')[4].text
        per_day_data.append(group_selection_3)
        # 组选6
        group_selection_6 = item.select('td')[5].text
        per_day_data.append(group_selection_6)
        # 销售额
        sales = item.select('td > strong')[0].text
        per_day_data.append(sales)
        # 返奖比例
        return_rates = item.select('td')[7].text
        per_day_data.append(return_rates)
        # 将每天的数据加入每页的数据中
        per_page_data.append(per_day_data)
    # 打印消息
    print('解析页面成功!')
    # 返回二维列表
    return per_page_data


# 主模块
if __name__ == "__main__":
    # 调用函数
    page_data = parse_per_page('http://kaijiang.zhcw.com/zhcw/html/3d/list.html')
    # 将列表转化为数组
    page_data_array = np.array(page_data)
    # 打印
    print(page_data_array)


这里写图片描述

        总的代码和效果如下:

#-*-coding:utf-8-*-
"""
@author:taoshouzheng
@time:2018/7/17 9:07
@email:tsz1216@sina.com
"""
from bs4 import BeautifulSoup
from urllib import request
import numpy as np

"""
使用BeautifulSoup模块和CSS选择器获取中彩网福彩3D的开奖数据
"""


# 定义获取所有页面对应的url的函数
def get_all_urls():
    """
    :return: url列表
    """
    # 创建url列表
    url_list = []
    # 第一页的真实请求地址
    ori_url = 'http://kaijiang.zhcw.com/zhcw/html/3d/list.html'
    # 加入列表
    url_list.append(ori_url)
    # 生成并遍历列表
    for i in list(range(2, 247)):
        url = 'http://kaijiang.zhcw.com/zhcw/html/3d/list_' + str(i) + '.html'
        # 加入列表
        url_list.append(url)
    # 打印消息
    print('成功获取url!')
    # 返回列表
    return url_list


# 定义使用BeautifulSoup和CSS选择器解析页面的函数
def parse_per_page(url):
    """
    :param url:页面对应的url
    :return: 页面中包含的数据列表
    """
    # 创建Request对象
    req = request.Request(url=url)
    # 传入用户代理
    req.add_header('User-Agent', 'Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166  Safari/535.19')
    # 发送请求,读取打开网页
    response = request.urlopen(req)
    # 读取网页内容,重新编码
    html = response.read().decode('utf-8')
    # 创建BeautifulSoup对象用于解析网页内容
    html_soup = BeautifulSoup(html, 'lxml')
    # 创建存放每个页面数据的列表
    per_page_data = []
    # 遍历tr标签列表
    for item in html_soup.select('tr')[2:-1]:
        # 创建存放每天数据的列表
        per_day_data = []
        # 开奖时间
        time = item.select('td')[0].text
        per_day_data.append(time)
        # 期号
        issue = item.select('td')[1].text
        per_day_data.append(issue)
        # 中奖号码
        digits = int(str(item.select('td > em')[0].text) + str(item.select('td > em')[1].text) + str(item.select('td > em')[2].text))
        per_day_data.append(digits)
        # 单选
        single_selection = item.select('td')[3].text
        per_day_data.append(single_selection)
        # 组选3
        group_selection_3 = item.select('td')[4].text
        per_day_data.append(group_selection_3)
        # 组选6
        group_selection_6 = item.select('td')[5].text
        per_day_data.append(group_selection_6)
        # 销售额
        sales = item.select('td > strong')[0].text
        per_day_data.append(sales)
        # 返奖比例
        return_rates = item.select('td')[7].text
        per_day_data.append(return_rates)
        # 将每天的数据加入每页的数据中
        per_page_data.append(per_day_data)
    # 打印消息
    print('解析页面成功!')
    # 返回二维列表
    return per_page_data


# 主模块
if __name__ == "__main__":
    # 创建用于存放所有数据的列表
    all_data = []
    # 调用函数获取所有的url
    url_list = get_all_urls()
    # 遍历列表中的每一个url
    for url in url_list:
        # 调用函数解析每一个网页
        page_data = parse_per_page(url=url)
        # 将每页的数据加入总的二维列表中
        all_data.extend(page_data)
    # 将存放所有数据的二维列表转化为数组
    all_data_array = np.array(all_data)
    # 表头信息
    header = '开奖日期' + '\t' + '期号' + '\t' + '中奖号码' + '\t' + '单选' + '\t' + '组选3' + '\t' + '组选6' + '\t' + '销售额(元)' + '\t' + '返奖比例'
    # 将数组中元素写入txt文件中
    np.savetxt('中彩3D开奖数据.txt', all_data_array, fmt='%s', delimiter='\t', header=header, comments='', encoding='utf-8')
    # 打印消息
    print('文件写入成功!')

        效果截图:


这里写图片描述
这里写图片描述

        欢迎交流! QQ:3408649893

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值