Skip to content

Fa爬虫教程

7339字约24分钟

2024-05-28

DOM查找网页分类实战

--导入jsoup库
import'org.jsoup.*'
--定义链接
url = 'http://dh.hfybbs.vip/cn/index.html'
--这里使用Http方法先获取到网页源码再解析。
--因为jsoup自带的connect方法是同步加载,会影响程序加载速度
Http.get(url,function(code,content)
  if code==200 then--判断网站状态
    doc = Jsoup.parse(content)--使用jsoup解析网页
    classification = doc.getElementsByClass('text-gray')--查找到所有class为text-gray的网页元素
    classification = luajava.astable(classification)--将其转换成table表
    for k,v in pairs(classification) do--循环打印输出
      print(v.text())
    end
  else
    print('无法访问')
  end
end)

jsoup概述

此篇教程必须最新版盒子才能正常运行!
jsoup概述
jsoup是java里的一个普遍使用的html解析器,其的逻辑简单,语法容易,且功能强大。
(此篇教程我不会再用中文变量,中文太别扭。。。。。。)

但androlua中并没有自带这个模块,我们需要将其导入
dex库下载链接http://47.107.34.109:8000/d/c8f7ecb09db940de9725/
使用方法:工程目录下创建libs目录,将jsoup开头的dex文件放入,在程序开头加入 import'org.jsoup.*'即可

jsoup API
从String解析文档
html = "<html><head><title>First parse</title></head>"
+ "<body><p>Parsed HTML into a doc.</p></body></html>"
doc = Jsoup.parse(html)

解析一个网页碎片
html = "<div><p>Lorem ipsum.</p>"
doc = Jsoup.parseBodyFragment(html)
body = doc.body()

从URL加载文档
doc = Jsoup.connect("http://example.com/").get()
title = doc.title()

高级url请求
doc = Jsoup.connect("http://example.com")
.data("query", "Java")
.userAgent("Mozilla")
.cookie("auth", "token")
.timeout(3000)
.post()

从文件加载文档
input = new File("/tmp/input.html")
doc = Jsoup.parse(input, "UTF-8", "http://example.com/")

使用DOM方法导航文档
寻找元素
getElementById(String id)
getElementsByTag(String tag)
getElementsByClass(String className)
getElementsByAttribute(String key) (及相关方法)
元素的兄弟姐妹:siblingElements(),firstElementSibling(),lastElementSibling(),nextElementSibling(),previousElementSibling()
图:parent(),children(),child(int index)
元素数据
attr(String key)获取和attr(String key, String value)设置属性
attributes() 获得所有属性
id(),className()和classNames()
text()获取和text(String value)设置文本内容
html()获取和html(String value)设置内部HTML内容
outerHtml() 获取外部HTML值
data()获取数据内容(例如script和style标签)
tag() 和 tagName()
处理HTML和文本
append(String html), prepend(String html)
appendText(String text), prependText(String text)
appendElement(String tagName), prependElement(String tagName)
html(String value)

使用selector-syntax查找元素
选择器概述
tagname:按标签查找元素,例如 a
ns|tag:在命名空间中按标记fb|name查找<fb:name>元素,例如查找元素
#id:按ID查找元素,例如 #logo
.class:按类名查找元素,例如 .masthead
[attribute]:具有属性的元素,例如 [href]
[^attr]:具有属性名称前缀的[^data-]元素,例如查找具有HTML5数据集属性的元素
[attr=value]:具有属性值的元素,例如[width=500](也是可引用的[data-name='launch sequence'])
[attr^=value],[attr$=value],[attr*=value]:用与启动属性,以结束,或包含所述的值,例如元素[href*=/path/]
[attr~=regex]:具有与正则表达式匹配的属性值的元素; 例如img[src~=(?i)\.(png|jpe?g)]
*:所有元素,例如 *
选择器组合
el#id:具有ID的元素,例如 div#logo
el.class:带有类的元素,例如 div.masthead
el[attr]:具有属性的元素,例如 a[href]
任何组合,例如 a[href].highlight
ancestor child:从祖先下降的子元素,例如在类“body”的块下的任何位置.body p查找p元素
parent > child:直接从父级下降的子元素,例如div.content > p查找p元素; 并body > *找到body标签的直接子节点
siblingA + siblingB:找到兄弟B元素之后紧接着兄弟A,例如 div.head + div
siblingA ~ siblingX:找到兄弟A前面的兄弟X元素,例如 h1 ~ p
el, el, el:对多个选择器进行分组,找到与任何选择器匹配的唯一元素; 例如div.masthead, div.logo
伪选择器
:lt(n):找到其兄弟索引(即它在DOM树中相对于其父节点的位置)小于的元素n; 例如td:lt(3)
:gt(n):查找兄弟索引大于的元素n; 例如div p:gt(2)
:eq(n):查找兄弟索引等于的元素n; 例如form input:eq(1)
:has(selector):查找包含与选择器匹配的元素的元素; 例如div:has(p)
:not(selector):查找与选择器不匹配的元素; 例如div:not(.logo)
:contains(text):查找包含给定文本的元素。搜索不区分大小写; 例如p:contains(jsoup)
:containsOwn(text):查找直接包含给定文本的元素
:matches(regex):查找文本与指定正则表达式匹配的元素; 例如div:matches((?i)login)
:matchesOwn(regex):查找自己的文本与指定正则表达式匹配的元素
注意,上面的索引伪选择器是基于0的,即第一个元素是索引0,第二个元素是1

