数据采集与融合技术实践(爬虫)——作业1

作业①

o 要求:用requests和BeautifulSoup库方法定向爬取给定网址(http://www.shanghairanking.cn/rankings/bcur/2020 )的数据,屏幕打印爬取的大学排名信息。
o 输出信息:

排名 学校名称 省市 学校类型 总分
1 清华大学 北京 综合 852.5
2 ..... ..... ..... .....

(1)实验代码

第一版代码如下:

点击查看代码
import urllib.request  # 获取URL信息
from bs4 import BeautifulSoup
import bs4


# 获取网页内容
def fetchWebContent(url):  # 获取URL信息,输出内容
    try:
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"
        }
        req = urllib.request.Request(url,headers=headers)
        # 打开URL网站的网址,读出二进制数据,二进制数据转为字符串
        data = urllib.request.urlopen(req).read().decode()
        return data
    except Exception as err:
        print(err)


# 提取网页内容中信息到合适的数据结构,解析网页数据
def parseUniversityData(ulist, html):  # 将html页面放到ulist列表中(核心)
    soup = BeautifulSoup(html, "html.parser")
    for tr in soup.find('tbody').children:
        if isinstance(tr, bs4.element.Tag):  # 如果tr标签的类型不是bs4库中定义的tag类型,则过滤掉
            a = tr('a')  # 把所用的a标签存为一个列表类型
            tds = tr('td')  # 将所有的td标签存为一个列表类型
            ulist.append([tds[0].text.strip(), a[0].string.strip(), tds[2].text.strip(),
                          tds[3].text.strip(), tds[4].text.strip()])


# 利用数据结构展示并输出结果:定义函数,打印大学排名数据
def printUnivList(ulist1, num):  # 打印出ulist列表的信息,num表示希望将列表中的多少个元素打印出来
    tplt = "{0:^10}\t{1:{5}^10}\t{2:^12}\t{3:^12}\t{4:^10}"
    print(tplt.format("排名", "学校名称", "省份", "学校类型", "总分",chr(12288)))
    for i in range(num):
        u = ulist1[i]
        print(tplt.format(u[0], u[1], u[2], u[3], u[4],chr(12288)))


def main():
    uinfo = []  # 将大学信息放到列表中
    url = "http://www.shanghairanking.cn/rankings/bcur/202311"
    html = fetchWebContent(url)
    parseUniversityData(uinfo, html)
    #这边仅爬取排名前100的学校做展示
    num = 30
    printUnivList(uinfo, num)


if __name__ == '__main__':
    main()


image

但是发现有几处问题:

  1. urlib库与request库
    对比了二者,发现urllib库构造请求头和发起请求需要分别需要req=urllib.request.Request(url,headers)、urllib.request.urlopen(req),而request库只要requset.get(url,headers)一行,于是我光速投入request库的怀抱。
  2. 某几行输出不规范

改进后的代码如下:

点击查看代码
import requests  # 获取URL信息
from bs4 import BeautifulSoup
import bs4


# 获取网页内容
def fetchWebContent(url):  # 获取URL信息,输出内容
    try:
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"
        }
        r = requests.get(url, headers=headers, timeout=30)  # 设置超时为30秒,30秒返回响应,否则就抛出异常
        r.raise_for_status()  # 如果发送了一个错误请求,就可以通过r.raise_for_status()来抛出异常
        r.encoding = r.apparent_encoding
        return r.text
    except Exception as err:
        print(err)


# 提取网页内容中信息到合适的数据结构,解析网页数据
def parseUniversityData(ulist, html):  # 将html页面放到ulist列表中(核心)
    soup = BeautifulSoup(html, "html.parser")
    for tr in soup.find('tbody').children:
        if isinstance(tr, bs4.element.Tag):  # 如果tr标签的类型不是bs4库中定义的tag类型,则过滤掉
            a = tr('a')  # 把所用的a标签存为一个列表类型
            tds = tr('td')  # 将所有的td标签存为一个列表类型
            ulist.append([tds[0].text.strip(), a[0].string.strip(), tds[2].text.strip(),
                          tds[3].text.strip(), tds[4].text.strip()])


