Beautiful选择器/遍历文档树Day3-7

#!/usr/bin/env python
#coding: utf8
#python2
#Beautiful选择器
from bs4 import BeautifulSoup
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="sister"><b>$37</b></p>

<p class="story" id="p">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" >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>
"""

soup = BeautifulSoup(html_doc,'lxml')
#遍历文档树
#1.直接使用 重点
print(soup.html)
print(type(soup.html))
print(soup.a)
print(soup.p)

#2.获取标签的名称
print(soup.a.name)

#3.获取标签的属性 重点
print(soup.a.attrs) #获取a标签中的所有属性
print(soup.a.attrs['href'])

#4.获取标签的文本内容 重点
print(soup.a.text)

#5.嵌套选择
print(soup.html.body.p)

#6.子节点、子孙节点
print(soup.p.children) #返回迭代器对象
print((list(soup.p.children)))

#7.父节点、祖先节点
print(soup.b.parent)
print(soup.b.parents)
print(list(soup.b.parents))

#8.兄弟节点
print(soup.a)
#下一个兄弟节点
print(soup.a.next_sibling)

#获取下一个兄弟的所有节点,返回的是一个生成器
print(soup.a.next_siblings)
print(list(soup.a.next_siblings))

#获取上一个兄弟节点
print(soup.a.previous_sibling)
#获取上一个的所有兄弟节点,返回的是一个生成器
print(list(soup.a.previous_siblings))

 

转载于:https://www.cnblogs.com/zxdhahaha/p/11128293.html

AndroidStudio如何自定义banner然后用gilde库加载图片,用OKhttp请求http://km.shengtest.icu/ht.json然后对接到自定义的banner里面也要有点击事件可以跳转浏览器,这个是参数{ "公告开关": "开", "公告标题": "测试公告", "公告内容": "测试公告内容", "公告图片": "https://bizhi1.com/wp-content/uploads/2024/02/beautiful-fantasy-landscape-desktop-wallpaper-small.jpg", "公告按钮": "取消", "公告按钮2": "去查看", "公告链接": "https://www.baidu.com/", "轮播图1": "https://bizhi1.com/wp-content/uploads/2024/02/beautiful-fantasy-landscape-desktop-wallpaper-small.jpg", "轮播图2": "https://bizhi1.com/wp-content/uploads/2024/02/beautiful-fantasy-landscape-desktop-wallpaper-small.jpg", "轮播图3": "https://bizhi1.com/wp-content/uploads/2024/02/beautiful-fantasy-landscape-desktop-wallpaper-small.jpg", "轮播图链接1": "https://bizhi1.com/wp-content/uploads/2024/02/beautiful-fantasy-landscape-desktop-wallpaper-small.jpg", "轮播图链接2": "https://bizhi1.com/wp-content/uploads/2024/02/beautiful-fantasy-landscape-desktop-wallpaper-small.jpg", "轮播图链接3": "https://bizhi1.com/wp-content/uploads/2024/02/beautiful-fantasy-landscape-desktop-wallpaper-small.jpg", "版本号": "1.0", "更新标题": "测试更新", "更新内容": "测试更新内容", "更新链接": "https://www.baidu.com/", "任务": "https://www.baidu.com/", "美化跳转": "https://www.baidu.com/", "官方网站": "https://www.baidu.com/", "购买卡密": "https://www.baidu.com/", "用户反馈": "https://www.baidu.com/", "常用问题": "https://www.baidu.com/" }
07-15
<think>我们正在开发一个自定义Banner组件,需要完成以下功能: 1. 使用OkHttp请求接口获取轮播图数据(JSON格式) 2. 使用Glide加载网络图片(需要支持https,可能需要配置OkHttp集成) 3. 自定义Banner视图,能够展示多张图片并支持滑动 4. 实现点击跳转(跳转到浏览器打开链接) 步骤分解: 1. 添加依赖 在build.gradle (Module: app) 中添加以下依赖: ```groovy dependencies { implementation &#39;com.github.bumptech.glide:glide:4.12.0&#39; implementation &#39;com.squareup.okhttp3:okhttp:4.9.3&#39; // Glide集成OkHttp的库 implementation &#39;com.github.bumptech.glide:okhttp3-integration:4.12.0&#39; annotationProcessor &#39;com.github.bumptech.glide:compiler:4.12.0&#39; } ``` 2. 创建Banner数据模型 根据接口返回的JSON数据结构创建模型类。假设接口返回的JSON结构如下: ```json [ { "imageUrl": "http://...", "linkUrl": "http://..." }, ... ] ``` 创建模型类`BannerItem.java`: ```java public class BannerItem { private String imageUrl; private String linkUrl; // 构造方法、getter和setter public BannerItem(String imageUrl, String linkUrl) { this.imageUrl = imageUrl; this.linkUrl = linkUrl; } public String getImageUrl() { return imageUrl; } public String getLinkUrl() { return linkUrl; } } ``` 3. 创建自定义Banner视图 我们可以使用ViewPager2来实现轮播图。首先,创建一个布局文件`item_banner.xml`作为每个轮播项的布局: ```xml <?xml version="1.0" encoding="utf-8"?> <ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/banner_image" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitXY" /> ``` 4. 创建Banner适配器 为ViewPager2创建适配器`BannerAdapter.java`: ```java public class BannerAdapter extends RecyclerView.Adapter<BannerAdapter.BannerViewHolder> { private Context context; private List<BannerItem> bannerItems; public BannerAdapter(Context context, List<BannerItem> bannerItems) { this.context = context; this.bannerItems = bannerItems; } @NonNull @Override public BannerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(context).inflate(R.layout.item_banner, parent, false); return new BannerViewHolder(view); } @Override public void onBindViewHolder(@NonNull BannerViewHolder holder, int position) { BannerItem item = bannerItems.get(position); Glide.with(context) .load(item.getImageUrl()) .into(holder.bannerImage); } @Override public int getItemCount() { return bannerItems.size(); } static class BannerViewHolder extends RecyclerView.ViewHolder { ImageView bannerImage; public BannerViewHolder(@NonNull View itemView) { super(itemView); bannerImage = itemView.findViewById(R.id.banner_image); } } } ``` 5. 配置Glide使用OkHttp 为了确保Glide使用OkHttp加载图片(特别是https),我们需要在应用初始化时配置。创建一个`MyApp`类继承`Application`: ```java public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); // 配置Glide使用自定义的OkHttpClient Glide.init(this, new GlideBuilder() .setDefaultRequestOptions( new RequestOptions() .format(DecodeFormat.PREFER_RGB_565) ) ); // 替换Glide的默认加载方式为OkHttp OkHttpClient okHttpClient = new OkHttpClient.Builder() .build(); Glide.get(this).getRegistry().replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(okHttpClient)); } } ``` 并在`AndroidManifest.xml`中设置`application`的`name`属性: ```xml <application android:name=".MyApp" ...> </application> ``` 6. 请求接口数据并设置到ViewPager2 在Activity或Fragment中,使用OkHttp请求接口数据,解析并设置到ViewPager2中。 首先,在布局文件中加入ViewPager2: ```xml <androidx.viewpager2.widget.ViewPager2 android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="200dp"/> ``` 在Activity中: ```java public class MainActivity extends AppCompatActivity { private ViewPager2 viewPager; private BannerAdapter bannerAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewPager = findViewById(R.id.viewPager); bannerAdapter = new BannerAdapter(this, new ArrayList<>()); viewPager.setAdapter(bannerAdapter); // 请求数据 requestBannerData(); } private void requestBannerData() { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("http://km.shengtest.icu/ht.json") .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { e.printStackTrace(); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { if (response.isSuccessful()) { String json = response.body().string(); // 解析JSON List<BannerItem> bannerItems = parseJson(json); runOnUiThread(() -> { bannerAdapter = new BannerAdapter(MainActivity.this, bannerItems); viewPager.setAdapter(bannerAdapter); // 设置点击事件 setBannerItemClick(); }); } } }); } private List<BannerItem> parseJson(String json) { List<BannerItem> items = new ArrayList<>(); try { JSONArray jsonArray = new JSONArray(json); for (int i = 0; i < jsonArray.length(); i++) { JSONObject obj = jsonArray.getJSONObject(i); String imageUrl = obj.getString("imageUrl"); String linkUrl = obj.getString("linkUrl"); items.add(new BannerItem(imageUrl, linkUrl)); } } catch (JSONException e) { e.printStackTrace(); } return items; } private void setBannerItemClick() { // 为每个item设置点击事件 bannerAdapter.setOnItemClickListener((position, bannerItem) -> { // 跳转到浏览器 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(bannerItem.getLinkUrl())); startActivity(intent); }); } } ``` 注意:上面的`setBannerItemClick`方法需要我们在适配器中添加点击事件支持。修改适配器: 在`BannerAdapter`中添加: ```java public class BannerAdapter ... { // ... 之前的代码 private OnItemClickListener onItemClickListener; public interface OnItemClickListener { void onItemClick(int position, BannerItem item); } public void setOnItemClickListener(OnItemClickListener listener) { this.onItemClickListener = listener; } @Override public void onBindViewHolder(@NonNull BannerViewHolder holder, int position) { // ... 加载图片 holder.itemView.setOnClickListener(v -> { if (onItemClickListener != null) { onItemClickListener.onItemClick(position, bannerItems.get(position)); } }); } // ... } ``` 7. 添加网络权限 在`AndroidManifest.xml`中添加: ```xml <uses-permission android:name="android.permission.INTERNET" /> ``` 8. 处理https问题(如果需要) 如果接口是https且证书不被信任,可能需要配置OkHttp信任所有证书(仅用于测试环境,生产环境请使用正规证书)。可以创建一个`UnsafeOkHttpClient`工具类(注意:生产环境不要使用): ```java public class UnsafeOkHttpClient { public static OkHttpClient getUnsafeOkHttpClient() { try { // 创建信任所有证书的TrustManager final TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { @Override public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) { } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[]{}; } } }; // 安装TrustManager SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); // 使用自定义的TrustManager创建OkHttpClient OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0]); builder.hostnameVerifier((hostname, session) -> true); return builder.build(); } catch (Exception e) { throw new RuntimeException(e); } } } ``` 然后在`MyApp`中配置Glide时使用这个不安全的OkHttpClient(仅测试): ```java Glide.get(this).getRegistry().replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(UnsafeOkHttpClient.getUnsafeOkHttpClient())); ``` 注意:生产环境请勿使用`UnsafeOkHttpClient`,应使用正规的证书。 9. 实现自动轮播(可选) 可以使用Handler实现自动轮播功能,这里不再展开。 以上步骤实现了自定义Banner,使用Glide加载图片,通过OkHttp请求接口数据,并实现点击跳转。 注意事项: - 确保接口地址正确,且网络权限已添加。 - 在Android 9及以上,默认不允许http请求,需要在`AndroidManifest.xml`的`application`标签内添加`android:usesCleartextTraffic="true"`(如果接口是http)。 - 如果接口是https且证书有问题,生产环境应使用正规CA颁发的证书,测试环境可以使用上述不安全客户端临时解决。 §§相关问题§§ 1. 如何优化Banner的滑动体验和内存占用? 2. 除了ViewPager2,还有哪些方式可以实现轮播图? 3. 如何为Banner添加指示器(小圆点)?</think>### 在Android Studio中自定义Banner组件实现方案 #### 1. 添加依赖 在`build.gradle`中添加: ```groovy dependencies { // Glide图片加载 implementation &#39;com.github.bumptech.glide:glide:4.16.0&#39; kapt &#39;com.github.bumptech.glide:compiler:4.16.0&#39; // OkHttp网络请求 implementation &#39;com.squareup.okhttp3:okhttp:4.12.0&#39; // Glide-OkHttp集成 implementation &#39;com.github.bumptech.glide:okhttp3-integration:4.16.0&#39; // ViewPager2轮播图 implementation &#39;androidx.viewpager2:viewpager2:1.0.0&#39; } ``` #### 2. 配置Glide与OkHttp集成 在`Application`类中初始化: ```java public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); // 配置Glide使用自定义OkHttpClient[^2] Glide.get(this).getRegistry().replace( GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(UnsafeOkHttpClient.getUnsafeOkHttpClient()) ); } } // 解决https证书问题 public class UnsafeOkHttpClient { public static OkHttpClient getUnsafeOkHttpClient() { try { final TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) {} @Override public void checkServerTrusted(X509Certificate[] chain, String authType) {} @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; } } }; final SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustAllCerts, new SecureRandom()); return new OkHttpClient.Builder() .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0]) .hostnameVerifier((hostname, session) -> true) .build(); } catch (Exception e) { throw new RuntimeException(e); } } } ``` #### 3. 创建数据模型 ```java public class BannerItem { private String imageUrl; private String linkUrl; // 构造函数、getter/setter } ``` #### 4. 实现Banner适配器 ```java public class BannerAdapter extends RecyclerView.Adapter<BannerAdapter.ViewHolder> { private List<BannerItem> items; private OnItemClickListener listener; public BannerAdapter(List<BannerItem> items) { this.items = items; } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_banner, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { BannerItem item = items.get(position); // 使用Glide加载图片(自动支持GIF)[^1] Glide.with(holder.itemView) .load(item.getImageUrl()) .into(holder.imageView); holder.itemView.setOnClickListener(v -> { if (listener != null) listener.onClick(item); }); } // 设置点击监听器 public void setOnItemClickListener(OnItemClickListener listener) { this.listener = listener; } public interface OnItemClickListener { void onClick(BannerItem item); } static class ViewHolder extends RecyclerView.ViewHolder { ImageView imageView; public ViewHolder(@NonNull View itemView) { super(itemView); imageView = itemView.findViewById(R.id.iv_banner); } } } ``` #### 5. 实现Banner布局 `item_banner.xml`: ```xml <ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/iv_banner" android:layout_width="match_parent" android:layout_height="200dp" android:scaleType="centerCrop"/> ``` #### 6. 主Activity实现 ```java public class MainActivity extends AppCompatActivity { private ViewPager2 viewPager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewPager = findViewById(R.id.viewPager); // 请求API数据 fetchBannerData(); } private void fetchBannerData() { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("http://km.shengtest.icu/ht.json") .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { Log.e("Banner", "API请求失败", e); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { if (response.isSuccessful()) { String json = response.body().string(); List<BannerItem> items = parseJson(json); runOnUiThread(() -> setupBanner(items)); } } }); } private List<BannerItem> parseJson(String json) { List<BannerItem> items = new ArrayList<>(); try { JSONArray array = new JSONArray(json); for (int i = 0; i < array.length(); i++) { JSONObject obj = array.getJSONObject(i); items.add(new BannerItem( obj.getString("imageUrl"), obj.getString("linkUrl") )); } } catch (JSONException e) { Log.e("Banner", "JSON解析错误", e); } return items; } private void setupBanner(List<BannerItem> items) { BannerAdapter adapter = new BannerAdapter(items); viewPager.setAdapter(adapter); // 设置点击跳转 adapter.setOnItemClickListener(item -> { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(item.getLinkUrl())); startActivity(intent); }); } } ``` #### 7. 添加权限 ```xml <uses-permission android:name="android.permission.INTERNET" /> ``` #### 关键点说明: 1. **Glide自动处理图片格式**:支持JPG/PNG/GIF等格式[^1] 2. **HTTPS支持**:通过自定义`TrustManager`解决证书问题[^2] 3. **点击跳转**:使用`Intent.ACTION_VIEW`打开浏览器 4. **内存优化**:Glide自动处理图片缓存和内存管理 5. **异步加载**:OkHttp在后台线程处理网络请求 #### 效果优化建议: 1. 添加加载进度条和错误占位图 2. 实现自动轮播功能 3. 添加页面指示器(小圆点) 4. 实现平滑滚动动画
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值