从元素中提取属性,文本和HTML
要获取属性的值,请使用该Node.attr(String key)方法
对于元素(及其组合子元素)上的文本,请使用 Element.text()
对于HTML,使用Element.html()或Node.outerHtml()
上述方法是元素数据访问方法的核心。还有其他人:
Element.id()
Element.tagName()
Element.className() 和 Element.hasClass(String className)
所有这些访问器方法都有相应的setter方法来更改数据。

设置属性值
使用属性setter方法Element.attr(String key, String value),和Elements.attr(String key, String value)。
如果需要修改class元素的属性,请使用Element.addClass(String className)和Element.removeClass(String className)方法。

设置元素的HTML
div = doc.select("div").first()
div.html("<p>lorem ipsum</p>")
div.prepend("<p>First</p>")
div.append("<p>Last</p>")

Element span = doc.select("span").first()
span.wrap("<li><a href='http://example.com/'></a></li>")

设置元素的文本内容
Element div = doc.select("div").first()
div.text("five > four")
div.prepend("First ")
div.append(" Last")

jsoup爬取网页标题实战

--导入jsoup库
import'org.jsoup.*'
--定义链接
url = 'http://dh.hfybbs.vip'
--这里使用Http方法先获取到网页源码再解析。
--因为jsoup自带的connect方法是同步加载,会影响程序加载速度
Http.get(url,function(code,content)
  if code==200 then--判断网站状态
    doc = Jsoup.parse(content)--使用jsoup解析网页
    print(doc.title())--使用jsoup方法获取到网页标题
  else
    print('无法访问')
  end
end)

String基础概述

爬虫,这是一个大学问,厉害的爬虫可以用同一个网站的相同数据,
做出更突出的效果,可以将杂乱无章的数据,处理成系统的,分类好的数据来进行复用。
当然,这些都是厉害的,工程量十分大的,而我们只需要简单的处理页面数据就可以了。
首先熟悉下Lua的字符串操作
字符串由一对双引号或单引号来表示。

string1 = "this is string1"
string2 = 'this is string2'

在对一个数字字符串上进行算术操作时,Lua 会尝试将这个数字字符串转成一个数字,字符串连接使用的是 ..如:

print("a" .. 'b')
--输出(ab)
print(157 .. 428)
--输出(157428)

使用 # 来计算字符串的长度,放在字符串前面,如下实例:

