[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[网络工具] 用批处理+curl+HtoX32c整理中国医药网上的医院名录信息

本帖最后由 namejm 于 2011-4-3 23:16 编辑

  中国医药网上有27000多家医疗机构的数据(网址:http://www.pharmnet.com.cn/search/template/yljg_index.htm),含医院名称、地址、联系电话……这信息还真够全的啊。哥们,还在楞着干什么啊?赶紧把这些数据扒下来啊,里面商机无限啊!

  一页一页往下翻,Ctrl+C、Ctrl+V不停变换,在网页和记事本之间来回倒腾,哎呦呦,我的手抽筋了,这样下去会死人di,挨踢民工不是这么当的——不要把生命浪费在鼠标的指指点点上!

  火速召集各路大仙前来会商。火车采集器,久闻大名,从未用过,据说需要熟悉html语言和正则表达式,难度太高,直接放弃;Offline Explorer、Teleport之流,貌似能下载指定格式的文件,可惜没找到只下载指定范围内页面的功能,只能打入冷宫……这些软件都存在一个共同的问题:即使把那些指定的网页都下载了,但是,如何提取网页中的指定内容,它们都纷纷表示很有压力,思前想后,决定重拾万众望而生畏的批处理,携curl、htox32c等一众命令行工具,披挂上阵,它们的分工如下:

  curl:负责下载网页文件。
  htox32c:负责把网页文件转换为纯文本。
  批处理:负责从curl下载回来的网页文件中提取其他网页文件的下载链接,以备curl调用;从htox32c转换后的文本中提取指定内容,并以指定格式保存。

  打开中国医药网,进入医疗机构页面(http://www.pharmnet.com.cn/search/template/yljg_index.htm),先火力侦察一番。

  在“医院地区检索”一栏中,罗列出了全国34个省/自治区/直辖市/特别行政区的名称。点击那些名称,可以直接跳到相应的网页,也就是说,那些名称文字背后,捆绑着真实的网页地址,恩,这非常好,批处理可以直接拿下,curl不用担心找不到下载用的url了;继续前行,随便点开一个名称,比如“山东”,哇,山东省的各个医院名称、医院地址、邮编、联系电话等等信息一应俱全,赫然在列,也就是说,只要下载到了这个页面,那些需要的条目都已经全部就位了。再往下一拉,看到了什么?“::::::共有1695条记录,113页,显示1--15 1 2 3 4 5 6 7 8 9 10 >> ::::::”,哈哈,太令人激动了,只要下载了其中一个网页,它前后几个网页的链接都可以在这里找到了,下载整个山东省的数据将是手到擒来的事情,以此类推,获取其他地区的数据也将轻而易举。

  抓取方案迅速形成:

  1、curl下载http://www.pharmnet.com.cn/search/template/yljg_index.htm到本地;
  2、批处理提取yljg_index.htm中各个地区的URL;
  3、curl下载各个地区的首页,批处理根据上一页分析下一页的URL,供curl下载,直至最后一个网页下载完毕
  4、htox32c转换这些网页文件为纯文本
  5、批处理分析转换后的纯文本文件,提取各医院的名称、地址、邮编

  原以为整个过程会相当顺利,可是,当我下载了yljg_index.htm之后,我傻眼了。

  山东啊,广东啊……你们对应的都是些什么URL啊:http://www.pharmnet.com.cn/searc ... C9%BD%B6%AB&p=1http://www.pharmnet.com.cn/searc ... B9%E3%B6%AB&p=1……你不知道百分号对在批处理中是表示变量引用么?%B9%?%BD%?经过多次处理之后,cmd.exe怎么知道你到底想表示URL还是代表变量?它一直当你们是变量引用的呢!一引用就成了空值了呢!你们长啥模样不好,偏偏给我来一串又一串的百分号!叫我情何以堪?!!谁能告诉我,你们的真身到底是什么?

  我苦闷,我彷徨,我百无聊赖地在网上闲逛。我招谁惹谁了?连个小小的百分号对都要和我对着干!我学着《非诚勿扰》里的男猪脚开始了忏悔,从幼儿园里得到大红花引起周围小朋友的嫉妒开始,直到大学毕业私刻萝卜章在毕业证学位证上涂鸦为止,大大小小的罪恶都忏悔了个遍,还是没有找到灵感。于是又伤心地回忆起自己的批处理从业史,万念俱灰地想随着CN-DOS的倒闭而自绝于批处理同仁,突然之间,脑中灵感闪现,想起了CN-DOS里一度火热的自动登录163信箱的批处理话题,其中提到了base64编码,莫非这个地址就是base64编码过的?

  有编码转换经验的童鞋,请原谅我当初的无知,对于我这个编程门外汉来说,那些字符串真的是天书,并且我的第一反应是base64编码,不为什么,只因自己的一无所知^_^。无知者无谓么,我就开动搜索引擎搜起base64编码的解码工具来了。

  这下倒好,base64解码功能没有把这些地址解读出来,倒是把url解码给试用了一下,这一试不打紧,一试就试出了完美答案:http://www.pharmnet.com.cn/searc ... C9%BD%B6%AB&p=1 解码后是 http://www.pharmnet.com.cn/search/index.cgi?c1=19&c2=山东&p=1 ,http://www.pharmnet.com.cn/searc ... B9%E3%B6%AB&p=1 解码后是 http://www.pharmnet.com.cn/search/index.cgi?c1=19&c2=广东&p=1 ,也就是说,可以直接在URL地址栏中输入带地名的字符串获取网页文件。再试试其他地址:http://www.pharmnet.com.cn/searc ... amp;c2=%C9%BD%B6%AB 实际就是 http://www.pharmnet.com.cn/searc ... =&c1=19&c2=山东 ,其中,p=3 中的 3 表示第3页,哈哈,百分号对没有了,还可以直接用省名来直接下载网页了,真是太美妙了。在这里推荐一个在线编码解码的网站:http://www.mxcz.net/tools/Url.aspx

  整理医院名录的完整代码在此,最终格式是应CCF网友evanjr的要求来做的(详情请见:请问有什么方法能快速地把这个网站的内容抓下来?http://bbs.et8.net/bbs/showthread.php?t=1014270),即2W多个医院的信息整理到一个文件中,只提取医院名称、地址和邮编,分3行显示,每个医院之间的条目空一行,不用过滤重复条目:
  1. @echo off
  2. set begin=%date% %time%
  3. setlocal enabledelayedexpansion
  4. set www=http://www.pharmnet.com.cn/search/template/yljg_index.htm
  5. md html 2>nul
  6. md txt 2>nul
  7. del /a /f /q txt\*.txt 2>nul
  8. curl -o html\index.html %www%
  9. for /f "delims=<>= tokens=7" %%a in ('findstr /i "search\/index\.cgi\?c1=19" html\index.html') do (
  10.     cls
  11.     title 正在下载 【%%a】 数据
  12.     md "html\%%a" 2>nul
  13.     cd.>txt\%%a.txt
  14.     pushd "html\%%a"
  15.     curl -o 1.html "http://www.pharmnet.com.cn/search/index.cgi?c1=19&c2=%%a&p=1"
  16.     for /f "delims=<> tokens=10" %%b in ('findstr /i ":共有.*页" 1.html') do (
  17.         curl -o #1.html "http://www.pharmnet.com.cn/search/index.cgi?p=[2-%%b]&cate1=&terms=&c1=19&c2=%%a"
  18.     )
  19.     title 正在转换 【%%a】 数据文件格式
  20.     htox32c /ip /O0 *.html
  21.     title 正在筛选 【%%a】 数据
  22.     echo;&echo 正在筛选 【%%a】 数据,请稍候...
  23.     (for %%c in (*.txt) do (
  24.         for /f "skip=18 tokens=*" %%d in ('findstr /iv "\* 共有 免责声明 关于公司 版权所有" "%%c"') do (
  25.             echo;%%d
  26.         )
  27.     ))>..\..\txt\%%a.txt
  28.     del /a /f /q *.txt
  29.     popd
  30. )
  31. cls
  32. title 提取数据
  33. echo;&echo;&echo         正在按照指定格式提取数据
  34. echo;&echo             请耐心等待...
  35. pushd txt
  36. cd.>tmp
  37. for %%i in (*.txt) do copy /b tmp+%%i tmp>nul
  38. set num=0
  39. (for /f "delims=" %%i in ('findstr /v "联系电话" tmp') do (
  40.     set /a num+=1
  41.     if !num! equ 1 set name=%%i
  42.     if !num! equ 2 (
  43.         set "str=%%i"
  44.         set "postcode=!str:*邮  编:  =!"
  45.         call set "address=%%str:  邮  编:  !postcode!=%%"
  46.         if not defined postcode set postcode=不详
  47.         set "address=!address:医院地址:  =!"
  48.         if not defined address set address=不详
  49.         echo 医院名称:!name!
  50.         echo 医院地址:!address!
  51.         echo 邮编:!postcode!
  52.         echo;
  53.         set num=0
  54.     )
  55. ))>result
  56. move result ..\处理结果.txt
  57. popd
  58. cls
  59. title 处理完毕
  60. echo;&echo;&echo         已经处理完毕,按任意键打开处理结果
  61. echo 开始时间:%begin%
  62. echo 结束时间:%date% %time%
  63. pause>nul
  64. start 处理结果.txt
复制代码
  代码解读:

  用curl抓取网页数据的关键是什么?

  是找到网页文件的真实url。

  找到了真实的url,就不会下载多余的网页,也不会漏下载网页。为了找到每个网页文件的真实url,就需要去寻找集中记录有这些链接的网页,一般是在网站的首页或某些版面的首页里会有这个东西。在这个案例中,http://www.pharmnet.com.cn/search/template/yljg_index.htm这个页面就按照省区记录了所有的链接——虽然不直接提供,但是,通过里面的链接进去,是能把我们需要的所有链接都找到的。

  非常不幸的是,这些链接是被url编码过的,仅从字符串上,我们无法了解这个链接的具体含义,更要命的是,编码后的字符串里含有多个百分号,在批处理中很容易被识别为变量引用,只能把这些编码过的字符串复原才好使用。

  经过转码,我们得知,完整的链接中,是含有省名、页码等关键字的,这就为我们构造curl的真实下载链接提供了方便:通过yljg_index.htm,我们可以提取出省名;点击进去之后,在第一个页面的最下方,可以提取到该省的数据总共有多少个页面(实际上,在每个网页中都包含有总页面个数的信息),curl只需从第1个页面下载到第N个页面就大功告成了。

  网页下载回来之后,因为里面有太多的网页标记,直接从原始网页中提取指定的信息,非常麻烦,需要用htox32c这个工具来把网页转换为纯文本文件。

  经过htox32c的转换之后,剩下的工作就转化成批处理如何整理本地文本的问题了。

  由此可见,用批处理采集数据并不是件十分困难的事情,一般使用如下流程,基本可以搞定:

  1、用curl下载网站首页;
  2、用批处理分析首页的网页文件,提取出指定的url,以备curl调用;
  3、curl接收上一步提取出来的url,继续下载后续网页文件;
  4、重复上述第2步和第3步,直至指定的网页下载完毕;
  5、用HtoX32c把网页文件转换为纯文本文件
  6、用批处理分析、提取转换后的纯文本文件中的内容。
  7、Over。

  上述代码有个地方值得特别注意:在筛选数据的时候,for /f "skip=18 tokens=*" %%d in (……) 一句中,tokens=*不能用delims=来替换,否则,筛选出来的文本中会含有带空格的空行,导致后续的处理出错。

  以上代码还可以进一步改造,使得医院名录可以分省市保存。大家可以自行琢磨,在此就不提供代码了。

  正文中提到的命令行工具可以在这些地方找到:

  1、Curl.exe:http://curl.haxx.se/(官网)或 http://bbs.bathome.net/thread-1761-1-1.html
  2、HtoX32c.exe:http://win32lab.com/(官网,日文)或 http://bbs.bathome.net/thread-1974-1-1.html(带中文帮助信息)
1

评分人数

尺有所短寸有所长,学好批处理没商量;
考虑问题复杂化,解决问题简洁化。

心在天山,身老沧州。

JM的实用工具,支持一下,占个沙发!

TOP

我是来捧场的
---学无止境---

TOP

返回列表