Jsoup获取全国地区数据(省市县镇村)

参考自:Jsoup获取全国地区数据(省市县镇村)

以下是我的代码:
需要优化的是最好采用批量导入,就是放入list里面一次性导入,一条条导入数据库的话会频繁获取数据库sqlsession,导入速度就很慢。

/**
 * 全国省市县镇村数据爬取
 * @version 1.0.0
 */   
public class JsoupTest extends BaseJunitTest
{
    @Autowired
    public  CityDetailService service;

    public static Map cssMap = new HashMap();
    public static BufferedWriter bufferedWriter = null;

    static
    {
        cssMap.put(1, "provincetr");// 省
        cssMap.put(2, "citytr");// 市
        cssMap.put(3, "countytr");// 县
        cssMap.put(4, "towntr");// 镇
        //我不需要村
//        cssMap.put(5, "villagetr");// 村
    }

    @Test
    public void test() throws IOException
    {
        int level = 1;

        initFile();

        // 获取全国各个省级信息
        Document connect = connect("http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/");
        Elements rowProvince = connect.select("tr." + cssMap.get(level));
        for (Element provinceElement : rowProvince)// 遍历每一行的省份城市
        {
            Elements select = provinceElement.select("a");
            for (Element province : select)// 每一个省份(四川省)
            {
            //我是存到数据库,不要存到txt里面
//              printInfo(province, level);
                //省份,parentId为0
                String name = province.select("a").first().text();
                int id = insertCity(0, name, level);
                parseNextLevel(id,province, level);


            }
        }
        System.out.println("导入成功!");
        closeStream();
    }

    public  int insertCity(Integer parentId,String name, Integer level) {
        CityDetail city = new CityDetail();
        city.setParentId(parentId);
        city.setName(name);
        city.setLevel(level);
        service.insert(city);
        return city.getId();
    }

    public  void initFile()
    {
        try
        {
            bufferedWriter = new BufferedWriter(new FileWriter(new File("d:\\CityInfo.txt"), true));
        } catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    public  void closeStream()
    {
        if (bufferedWriter != null)
        {
            try
            {
                bufferedWriter.close();
            } catch (IOException e)
            {
                e.printStackTrace();
            }
            bufferedWriter = null;
        }
    }

    public  void parseNextLevel(int id,Element parentElement, int level) throws IOException
    {
        try
        {
            Thread.sleep(50);//睡眠一下,否则可能出现各种错误状态码
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }

        Document doc = connect(parentElement.attr("abs:href"));
        if (doc != null)
        {
            Elements newsHeadlines = doc.select("tr." + cssMap.get(level+1));//
            // 获取表格的一行数据
            for (Element element : newsHeadlines)
            {
//                printInfo(element, level+1);
                String name = element.select("td").last().text();
                int parentId = insertCity(id, name, level+1);
                Elements select = element.select("a");// 在递归调用的时候,这里是判断是否是村一级的数据,村一级的数据没有a标签
                if (select.size() != 0)
                {
                    parseNextLevel(parentId,select.last(), level + 1);
                }
            }
        }
    }

    /**
     * 写一行数据到数据文件中去
     * @param element 爬取到的数据元素
     * @param level 城市级别
     */
    public  void printInfo(Element element, int level)
    {
        try
        {
            if(element.select("td").size()>0) {
                bufferedWriter.write(element.select("td").last().text() + "{" + level + "}["
                        + element.select("td").first().text() + "]");
            }else {
                bufferedWriter.write(element.select("a").first().text() + "{" + level + "}");
            }

            bufferedWriter.newLine();
            bufferedWriter.flush();
        } catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    public  Document connect(String url)
    {
        if (url == null || url.isEmpty())
        {
            throw new IllegalArgumentException("The input url('" + url + "') is invalid!");
        }
        try
        {
            return Jsoup.connect(url).timeout(100 * 1000).get();
        } catch (IOException e)
        {
            e.printStackTrace();
            return null;
        }
    }
}

这里单元测试要注意的是依赖注入:
需要加入sping整合junit支持:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration(value = "src/main/webapp") // 测试spring-mvc
// ------------如果加入以下代码,所有继承该类的测试类都会遵循该配置,也可以不加,在测试类的方法上///控制事务,参见下一个实例
// 这个非常关键,如果不加入这个注解配置,事务控制就会完全失效!
// @Transactional
// 这里的事务关联到配置文件中的事务控制器(transactionManager =
// "transactionManager"),同时//指定自动回滚(defaultRollback = true)。这样做操作的数据才不会污染数据库!
// @TransactionConfiguration(transactionManager = "transactionManager",
// defaultRollback = true)
@ContextConfiguration(locations = { "classpath:spring/framework/applicationContext-core.xml" })
public class BaseJunitTest {

domain:

/**
 * 省市区镇级联表
 * 
 * @author gujm
 *
 */
@Data
public class CityDetail implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private Integer id;
    private String name;
    private Integer level;// 级别:1:省,2:市,3:区,4:镇
    private Integer parentId;


}

使用的是mybatis,所有附上配置文件:



<mapper namespace="com.newCloud.city.mapper.CityDetailMapper">

    <insert id="insert" keyProperty="id" useGeneratedKeys="true" parameterType="com.newCloud.city.entity.CityDetail">
        INSERT INTO city_detail (
            name,
            level,
            parent_id
        ) VALUES (      
         #{name},       
         #{level},      
         #{parentId}    
        )
    insert>
mapper>

你可能感兴趣的:(Jsoup获取全国地区数据(省市县镇村))