len = "www.androlua.com"
print(#len)
--输出(16)

字符串的截取操作:
strings="左中右"

--取字符串左边
=strings:match("(.+)中")


--取字符串中间
=strings:match("左(.-)右")


--取字符串右边
=strings:match("中(.+)")

--替换
string.gsub(原字符串,替换的字符串,替换成的字符串)

--匹配子串位置
起始位置,结束位置=string.find(字符串,子串)


--按位置捕获字符串
string.sub(字符串,子串起始位置,子串结束位置)

需要一提得是,Lua中使用\来进行转义,例如:
\n 换行(LF) ,将当前位置移到下一行开头
\r 回车(CR) ,将当前位置移到本行开头
\t 水平制表(HT) (跳到下一个TAB位置)
\\ 代表一个反斜线字符\
\' 代表一个单引号(撇号)字符
\" 代表一个双引号字符
\0 空字符(NULL)

Lua中字符串操作api
string.upper(argument) 字符串全部转为大写字母。
string.lower(argument) 字符串全部转为小写字母。
string.gsub(mainString,findString,replaceString,num) 在字符串中替换,mainString为要替换的字符串findString 为被替换的字符,replaceString 要替换的字符,num 替换次数(可以忽略,则全部替换)
string.find (str, substr, [init, [end]]) 在一个指定的目标字符串中搜索指定的内容(第三个参数为索引),返回其具体位置。不存在则返回 nil
string.reverse(arg) 字符串反转
string.format(...) 返回一个类似printf的格式化字符串
string.char(arg) 和 string.byte(arg[,int]) char 将整型数字转成字符并连接, byte 转换字符为整数值(可以指定某个字符,默认第一个字符)。
string.len(arg) 计算字符串长度。
string.rep(string, n) 返回字符串string的n个拷贝
.. 链接两个字符串
string.gmatch(str, pattern) 回一个迭代器函数,每一次调用这个函数,返回一个在字符串 str 找到的下一个符合 pattern 描述的子串。如果参数 pattern 描述的字符串没有找到,迭代函数返回nil。
string.match(str, pattern, init) string.match()只寻找源字串str中的第一个配对. 参数init可选, 指定搜寻过程的起点, 默认为1。 
在成功配对时, 函数将返回配对表达式中的所有捕获结果; 如果没有设置捕获标记, 则返回整个配对字符串. 当没有成功的配对时, 返回nil。

其中string.format()有以下转义码:
%c - 接受一个数字, 并将其转化为ASCII码表中对应的字符
%d, %i - 接受一个数字并将其转化为有符号的整数格式
%o - 接受一个数字并将其转化为八进制数格式
%u - 接受一个数字并将其转化为无符号整数格式
%x - 接受一个数字并将其转化为十六进制数格式, 使用小写字母
%X - 接受一个数字并将其转化为十六进制数格式, 使用大写字母
%e - 接受一个数字并将其转化为科学记数法格式, 使用小写字母e
%E - 接受一个数字并将其转化为科学记数法格式, 使用大写字母E
%f - 接受一个数字并将其转化为浮点数格式
%g(%G) - 接受一个数字并将其转化为%e(%E, 对应%G)及%f中较短的一种格式
%q - 接受一个字符串并将其转化为可安全被Lua编译器读入的格式
%s - 接受一个字符串并按照给定的参数格式化该字符串

Lua的匹配模式
.(点): 与任何字符配对
%a: 与任何字母配对
%c: 与任何控制符配对(例如\n)
%d: 与任何数字配对
%l: 与任何小写字母配对
%p: 与任何标点(punctuation)配对
%s: 与空白字符配对
%u: 与任何大写字母配对
%w: 与任何字母/数字配对
%x: 与任何十六进制数配对
%z: 与任何代表0的字符配对
%x(此处x是非字母非数字字符): 与字符x配对. 主要用来处理表达式中有功能的字符(^$()%.[]*+-?)的配对问题, 例如%%%配对
[数个字符类]: 与任何[]中包含的字符类配对. 例如[%w_]与任何字母/数字, 或下划线符号(_)配对
[^数个字符类]: 与任何不包含在[]中的字符类配对. 例如[^%s]与任何非空白字符配对
单个字符类匹配该类别中任意单个字符;
单个字符类跟一个 '*', 将匹配零或多个该类的字符。 这个条目总是匹配尽可能长的串;
单个字符类跟一个 '+', 将匹配一或更多个该类的字符。 这个条目总是匹配尽可能长的串;
单个字符类跟一个 '-', 将匹配零或更多个该类的字符。 和 '*' 不同, 这个条目总是匹配尽可能短的串;
单个字符类跟一个 '?', 将匹配零或一个该类的字符。 只要有可能,它会匹配一个;
%n, 这里的 n 可以从 19; 这个条目匹配一个等于 n 号捕获物(后面有描述)的子串。
%bxy, 这里的 xy 是两个明确的字符; 这个条目匹配以 x 开始 y 结束, 且其中 xy 保持 平衡 的字符串。 意思是,如果从左到右读这个字符串,对每次读到一个 x+1 ,读到一个 y-1, 最终结束处的那个 y 是第一个记数到 0y。 举个例子,条目 %b() 可以匹配到括号平衡的表达式。
%f[set], 指 边境模式; 这个条目会匹配到一个位于 set 内某个字符之前的一个空串, 且这个位置的前一个字符不属于 set 。 集合 set 的含义如前面所述。 匹配出的那个空串之开始和结束点的计算就看成该处有个字符 '\0' 一样。

常用正则(Lua中需要将\换成%):
非负整数:^\d+$
正整数:^[0-9]*[1-9][0-9]*$
非正整数:^((-\d+)|(0+))$
负整数:^-[0-9]*[1-9][0-9]*$
整数:^-?\d+$
非负浮点数:^\d+(\.\d+)?$
正浮点数 : ^((0-9)+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)$
非正浮点数:^((-\d+\.\d+)?)|(0+(\.0+)?))$
负浮点数:^(-((正浮点数正则式)))$
英文字符串:^[A-Za-z]+$
英文大写串:^[A-Z]+$
英文小写串:^[a-z]+$
英文字符数字串:^[A-Za-z0-9]+$
英数字加下划线串:^\w+$
E-mail地址^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$
URL^[a-zA-Z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\s*)?$ 
或:^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$
邮政编码:^[1-9]\d{5}$
中文:^[\u0391-\uFFE5]+$
电话号码:^((\(\d{2,3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$
手机号码:^((\(\d{2,3}\))|(\d{3}\-))?13\d{9}$
双字节字符(包括汉字在内):^\x00-\xff
匹配首尾空格:(^\s*)|(\s*$)(像vbscript那样的trim函数)
匹配HTML标记:<(.*)>.*<\/\1>|<(.*) \/>
匹配空行:\n[\s| ]*\r
提取信息中的网络链接:(h|H)(r|R)(e|E)(f|F) *= *('|")?(\w|\\|\/|\.)+('|"| *|>)?
提取信息中的邮件地址:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
提取信息中的图片链接:(s|S)(r|R)(c|C) *= *('|")?(\w|\\|\/|\.)+('|"| *|>)?
提取信息中的IP地址:(\d+)\.(\d+)\.(\d+)\.(\d+)
提取信息中的中国手机号码:(86)*0*13\d{9}
提取信息中的中国固定电话号码:(\(\d{3,4}\)|\d{3,4}-|\s)?\d{8}
提取信息中的中国电话号码(包括移动和固定电话):(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}
提取信息中的中国邮政编码:[1-9]{1}(\d+){5}
提取信息中的浮点数(即小数):(-?\d*)\.?\d+
提取信息中的任何数字 :(-?\d*)(\.\d+)? 
IP:(\d+)\.(\d+)\.(\d+)\.(\d+)
电话区号:/^0\d{2,3}$/
腾讯QQ号:^[1-9]*[1-9][0-9]*$
帐号(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
中文、英文、数字及下划线:^[\u4e00-\u9fa5_a-zA-Z0-9]+$
匹配中文字符的正则表达式: [\u4e00-\u9fa5]
匹配双字节字符(包括汉字在内):[^\x00-\xff]
匹配空行的正则表达式:\n[\s| ]*\r
匹配HTML标记的正则表达式:/<(.*)>.*<\/\1>|<(.*) \/>/
sql语句^(select|drop|delete|create|update|insert).*$
匹配首尾空格的正则表达式:(^\s*)|(\s*$)
匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

抓取aj ax数据实战

--首先创建一个布局,为教程提供良好的可视化
--导入cjson包
import'cjson'
shamrock=
{
  LinearLayout;--线性布局
  Orientation='vertical';--布局方向
  layout_width='fill';--布局宽度
  layout_height='fill';--布局高度
  background='#ffffff';--布局背景颜色(或者图片路径)
  {
    ScrollView;--纵向滚动
    layout_width='fill';--宽
    layout_height='fill';--高
    {
      LinearLayout;--线性布局
      Orientation='vertical';--布局方向
      layout_width='fill';--布局宽度
      layout_height='fill';--布局高度
      background='';--布局背景颜色(或者图片路径)
      gravity='center';--设置居中
      {
        TextView;--文本控件
        id='文本';--绑定ID
        layout_margin='5%w';--布局外边距
        layout_width='wrap';--文本宽度
        layout_height='wrap';--文本高度
        Gravity='center';--重力属性
        textColor='#000000';--文本颜色
        text='爬取内容中';--显示的文本
        textSize='18sp';--文本大小
      };
    };
  };
};
activity.setContentView(loadlayout(shamrock))--将布局添加至窗口
--设置需要爬取的网站,可以随意更换
--这个链接是百度热搜的接口
url = 'https://www.anyknew.com/api/v1/sites/baidu'

--使用Http访问该网站,获取网页源码
Http.get(url,nil,'utf8',nil,function(状态码,网页源码)
  --判断返回状态码,确定网站的正常运行
  if 状态码 ==200 then
    --使用cjson库将获取到的json数据table化
    数据 = cjson.decode(网页源码)
    --取出需要的数据
    数据列表 = 数据.data.site.subs[1].items
    --定义一个空文本用于显示数据
    标题 = ''
    --遍历爬取到的数据
    for k,v in pairs(数据列表) do
      --将数据逐个取出,累加进字符串进行显示
      标题 =标题.. string.format('标题%d:%s',k,v.title)..'\n'
    end
    --设置文本显示,显示爬取效果
    文本.setText(标题)
  else
    文本.setText('获取内容失败')
  end
end)

爬取论坛实战

--创建一个布局,为教程提供良好的可视化
--做一个爬虫,前期的分析网页工作需要做好
--明确目标,明白只需要哪些数据,以及如何处理数据
shamrock=
{
  LinearLayout;--线性布局
  Orientation='vertical';--布局方向
  layout_width='fill';--布局宽度
  layout_height='fill';--布局高度
  background='#ffffff';--布局背景颜色(或者图片路径)
  {
    ScrollView;--纵向滚动
    layout_width='fill';--宽
    layout_height='fill';--高
    {
      TextView;--文本控件
      id='显示文本';--绑定ID
      layout_width='fill';--文本宽度
      layout_height='fill';--文本高度
      Gravity='center';--重力属性
      textColor='#000000';--文本颜色
      text='爬取中...';--显示的文本
      textSize='16sp';--文本大小
    };
  };
};
activity.setContentView(loadlayout(shamrock))--将布局添加至窗口

url="论坛网址"--论坛网址
--HTTP请求网页源码
Http.get(url,nil,'utf8',nil,function(状态码,网页源码)
  --判断网站的访问情况
  if 状态码 == 200 then
    --获取到帖子标题数据
    帖子标题迭代器 = 网页源码:gmatch('<a href="thread.-htm">(.-)</a>')
    --创建帖子标题表
    帖子标题 = {}
    --遍历帖子标题数据,将数据存入表
    for i in 帖子标题迭代器 do
      table.insert(帖子标题,i)
    end
    --获取帖子链接数据
    帖子链接迭代器 = 网页源码:gmatch('<a href="(thread.-htm)">.-</a>')
    --创建帖子链接表
    帖子链接 = {}
    --遍历帖子链接数据,将其存入表
    for i in 帖子链接迭代器 do
      table.insert(帖子链接,i)
    end
    --定义一个空字符串,后面将数据展示到布局
    爬取内容 = ''
    --遍历所有数据
    for i=1,#帖子标题 do
      --累加字符串,使显示效果良好
      爬取内容 = 爬取内容..string.format('帖子标题:%s\n帖子链接:论坛网址/%s\n',帖子标题[i],帖子链接[i])
    end
    --将数据显示
    显示文本.setText(爬取内容)
  else
    显示文本.setText('网站无法访问')
  end
end)

爬取ip与地理位置实战

--创建布局,显示爬取效果
shamrock=
--布局请写在这里
{
  LinearLayout;--线性布局
  Orientation='vertical';--布局方向
  layout_width='fill';--布局宽度
  layout_height='fill';--布局高度
  background='#ffffff';--布局背景颜色(或者图片路径)
  Gravity="center";--设置居中
  {
    TextView;--文本控件
    id="显示文本";--绑定id
    layout_width='wrap';--文本宽度
    layout_height='wrap';--文本高度
    Gravity='center';--重力属性
    textColor='#000000';--文本颜色
    text='正在查询中';--显示的文本
    textSize='16sp';--文本大小
  };
};
activity.setContentView(loadlayout(shamrock))--将布局添加至窗口
url="https://ip.cn/"--设置爬取链接
--设置爬取请求头
header={
  ["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",
}
--请求网页源码
Http.get(url,nil,"utf8",header,function(状态码,网页源码)
  --判断网站状态
  if 状态码==200 then
    --根据网页,分析出筛选规则
    ip地址=网页源码:match('您现在的 IP:<code>(.-)</code>')
    地理位置=网页源码:match('所在地理位置:<code>(.-)</code>')
    --设置文本进行显示
    文本=string.format("您现在的 IP:%s\n您所在地理位置:%s",ip地址,地理位置)
    显示文本.setText(文本)
  else
    显示文本.setText("网站无法访问")
  end
end)

爬取必应壁纸实战

--创建布局,用于显示爬取的图片
--由于考虑到学习成本的问题,所以我没有用适配器写图片展示
--用了较简单的循环添加布局
--提示:图片爬虫显示较吃性能,所以本教程可能导致程序闪退。
--由于网站和循环布局原因,所以爬取会比较慢,请耐心等待。
shamrock=
{
  LinearLayout;--线性布局
  Orientation='vertical';--布局方向
  layout_width='fill';--布局宽度
  layout_height='fill';--布局高度
  background='#ffffff';--布局背景颜色(或者图片路径)
  {
    ScrollView;--纵向滚动
    layout_width='fill';--宽
    layout_height='fill';--高
    {
      LinearLayout;--线性布局
      id="壁纸";--绑定ID
      Orientation='vertical';--布局方向
      layout_width='fill';--布局宽度
      layout_height='fill';--布局高度
      background='';--布局背景颜色(或者图片路径)
    };
  };
};
activity.setContentView(loadlayout(shamrock))--将布局添加至窗口
--创建等待窗口提示
dialog3 = ProgressDialog.show(this, "提示", "正在爬取中",false, false)
--将等待窗口美化(设置圆角)
import "android.graphics.drawable.GradientDrawable"
local radiu=25
dialog3.getWindow().setBackgroundDrawable(GradientDrawable().setCornerRadii({radiu,radiu,radiu,radiu,radiu,radiu,radiu,radiu}).setColor(0xffffffff))
--定义爬取链接
url="https://bing.ioliu.cn/"
--Http请求源码
Http.get(url,nil,"utf8",nil,function(状态码,网页源码)
  --等待窗口隐藏
  dialog3.hide()
  --判断状态码,确认网站可访问
  if 状态码==200 then
    --筛选图片链接数据
    图片链接迭代器=网页源码:gmatch('src="(https://h1.ioliu.cn/bing/.-jpg)"')
    --创建图片链接表,用于存储抓取到的图片链接
    图片链接={}
    --迭代抓取到的图片链接
    for i in 图片链接迭代器 do
      --将图片链接存入表中
      table.insert(图片链接,i)
    end
    --遍历图片链接表
    for k,v in pairs(图片链接) do
      --创建布局,用于显示每一张图片
      单张壁纸={
        LinearLayout;--线性布局
        Orientation='vertical';--布局方向
        layout_width='fill';--布局宽度
        layout_height='50%w';--布局高度
        background='';--布局背景颜色(或者图片路径)
        Gravity="center";
        {
          CardView;--卡片控件
          layout_margin='10';--卡片边距
          layout_gravity='center';--重力属性
          Elevation='0';--阴影属性
          layout_width='fill';--卡片宽度
          layout_height='fill';--卡片高度
          radius='20';--卡片圆角
          CardBackgroundColor='';--卡片背景颜色
          {
            ImageView;--图片控件
            id="图片";
            src="";--图片路径
            layout_width='fill';--图片宽度
            layout_height='fill';--图片高度
            layout_gravity='center';--重力属性
          };
        };
      };
      --将布局添加至主布局
      壁纸.addView(loadlayout(单张壁纸))
      --设置在线图片显示
      图片.setImageBitmap(LuaBitmap.getHttpBitmap(v))
    end
  else
    print("无法访问")
  end
end)

爬取网页分类实战

--首先创建一个布局,为教程提供良好的可视化
shamrock=
{
  LinearLayout;--线性布局
  Orientation='vertical';--布局方向
  layout_width='fill';--布局宽度
  layout_height='fill';--布局高度
  background='#ffffff';--布局背景颜色(或者图片路径)
  Gravity='center';--设置居中
  {
    TextView;--文本控件
    id='文本';--绑定ID
    layout_margin='5%w';--布局外边距
    layout_width='wrap';--文本宽度
    layout_height='wrap';--文本高度
    Gravity='center';--重力属性
    textColor='#000000';--文本颜色
    text='爬取内容中';--显示的文本
    textSize='18sp';--文本大小
  };
};
activity.setContentView(loadlayout(shamrock))
--设置需要爬取的网站,可以随意更换
url = 'http://dh.hfybbs.vip/cn/index.html'

--使用Http访问该网站,获取网页源码
Http.get(url,nil,'utf8',nil,function(状态码,网页源码)
  --判断返回状态码,确定网站的正常运行
  if 状态码 ==200 then
    --分析网页源码,使用gmatch筛选出所有符合条件的内容,gamtch返回的是迭代器
    网页框架 = 网页源码:gmatch('<ul.->(.-)</ul>')
    --定义一个空表,用来存储获取的网页数据
    网页框架表 = {}
    --将gmatch函数返回的迭代器进行遍历,取出数据,然后存进网页框架表表
    for i in 网页框架 do
      --判断是否可以筛选需要爬取的内容,可以才存放进网页框架表
      if i:match('<span.->(.-)</span>') then
        table.insert(网页框架表,i:match('<span.->(.-)</span>'))
      end
    end
    --定义一个空字符串,用于显示效果
    显示文本 = ''
    --遍历表,将爬取到的数据取出
    for k,v in pairs(网页框架表) do
      --累加文本,将表内数据形成可视化
      显示文本=显示文本..'\n'..string.format('分类%d:%s',k,v)
    end
    --设置文本显示,显示爬取效果
    文本.setText(显示文本)
  else
    文本.setText('获取内容失败')
  end
end)

翻页爬取论坛实战

--创建布局,用于显示爬取效果
--翻页爬取的思路是:
--获取网页的翻页所有链接,然后循环请求爬取
shamrock=
{
  LinearLayout;--线性布局
  Orientation='vertical';--布局方向
  layout_width='fill';--布局宽度
  layout_height='fill';--布局高度
  background='#ffffff';--布局背景颜色(或者图片路径)
  {
    ScrollView;--纵向滚动
    layout_width='fill';--宽
    layout_height='fill';--高
    {
      TextView;--文本控件
      id='显示文本';--绑定ID
      layout_width='fill';--文本宽度
      layout_height='fill';--文本高度
      Gravity='center';--重力属性
      textColor='#000000';--文本颜色
      text='正在爬取中';--显示的文本
      textSize='16sp';--文本大小
    };
  };
};
activity.setContentView(loadlayout(shamrock))--将布局添加至窗口
--定义爬取翻页链接的网址
url = 'https://yum5.cn'
--请求链接
Http.get(url,nil,'utf8',nil,function(状态码,网页源码)
  --判断网站状态
  if 状态码 == 200 then
    --获取所有页数链接
    页数迭代器 = 网页源码:gmatch('<a href="index.-htm" class="page.-">(.-)</a>')
    --新建表,存放爬取数据
    页数={}
    --迭代页数迭代器,将数据存入表
    for i in 页数迭代器 do
      --这里筛选数字,因为部分数据是杂乱的
      if i:find('%d') then
        table.insert(页数,i:match('(%d.*)'))
      end
    end
    --获取到页数
    末尾页数 = tointeger(页数[#页数])
    --新建表,存放帖子标题
    帖子标题 = {}
    --循环页数
    for i=1,末尾页数 do
      --将页数拼接进链接
      url = 'https://yum5.cn/index-'..i..'.htm'
      --请求网页
      Http.get(url,nil,'utf8',nil,function(状态码,网页源码)
        --判断网站状态
        if 状态码 == 200 then
          --显示当前爬取页数
          table.insert(帖子标题,''..i..'页:\n\n')
          --爬取帖子标题信息
          帖子标题迭代器 = 网页源码:gmatch('<a href="thread.-htm">(.-)</a>')
          --迭代帖子标题迭代器,将数据存入表
          for v in 帖子标题迭代器 do
            table.insert(帖子标题,v)
          end
          --定义空文本,用于显示数据
          文本=''
          --遍历表,取出数据
          for k,v in pairs(帖子标题) do
            --将数据文本累加
            文本=文本..k..''..v..'\n'
          end
          --展示数据
          显示文本.setText(文本)
        else
          显示文本.setText('无法访问')
        end
      end)
    end
  else
    显示文本.setText('无法访问')
  end
end)

获取网页标题实战

--首先创建一个布局,为教程提供良好的可视化
shamrock=
{
  LinearLayout;--线性布局
  Orientation='vertical';--布局方向
  layout_width='fill';--布局宽度
  layout_height='fill';--布局高度
  background='#ffffff';--布局背景颜色(或者图片路径)
  Gravity='center';--设置居中
  {
    TextView;--文本控件
    id='文本';--绑定ID
    layout_margin='5%w';--布局外边距
    layout_width='wrap';--文本宽度
    layout_height='wrap';--文本高度
    Gravity='center';--重力属性
    textColor='#000000';--文本颜色
    text='查询网站标题中';--显示的文本
    textSize='18sp';--文本大小
  };
};
activity.setContentView(loadlayout(shamrock))
--设置需要爬取的网站,可以随意更换
url = 'http://dh.hfybbs.vip'

--使用Http访问该网站,获取网页源码
Http.get(url,nil,'utf8',nil,function(状态码,网页源码)
  --判断返回状态码,确定网站的正常运行
  if 状态码 ==200 then
    --分析网页结构,发现标题在title标签内,所以进行截取
    title = 网页源码:match('<title>(.-)</title>')
    --将截取到的标题设置至文本显示
    文本.setText(title)
  else
    文本.setText('该网站无法访问')
  end
end)

讯飞远程更新实战

--[[
很多同学似乎还不会远程更新,其实所谓讯飞远程更新也就是爬虫的
一种运用方式,结合前面所学和查看下面的链接的网页结构
你就能写出属于你的远程更新。
]]
SorrowClover=--随便写的一个布局,没有任何意义。
{
  LinearLayout;--线性布局
  Orientation='vertical';--布局方向
  layout_width='fill';--布局宽度
  layout_height='fill';--布局高度
  background='#ffffff';--布局背景颜色(或图片路径)
};
activity.setContentView(loadlayout(SorrowClover))--显示布局
--定义一个你的讯飞远程链接
--可以复制到浏览器看看网页结构
url="讯飞链接"
--使用http获取网页源码
Http.get(url,nil,"utf8",nil,function(code,content)
  --判断网页状态 
  if code==200 then
    --获取当前应用包名
    包名=activity.getPackageName()
    --利用包名获取到当前版本号
    当前版本=tonumber(activity.getPackageManager().getPackageInfo(包名, 0).versionName)
    --获取远程更新版本号
    更新版本=tonumber(content:match("【版本】(.-)【版本】"))
    --比较版本号
    if 更新版本 > 当前版本 then
      --制作对话框,显示更新提示
      更新说明=content:match("【更新说明】(.-)【更新说明】")
      更新链接=content:match("【更新链接】(.-)【更新链接】")
      AlertDialog.Builder(this)
      .setTitle("你有新版本更新")
      .setMessage(更新说明)
      .setPositiveButton("更新",{onClick=function(v)
          import "android.content.Intent"
          import "android.net.Uri"
          url=更新链接
          viewIntent = Intent("android.intent.action.VIEW",Uri.parse(url))
          activity.startActivity(viewIntent)
        end})
      .setNegativeButton("取消",nil)
      .show()
      --判断正版软件
    elseif 更新版本 < 当前版本 then
      更新链接=content:match("【更新链接】(.-)【更新链接】")
      AlertDialog.Builder(this)
      .setTitle("公告")
      .setMessage("软件已出新版本,请更新后使用")
      .setPositiveButton("下载更新",{onClick=function(v)
          import "android.content.Intent"
          import "android.net.Uri"
          url=更新链接
          viewIntent = Intent("android.intent.action.VIEW",Uri.parse(url))
          activity.startActivity(viewIntent)
        end})
      .setNegativeButton("取消",nil)
      .show()
    else
      print("已是最新版本")
    end
  else
    print("检测更新失败")
  end
end)