# 利用数据结构展示并输出结果:定义函数,打印大学排名数据
def printUnivList(ulist1, num):  # 打印出ulist列表的信息,num表示希望将列表中的多少个元素打印出来
    tplt = "{0:^10}\t{1:{5}^10}\t{2:^12}\t{3:^12}\t{4:^10}"
    print(tplt.format("排名", "学校名称", "省份", "学校类型", "总分", chr(12288)))
    for i in range(num):
        u = ulist1[i]
        print(tplt.format(u[0], u[1], u[2], u[3], u[4], chr(12288)))


def main():
    uinfo = []  # 将大学信息放到列表中
    url = "http://www.shanghairanking.cn/rankings/bcur/202311"
    html = fetchWebContent(url)
    parseUniversityData(uinfo, html)
    # 这边仅爬取排名前30的学校做展示
    num = 30
    printUnivList(uinfo, num)


if __name__ == '__main__':
    main()

image

(2)心得体会

  1. request库相较urllib库更为方便。
  2. chr(12288)用于对齐真好用!
  3. 原来以为爬完了要关掉,不然多运行几个爬虫程序且都没关之后,爬取的速度会变得很慢。使用的 requests 库自身会处理连接的关闭,所以通常不需要手动关闭。

作业②

o 要求:用requests和re库方法设计某个商城(自已选择)商品比价定向爬虫,爬取该商城,以关键词“书包”搜索页面的数据,爬取商品名称和价格。
o 输出信息:

序号 价格 商品名
1 65.00 xxx
2 ..... .....

(1)实验代码

  1. 定位到我们想要获取的图片元素的所在位置(巧用F12)。
    首先输入关键词“书包”,刷新页面请求,观察页面结构。
    image
    多观察几个后发现,<ul class="bigimg cloth_shoplist" id="component_lixia59>下的<li>分别对应一个单品,而我们想要获取的商品名称元素位于<li>的<a>标签里的'title'属性中,价格元素位于<li>下<p>下<span>的文本值中。
    至此,每个单品的名称和价格已能够获取到。
    2. 翻页处理
    现在我们能够拿到一整张页面的图片,但是怎么获取第2页、第3页、或者说更多页后面的数据呢?
    image
    第一下观察页面毫无头绪,请求根本没有携带和页数有关的参数。只能继续往下看第二页:
    image
    这时候发现了和页面有关的参数page_index,现在再尝试回到第一页。
    image

发现原来search.dangdang.com/?key=%CA%E9%B0%FC&act=input&page_index=1和search.dangdang.com/?key=%CA%E9%B0%FC&act=input都是指向第一页,那现在实现翻页只需要修改url中的page_index即可。

(2)心得体会

1.随着爬虫技术的发展,反爬手段也在跟进。其实第一下想爬的是淘宝,发现刷新页面返回的响应数据全是动态加密后的,于是转去了当当哈哈。
2.学会了巧用F12来观察页面结构,定位元素位置。

作业③:

o 要求:爬取一个给定网页( https://xcb.fzu.edu.cn/info/1071/4481.htm)或者自选网页的所有JPEG和JPG格式文件
o 输出信息:将自选网页内的所有JPEG和JPG文件保存在一个文件夹中

(1)实验代码

点击查看代码
import requests
from bs4 import BeautifulSoup
import os

url = r'https://xcb.fzu.edu.cn/info/1071/4481.htm'
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"
}
response = requests.get(url=url, headers=headers).text
soup = BeautifulSoup(response, 'lxml')
img_list = soup.select("p[class='vsbcontent_img'] img")
for img in img_list:
    url_ = img.attrs['src']
    img_url_ = 'https://xcb.fzu.edu.cn{}'.format(url_)
    response_ = requests.get(url=img_url_, headers=headers).content
    # 使用os.path.basename获取URL的最后一部分,并替换不合法字符
    filename = os.path.basename(url_).split('?')[0]
    imgPath = './' + filename
    with open(imgPath, 'wb') as fp:
        fp.write(response_)
        print(filename, '下载成功!!!')

(2)心得体会

在第二题的基础上,本题稍作改变就能拿下!努力努力冲冲冲

posted @ 2023-09-26 09:06  毕加毕加索  阅读(2)  评论(0编辑  收藏  举报