日常求赞,感谢老板。
欢迎关注公众号:其实是白羊。干货持续更新中......
我扶了下腰,不多不多。。。
之前一直听爬虫爬虫的,咱也不知道是啥,但都是用Python,咱也不会啊,就回个Python。后来了解到,简单的爬虫其实就是解析页面嘛,提取自己需要的资源(嘿嘿)。再后来在工作中接到了个需求里需要解析html,度娘了一下了解到了Jsoup这个类库。需求做完了,就这么结束?怎么可能,当然是做一些有趣的事情啦。
<dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.12.1</version> </dependency>
String html = "<html><head><title>First parse</title></head>"
Document doc = Jsoup.parse(html);//通过Document可以获取里面的任何值 //html必须是html哦不能是片段 ```
String html = "<div><p>Lorem ipsum.</p>"; Document doc = Jsoup.parseBodyFragment(html);//解析html片段,封装成完整的html Element body = doc.body();//获取其中的body片段
重头戏来了
Connection connect = Jsoup.connect("http://example.com/");//获取Connection Document document = connect.get();//Connection可以设置常规网络请求都可以设置的一些项,如: //connect.header("Accept-Encoding", "gzip, deflate, sdch");//设置请求头(注意要在调用get或post方法之前设置) //connect.cookie("auth", "token");//设置cookie //connect.timeout(3000);//设置响应时间等 //这是爬取资源重要的一步哦 String title = document.title();
下面是对于Document解析想要的值的方法:
getElementById(String id)
getElementsByTag(String tag)
getElementsByClass(String className)
getElementsByAttribute(String key)
(and related methods) siblingElements()
, firstElementSibling()
, lastElementSibling()
; nextElementSibling()
, previousElementSibling()
parent()
, children()
, child(int index)
attr(String key)
获取属性 attr(String key, String value)
设置属性 attributes()
获取所有属性 id()
, className()
and classNames()
text()
获取文本内容 text(String value)
设置文本内容 html()
获取元素内HTML html(String value)
设置元素内的HTML内容 outerHtml()
获取元素外HTML内容 data()
获取数据内容(例如:script和style标签) tag()
and tagName()
append(String html)
, prepend(String html)
appendText(String text)
, prependText(String text)
appendElement(String tagName)
, prependElement(String tagName)
html(String value)
以上内容参考自: 更多方法使用
了解了类库,我们就可以着手开始实践解析了:
先分析下网站上的资源都在哪?
String url = "https://www.mzitu.com/page/1/"; Connection connect = Jsoup.connect(url); Document document = connect.get();
我们可以看到得到的document中我们想要的资源是这样存在的:
<img class="lazy" src="https://www.mzitu.com/static/pc/img/lazy.png" data-original="https://i.mmzztt.com/thumb/2020/04/226719_236.jpg" alt="气质少妇任莹樱人体艺术照 丰满木瓜奶完美呈现" width="236" height="354">
ok,那么我们要的是img标签下data-original属性的值和alt属性的值。
解析获取
//在上面代码基础上 Elements imgs = document.getElementsByTag("img");//获取全部img for (Element img : imgs) { String src = img.attr("data-original"); String alt = img.attr("alt"); log.info("第{}页:alt->{};src->{}", i, alt, src); }
到这就ok啦,alt是图片的描述可以将它作为图片的名字,src就是图片的请求地址,你可以直接将它存在数据库里,或者直接保存到本地磁盘(具体做法后面会写)
接这样结束了? 怎么可能这可是有243页哎(再深的咱们就不挖了)。看下不同页的url可以写成:
for (int i = 1; i <= 243; i++) { String url = "https://www.mzitu.com/page/"+ i +"/"; //获取+解析步骤省略参考上面步骤 }
执行下来你会发现,保存下来的图片后面很多都是,这个:
不同的url请求下来的却是同一张图片,单独把url拿出来请求下,果然是请求了只有重定向到了这个图片。嗯虽然我不知道他具体是怎么做的,但我猜应该是从什么地方判断出我不是正常请求,或者是判断同一个ip请求的频率,之后就把我的每次请求都重定向到了这个图片导致我有url却看不到我想要的东西,可恶。
既然他能判断出我不是正常请求,那我们就看看正常请求和直接访问请求有什么区别吧:
正常浏览:
url直接请求:
发现什么没,请求头里少了Referer,找到原因了那就试一哈。
综上在使用Jsoup时获取网页和根据url请求资源时加上一定的请求头:
//简单写下意思(文末会赋源码) for (int i = 1; i <= 243; i++) { String url = "https://www.mzitu.com/page/" + i + "/"; Connection connect = Jsoup.connect(url); connect.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); connect.header("Accept-Encoding", "gzip, deflate, sdch"); connect.header("Accept-Language", "zh-CN,zh;q=0.8"); connect.header("Sec-Fetch-Dest", "document"); connect.header("Upgrade-Insecure-Requests", "1"); connect.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"); connect.header("Referer", refererPageInit); Document document = connect.get(); //todo 解析出需要的资源 refererPageInit = "https://www.mzitu.com/page/" + i + "/"; }
至此你就能获取这两百多页(六七千多张图片)啦。
各位绅士先放下手中的针线活, 源码在此 ,觉得写的还可以的给点个赞,也可以评论浏览讨论下。
欢迎star