【爬虫】1.9 实践项目——爬取学生信息

1. 项目简介


设计一个 Web 服务器 server.py它读取 students.txt 文件中的学生数据,以表格的形式呈现在网页上,其中 students.txt 的格式如下:

No,Name,Gender,Age
1001,张三,男,20
1002,李四,女,19
1003,王五,男,21

设计一个客户端的爬虫程序client.py它从这个网页上爬行学生的这些信息,存储到数据库中。学生数据库可以使用 Sqllite 数据库 students.db。

2. 服务器程序


服务器程序首先读取同一个目录下的 students.txt 文件,然后组成一张<table>的HTML表格用网页的形式呈现,效果如下图:


程序先检查是否有 students.txt 文件存在,如果文件存在就打开读取,读出一行的数据使用逗号分开的,因此使用 split(",") 函数拆分,然把一行数据组成在<tr>...</tr>的行中,把每个数据组织在<td>...</td>的单元格中

服务器程序server.py 如下:


importflask
importos
​
app=flask.Flask(__name__)
​
​
@app.route("/")
defshow():
    ifos.path.exists("students.txt"):
        st="<h3>学生信息表</h3>"
        st=st+"<table border='1' width='300'>"
        fobj=open("students.txt", "rt", encoding="utf-8")
        whileTrue:
            s=fobj.readline().strip("\n")  # 读取一行,去除行尾部"\n"换行符号
            ifs=="":  # 如果读到文件尾部就退出
                break
            s=s.split(",")  # 按逗号拆分开
            st=st+"<tr>"
            foriinrange(len(s)):  # 把各个数据组织在<td>...</td>的单元格中
                st=st+"<td>"+s[i] +"</td>"
            st=st+"</tr>"  # 完成一行
        fobj.close()
        st=st+"</table>"
        returnst
​
​
if__name__=="__main__":
    app.run()
​

运行服务器程序,默认网址为 http://127.0.0.1:5000/

3. 客户端程序


客户端程序访问网址 http://127.0.0.1:5000/,从中下载其 HTML 网页,这个网页的结果如下:

<h3>学生信息表</h3>
<tableborder='1'width='300'>
    <tr>
        <td>No</td>
        <td>Name</td>
        <td>Gender</td>
        <td>Age</td>
    </tr>
    <tr>
        <td>1001</td>
        <td>张三</td>
        <td>男</td>
        <td>20</td>
    </tr>
    <tr>
        <td>1002</td>
        <td>李四</td>
        <td>女</td>
        <td>19</td>
    </tr>
    <tr>
        <td>1003</td>
        <td>王五</td>
        <td>男</td>
        <td>21</td>
    </tr>
</table>

程序要从这个 HTML 网页爬取数据,只要分解出第一行:

<tr><td>No</td><td>Name</td><td>Gender</td><td>Age</td></tr>

再次分解这一行的<td>...</td>数据,就知道这个表有哪些标题字段,这个表目前有 No、Name、Gender、Age 字段。

接下来再次分解出下一行的<tr>...</tr>数据:

<tr><td>1001</td><td>张三</td><td>男</td><td>20</td></tr>

再次分解这一行的<td>...</td>数据,得到 No、Name、Gender、Age 的数据依次是 "1001"、"张三"、"男"、"20",把这一行的数据写入对应的数据库即可。

要分解出<tr>...</tr>只要使用 r"<tr>"r"/tr" 的正则表达式即可,先用 r"<tr>" 匹配 HTML 代码,得到第一个 <tr> 的位置,再使用 r"</tr>" 匹配 HTML 字符串,得到第一个 </tr> 的位置,取出 <tr>...</tr> 的数据部分,再次使用 r"<td>" 与 r"</td>" 的正则表达式分解<td>...</td> 的数据。

客户端程序client.py 如下:

importurllib.request
importre
importsqlite3
​
​
# 在html中查找学生信息
defsearchWeb(html):
    rows= []
    # 查询第一个<tr>...</tr>行
    m=re.search(r"<tr>", html)
    n=re.search(r"</tr>", html)
    ifmisnotNoneandnisnotNone:
        # 跳过第一行的标题
        html=html[n.end():]
    # 查询第二行开始的数据部分
    m=re.search(r"<tr>", html)
    n=re.search(r"</tr>", html)
    whilemisnotNoneandnisnotNone:
        row= []
        start=m.end()  # start是<tr>的结束位置
        end=n.start()  # end是</tr>的开始位置
        t=html[start:end]  # t 是<tr>...</tr>包含的字符串
        html=html[n.end():]  # 是剩余的html
        # 查询第一组<td>...</td>
        a=re.search(r"<td>", t)
        b=re.search(r"</td>", t)
        whileaisnotNoneandbisnotNone:
            start=a.end()  # start是<td>的结束位置
            end=b.start()  # end是</td>的开始位置
            row.append(t[start:end])  # 找到一组<td>...</td>的数据
            t=t[b.end():]  # 本行剩余的部分
            a=re.search(r"<td>", t)
            b=re.search(r"</td>", t)
        # 增加一行数据
        rows.append(row)
        # 继续查找下一行<tr>...</tr>
        m=re.search(r"<tr>", html)
        n=re.search(r"</tr>", html)
    returnrows
