简介:
学习前端的时候,想要找个适合新手的网页来复刻,于是找到了百度网页,这部分代码实现了前端框架的搭建,补充了爬虫爬取的百度热搜榜,并通过fastapi更新到前端,还有登录界面的实现。
前端代码:
html+JavaScript+vue:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BaiDu</title>
<link rel="stylesheet" href="baidu.css">
<script type="text/javascript" src="./js/vue.js"></script>
</head>
<body>
<!-- 头部导航栏 -->
<div id="base">
<div id="header">
<div class="header_left">
<ul class="header_left_ul">
<li><a href="#">新闻</a></li>
<li><a href="#">hao123</a></li>
<li><a href="#">地图</a></li>
<li><a href="#">视频</a></li>
<li><a href="#">贴吧</a></li>
<li><a href="#">学术</a></li>
<li class="show">
<a href="#">更多</a>
<div class="more">
<ul class="more_drop">
<li><img src="./img/baike.png" alt="">
<div>百科</div>
</li>
<li><img src="./img/baobaozhidao.png" alt="">
<div>宝宝</div>
</li>
<li><img src="./img/jingyan.png" alt="">
<div>经验</div>
</li>
<li><img src="./img/tu.png" alt="">
<div>图片</div>
</li>
<li><img src="./img/wangpan.png" alt="">
<div>网盘</div>
</li>
<li><img src="./img/wneku.png" alt="">
<div>文库</div>
</li>
<li><img src="./img/yinyue.png" alt="">
<div>音乐</div>
</li>
<li><img src="./img/zhidao.png" alt="">
<div>知道</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="header_right">
<!-- <button href="#">登陆</button> -->
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#loginModal"
onclick="openDialog()">
登陆
</button>
</div>
<div class="setting"><span>设置</span></div>
</div>
<!-- 中间主体 -->
<div id="main">
<div class="main_left"></div>
<div class="main_center">
<div class="logo">
<img src="./img/baidu_logo.png" alt="">
</div>
<div class="search">
<input type="text">
<input type="submit" value="百度一下">
<!-- <button></button> -->
</div>
<div style="padding-top: 50px;">
<!-- <div style="float: left;font-size: 20px;">
<span>百度热榜</span>
</div>
<div style="float: right;font-size: 20px;">
<span>换一换</span>
</div> -->
<table>
<tr>
<td><span>百度热榜</span></td>
<td style="float: right;"><button class="huanyihuan" @click="upgrade"
style="border:none;background-color: white;color: rgb(31, 29, 96);"><a
href="javascript:void(0)">换一换</a></button></td>
</tr>
<tr>
<td><a :href="name[3]" target="_blank"><span style="color: rgb(250, 61, 61);">1</span>
{{name[2]}} <span style="background: lightcoral;border-radius: 5px; color: white;">
 新  </span></a></td>
