零、爬虫个人理解
获取想要的数据。找到网站,访问网址获取到粗数据,使用技术手段解析出我们想要的数据和下层的请求的网址,然后再来一次直到没有下层。如:省->市->县->镇->村
一、导入依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.2</version>
</dependency>
二、编写代码
import com.sun.istack.internal.NotNull;
import lombok.Data;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.util.ArrayList;
import java.util.List;
public class AreaUtil {
public static final String baseUrl = "http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2020/";
/**
* 爬取国家统计局2020的区域数据
*/
public static void crawlingAreaByNationalBureauOfStatistics(String url,int lv,String code,@NotNull List<Area> list) {
try {
Thread.sleep(500L);
Document doc = Jsoup.connect(url).maxBodySize(0).get();
System.out.println(url);
Elements tdElements = doc.select("td");
switch (lv){
case 1:{
Elements aElements = tdElements.select("a");
for (Element item : aElements) {
if (item.text().indexOf("京ICP备") == -1) {
Area area = new Area();
area.setCode(item.attributes().get("href").replaceAll(".html",""));
area.setName(item.text());
area.setParCode(code);
list.add(area);
String cUrl = url.substring(0,url.lastIndexOf("/")+1) + item.attributes().get("href");
crawlingAreaByNationalBureauOfStatistics(cUrl,2,area.getCode(),list);
}
}
};break;
case 2:{
int index = 0;
for(Element item : tdElements){
if(item.parent().attributes().get("class").equals("citytr")){
if(index%2==0){
Area area = new Area();
area.setCode(item.select("a").get(0).text());
area.setParCode(code);
list.add(area);
}
if(index%2==1){
list.get(list.size()-1).setName(item.select("a").get(0).text());
String cUrl = url.substring(0,url.lastIndexOf("/")+1) + item.select("a").get(0).attributes().get("href");
crawlingAreaByNationalBureauOfStatistics(cUrl,3,list.get(list.size()-1).getCode(),list);
}
index++;
}
}
};break;
case 3:{
int index = 0;
for(Element item : tdElements){
if(item.parent().attributes().get("class").equals("countytr")){
if(index%2==0){
Area area = new Area();
if(index ==0){
area.setCode(item.text());
}else{
area.setCode(item.select("a").get(0).text());
}
area.setParCode(code);
list.add(area);
}
if(index%2==1){
if(index == 1){
list.get(list.size()-1).setName(item.text());
}else {
list.get(list.size()-1).setName(item.select("a").get(0).text());
String cUrl = url.substring(0,url.lastIndexOf("/")+1) + item.select("a").get(0).attributes().get("href");
crawlingAreaByNationalBureauOfStatistics(cUrl,4,list.get(list.size()-1).getCode(),list);
}
}
index++;
}
}
};break;
case 4:{
int index = 0;
for(Element item : tdElements){
if(item.parent().attributes().get("class").equals("towntr")){
if(index%2==0){
Area area = new Area();
area.setCode(item.select("a").get(0).text());
area.setParCode(code);
list.add(area);
}
if(index%2==1){
list.get(list.size()-1).setName(item.select("a").get(0).text());
String cUrl = url.substring(0,url.lastIndexOf("/")+1) + item.select("a").get(0).attributes().get("href");
crawlingAreaByNationalBureauOfStatistics(cUrl,5,list.get(list.size()-1).getCode(),list);
}
index++;
}
}
};break;
case 5:{
int index = 0;
for(Element item : tdElements){
if(item.parent().attributes().get("class").equals("villagetr")){
if(index%3==0){
Area area = new Area();
area.setCode(item.text());
area.setParCode(code);
list.add(area);
}
if(index%3==1){
list.get(list.size()-1).setCode2(item.text());
}
if(index%3==2){
list.get(list.size()-1).setName(item.text());
}
index++;
}
}
};break;
}
}catch ( Exception e){
System.out.println(e.getMessage());
}
}
public static void main(String[] args) {
List<Area> list = new ArrayList<>();
crawlingAreaByNationalBureauOfStatistics(baseUrl,3,null,list);
list.forEach(System.out::println);
}
}
/**
* 数据结构
*/
@Data
class Area {
//编码
private String code;
//编码
private String code2;
//名称
private String name;
//父级编码
private String parCode;
}
三、结果
四、注意
本来是用多线程去做的,后面发现程序请求不到了数据了,该站点有反爬虫手段,去掉多线程后发现有时也是请求不到,后面又加了Thread.sleep(500L);这样请求的慢会好一点。