​
​
# 保存学生信息到数据库
defsaveDB(rows):
    iflen(rows) ==0:  # 没有数据就返回
        return
    try:
        con=sqlite3.connect("students.db")
        cursor=con.cursor()
        try:
            cursor.execute("drop table students")  # 如果有students表就删除
        except:
            pass
        try:
            # 建立新的students表
            sql="create table students (No varchar(128) primary key,Name varchar(128),Gender varchar(128),Age int)"
            cursor.execute(sql)
        except :
            pass
​
        forrowinrows:
            iflen(row) ==4:
                # 插入一条记录
                sql="insert into students (No,Name,Gender,Age) values (?,?,?,?)"
                try:
                    No, Name, Gender, Age=row[0], row[1], row[2], int(row[3])
                    cursor.execute(sql, (No, Name, Gender, Age))
                exceptExceptionaserr:
                    print(err)
        con.commit()  # 数据库提交保存
        con.close()
    exceptExceptionaserr:
        print(err)
​
​
# 显示查找的信息
defshowWeb(rows):
    print("显示来自Web的数据...")
    forrowinrows:
        print(row)
​
​
# 显示数据库的数据
defshowDB():
    print("显示来自DB的数据...")
    try:
        con=sqlite3.connect("students.db")
        cursor=con.cursor()
        cursor.execute("select * from students")  # 查询数据库记录
        rows=cursor.fetchall()
        # 显示每条记录
        forrowinrows:
            print(row)
        con.close()
    exceptExceptionaserr:
        print(err)
​
​
try:
    url="http://127.0.0.1:5000"
    resp=urllib.request.urlopen(url)  # 访问这个网址获取 html
    data=resp.read()
    html=data.decode()
    rows=searchWeb(html)  # 在html中查找学生信息
    showWeb(rows)  # 显示查找的信息
    saveDB(rows)  # 保存学生信息到数据库
    showDB()  # 显示数据库的数据
exceptExceptionaserr:
    print(err)
​

程序执行后结果显示客户端从服务器的网页上爬取了学生信息并保存到来数据库:


下一篇文章:爬取淘宝商城商品
实战源码:Python网络爬虫实战

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,您想了解关于Java版Web搜索爬虫系统和Java开源爬虫框架WebCollector的教程,主要是如何爬取搜索引擎的内容,对吗?那我来给您介绍一下。 WebCollector是一款Java开源爬虫框架,它基于Jsoup解析库,提供了一系列简单易用的API,可以帮助用户快速开发爬虫程序。WebCollector可以用于爬取各种类型的网站,包括搜索引擎。 下面是一个简单的WebCollector爬虫程序示例,可以用来爬取百度搜索结果页面的内容: ```java import cn.edu.hfut.dmic.webcollector.model.Page; import cn.edu.hfut.dmic.webcollector.net.HttpRequest; import cn.edu.hfut.dmic.webcollector.net.HttpResponse; import cn.edu.hfut.dmic.webcollector.net.Requester; import cn.edu.hfut.dmic.webcollector.plugin.berkeley.BreadthCrawler; public class BaiduSearchCrawler extends BreadthCrawler { public BaiduSearchCrawler(String crawlPath, boolean autoParse) { super(crawlPath, autoParse); this.addSeed("https://www.baidu.com/s?wd=webcollector"); } public void visit(Page page, HttpRequest httpRequest, HttpResponse httpResponse) { System.out.println(page.getHtml()); } public static void main(String[] args) throws Exception { BaiduSearchCrawler crawler = new BaiduSearchCrawler("crawl", true); crawler.setThreads(10); crawler.start(2); } } ``` 在这个示例中,我们定义了一个名为BaiduSearchCrawler的类,它继承自BreadthCrawler类。在BaiduSearchCrawler的构造函数中,我们指定了爬虫程序的爬取路径和是否自动解析网页内容。然后,我们使用addSeed()方法添加了一个种子URL,这个URL是百度搜索webcollector的结果页面。 在visit()方法中,我们定义了爬取页面时的处理逻辑,这里我们只是简单地将页面内容打印出来。在main()方法中,我们创建了一个BaiduSearchCrawler对象,设置了线程数为10,并启动了爬虫程序。 当您运行这个程序时,它将会爬取百度搜索webcollector的结果页面,并将页面内容打印出来。 当然,实际的爬虫程序往往比这个示例要复杂得多,需要考虑到各种情况和异常处理。但是,WebCollector的API非常简单易用,您可以根据自己的需求快速开发出符合要求的爬虫程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值