<td><a :href="name[9]" target="_blank"><span style="color: #aaa;">4</span> {{name[8]}}</a>
</td>
</tr>
<tr>
<td><a :href="name[5]" target="_blank"><span style="color: rgb(255, 100, 100);">2</span>
{{name[4]}}</a></td>
<td><a :href="name[11]" target="_blank"><span style="color: #aaa;">5</span> {{name[10]}}</a>
</td>
</tr>
<tr>
<td><a :href="name[7]" target="_blank"><span style="color: rgb(255, 165, 165);">3</span>
{{name[6]}} </span></a></td>
<td><a :href="name[13]" target="_blank"><span style="color: #aaa;">6</span> {{name[12]}}</a>
</td>
</tr>
</table>
</div>
</div>
<div class="main_right"></div>
</div>
<!-- 尾部 -->
<div id="footer">
<div class="footer_left">
<ul class="footer_left_ul">
<li><a href="#">设为首页</a></li>
<li><a href="#">关于百度</a></li>
<li><a href="#">About Baidu</a></li>
<li><a href="#">百度营销</a></li>
<li><a href="#">使用百度前必读</a></li>
<li><a href="#">意见反馈</a></li>
<li><a href="#">帮助中心</a></li>
</ul>
</div>
<div class="footer_right">
<ul class="footer_right_ul">
<li><a href="#">2023.1.20</a></li>
<li><a href="#">深圳</a></li>
<li><a href="#">Nora & Ledger
</a></li>
</ul>
</div>
</div>
<div id="light" class="login">
<div>
<a href="javascript:void(0)" style="top:0px;left:0px;float: right;margin-right: 10px;" onclick="closeDialog()"><img src="./img/cha.png" alt="cha" style="width: 15px;"></a>
<h5 style="float: left;margin-left: 10px;">Login</h5>
<!-- <div>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" >
<span aria-hidden="true">×</span>
</button>
</div> -->
</div>
<div style="float: left;width:100%">
<div class="login_check" style="float:left;margin-top: 25px;margin-bottom: 15px;">
<span style="margin-left: 10px;">
账号登录
</span>
<span style="margin-left: 50px;">
短信登录
</span>
</div>
<div class="login_center">
<input placeholder="手机号/用户名/邮箱"><br />
<input placeholder="密码"><br />
<div><a href="#" style="float: right;margin-top: 10px;margin-right: 10px;color:rgb(109, 109, 146)">忘记密码?</a>
</div>
</div>
<div class="login_footer" style="clear:both">
<button style="display: inline-block;">
登录
</button>
<div style="float: left;margin-left: 17%;">
阅读并接受<a href="#"><strong style="color:rgb(109, 109, 146);">百度用户协议 </strong></a>和<a href="#"><strong
style="color:rgb(109, 109, 146)">隐私政策</strong></a>
</div>
</div>
</div>
</div>
</div>
<div class="page">
<keep-alive>
<router-view></router-view>
</keep-alive>
</div>
</body>
<script>
function closeDialog() {
document.getElementById('light').style.display = 'none';
}
function openDialog() {
document.getElementById('light').style.display = 'block';
}
</script>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el: '#base',
data: {
name: [],
},
methods: {
upgrade: function () {
var that = this;
// alert('nihao');
axios.get("http://localhost:8000/upgrade")
.then(function (res) {
// alert('你好吗');
that.name = res.data;
console.log(res);
console.log(that.name);
}), function () { alert('请求失败') }
}
},
activated() {
this.type = this.$route.query.type;
},
})
</script>
<script src="./js/axios.min.js"></script>
</html>
css:
*{
padding:0;margin:0;
color: #222;
font-size: 16px;
}
li{
list-style: none;
}
a{
text-decoration: none;
padding-left: 12px;
}
a:hover{
color:#4e71f2;
}
#header{
width: 100%;
height: 60px;
background: #eee;
/* border */
}
.header_left_ul>li{
/* display: inline; */
float: left;
margin-right: 20px;
margin-top: 22px;
line-height: 100%;
text-align: center;
}
.header_left ul{
padding-left: 25px;
}
.header_right{
float: right;
}
.setting{
float: right;
line-height: 12px;
margin-top: 11px;
padding: 10px;
margin-right: 20px;
}
.more{
display: none;
position: absolute;
/* left: 12%; */
top: 60px;
width: 300px;
height: 223px;
line-height: 30px;
text-align: center;
box-shadow: 0 2px 10px rgb(0 0 0 / 15%);
border-radius: 12px;
background: #fff;
padding-right: 15px;
left: 170px;
}
.more_drop>li{
float: left;
padding: 13px;
}
.more_drop>li>img{
width: 42px;
height: 42px;
}
.more_drop>li>div{
text-align: center;
}
.show:hover div{
display: block;
}
.header_right>button{
background-color: rgb(95, 95, 233);
border-radius: 6px;
float: right;
line-height: 12px;
margin-right: 50px;
color: white;
padding: 10px;
margin-top: 11px;
border: none;
}
.main{
width: 100%;
}
.main_left{
float: left;
width: 25%;
height: 730px;
/* background: red; */
}
.main_center{
float: left;
width: 50%;
/* background: black; */
height: 730px;
}
.main_right{
float: right;
width: 25%;
/* background: blue; */
height: 730px;
}
.logo>img{
width: auto;
height: 230px;
}
.logo{
text-align:center;
}
.search{
height: 50px;
/* background: pink; */
}
.search>input:first-child{
height: 100%;
width: 81%;
border-radius: 10px;
border: solid #ddd 1px;
}
.search>input:nth-child(2){
height: 100%;
width: 19%;
margin-left: -15px;
background-color: #4e71f2;
border: none;
font-size: 17px;
color: white;
border-radius: 0px 10px 10px 0px;
padding: 14px;
}
table{
height: 180px;
width: 100%;
margin-bottom: 50px;
}
.main_center>tr{
border:50px solid red;
margin-left: 50px;
}
.main_center>a{
font-size: 50px;
}
#footer{
position: fixed;
width: 100%;
background: #eee;
height: 40px;
bottom: 0;
}
.footer_left_ul{
margin-top: 10px;
}
.footer_left_ul>li{
float: left;
margin-right: 10px;
/* margin-top: 22px; */
line-height: 100%;
text-align: center;
}
.footer_left_ul>li>a{
color: #aaa;
}
.footer_right_ul{
margin-top: 10px;
}
.footer_right_ul>li{
float: right;
margin-right: 10px;
/* margin-top: 22px; */
line-height: 100%;
text-align: center;
}
.login{
float:right;
margin-right: 35%;
margin-top: -40%;
display:none;
background-color: rgb(246, 250, 248);
width:30%;
height: 60%;
/* border-bottom:none; */
border-radius: 10px;
font-size: 20px;
padding:10px;
opacity: 0.99;
padding: 25px;
box-shadow:15px 15px 8px rgba(5, 45, 58, 0.368)
}
.login_top_modal{
margin-top: 20px;
margin-bottom: 20px;
}
.login_center>input{
width: 97%;
margin-left: 1%;
margin-top: 1%;
border-radius: 5px;
height: 50px;
border: solid #ddd 1px;
}
.login_footer>button{
width:97%;
height: 50px;
border-radius: 5px;
margin-left: 1%;
margin-top: 1%;
background-color: rgb(95, 95, 233);
color: white;
/* border: solid #ddd 1px; */
box-shadow: 0px 3px 5px rgb(0 0 0 / 14%);
border:none;
}
.login_footer>div{
margin-left: 66px;
margin-top: 20px;
}
input::placeholder {
position: absolute;
top: 10px;
left: 10px;
}
/* .huanyihuan:hover {
background-color: pink;
} */
/* .huanyihuan:hover {
border:none;
background-color: pink;
} */
爬虫:
import requests
from lxml import etree as et
import urllib
import urllib.request
import urllib.error
from bs4 import BeautifulSoup
import json
import time
import random
import os
# 请求头
headers = {
# 用户代理
# 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
# 'User-Agent': 'Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1'
'User-Agent': '"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"'
}
USER_AGENT_LIST = [
'MSIE (MSIE 6.0; X11; Linux; i686) Opera 7.23',
'Opera/9.20 (Macintosh; Intel Mac OS X; U; en)',
'Opera/9.0 (Macintosh; PPC Mac OS X; U; en)',
'iTunes/9.0.3 (Macintosh; U; Intel Mac OS X 10_6_2; en-ca)',
'Mozilla/4.76 [en_jp] (X11; U; SunOS 5.8 sun4u)',
'iTunes/4.2 (Macintosh; U; PPC Mac OS X 10.2)',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.0) Gecko/20100101 Firefox/5.0',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20120813 Firefox/16.0',
'Mozilla/4.77 [en] (X11; I; IRIX;64 6.5 IP30)',
'Mozilla/4.8 [en] (X11; U; SunOS; 5.7 sun4u)'
]
url = 'https://top.baidu.com/board?tab=realtime'
page = requests.get(url, verify=False)
s = requests.session()
s.keep_alive = False
home_page = 'https://top.baidu.com/board?tab=realtime'
# 下载页面
def download(url, user_agent='wswp', num_retries=2):
print('downloading: %', url)
# 防止对方禁用Python的代理,导致forbidden错误
headers = {'User-agent': user_agent}
request = urllib.request.Request(url, headers=headers)
try:
html = urllib.request.urlopen(request).read()
except urllib.error.URLError as e:
print('download error:', e.reason)
html = None
if num_retries > 0:
# URLError是一个上层的类,因此HttpERROR是可以被捕获到的。code是HttpError里面的一个字段
if hasattr(e, 'code') and 500 <= e.code < 600:
return download(url, num_retries - 1)
return html
# 获得页面内容
def get_content(page_url):
html_result = download(page_url)
if html_result is None:
print('is None')
exit(1)
else:
pass
# 分析得到的结果,从中找到需要访问的内容
soup = BeautifulSoup(html_result, 'html.parser')
return soup
def get_mian_content(url):
second_html = get_content(url)
# print(second_html)
# name = second_html.find('h1').find('a').text
name = []
num_list = second_html.find_all(
'div', attrs={'class': "category-wrap_iQLoo horizontal_1eKyQ"})
j = 0
for i in num_list:
a = i.find('a').find('div').text
b = i.find('div', attrs={'class': 'c-single-text-ellipsis'}).text
c = i.find('a', attrs={'class': 'img-wrapper_29V76'})['href']
name.append(b)
name.append(c)
# print(a)
print(name)
# break
return name
后端:
from fastapi import FastAPI
from 百度 import *
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
app = FastAPI()
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"],
allow_headers=["*"], )
@app.get("/upgrade")
async def Upgrade():
name = []
name = get_mian_content('https://top.baidu.com/board?tab=realtime')
print(name)
return name
name = get_mian_content('https://top.baidu.com/board?tab=realtime')
print(name)
if __name__ == '__main__':
uvicorn.run(app='main:app', host="0.0.0.0", port=8000)
效果图:
尾语:
代码与真正的百度搜索网页相比还有很多的不足,只是复刻了部分,后面会逐渐补充代码。