利用IronPython做更灵活的网页爬虫

我们经常需要去别的网站采集一些信息,.NET下所有相关的技术都已经非常成熟,用Webrequest抓取页面,虽然支持自定义Reference头,又支持cookie,解析页面一般都是用正则,但是对方网站结构一变,还得重新改代码,重新编译,发布。有了IronPython,可以把抓取和分析的逻辑做成Python脚本,如果对方页面结构变了,只需修改脚本就行了,不需重新编译软件,这样可以用c#做交互和界面部分,用Python封装预期经常变化的部分。

安平网站建设公司成都创新互联公司,安平网站设计制作,有大型网站制作公司丰富经验。已为安平近千家提供企业网站建设服务。企业网站搭建\外贸网站建设要多少钱,请找那个售后服务好的安平做网站的公司定做!

如何利用IronPython把抓取和分析的逻辑做成Python脚本
  安装好IronPython和vs.net 2010后,还需要下载一个SGMLReader(见参考链接),这个组件可以把格式不是很严格的HTML转换成格式良好的XML文件,甚至还能增加DTD的验证  
  我们以抓取百度贴吧页面为例,新建一个Console项目,引用IronPython,Microsoft.Dynamic,Microsoft.Scripting,SgmlReaderDll这些组件,把SGMLReader里的Html.dtd复制到项目目录下,如果没有这个,它会根据doctype去网络上找dtd,然后新建baidu.py的文件,最后在项目属性的生成事件里写上如下代码,把这两个文件拷贝到目标目录里。

 
 
  1. copy $(ProjectDir)\*.py $(TargetDir)  
  2. copy $(ProjectDir)\*.dtd $(TargetDir) 

  在baidu.py里首先引用必要的.net程序集。

 
 
  1. import clr, sys  
  2. clr.AddReference("SgmlReaderDll")  
  3. clr.AddReference("System.Xml")  

完了导入我们需要的类

 
 
  1. from Sgml import *  
  2. from System.Net import *  
  3. from System.IO import TextReader,StreamReader  
  4. from System.Xml import *  
  5. from System.Text.UnicodeEncoding import UTF8  

利用SgmlReader写一个把html转换成xml的函数,注意SystemLiteral属性必须设置,否则就会去网上找dtd了,浪费时间

 
 
  1. def fromHtml(textReader):      
  2. sgmlReader = SgmlReader()      
  3. sgmlReader.SystemLiteral = "html.dtd"    sgmlReader.WhitespaceHandling =WhitespaceHandling.All      
  4. sgmlReader.CaseFolding = CaseFolding.ToLower    sgmlReader.InputStream = textReader          
  5.  
  6.  
  7. doc = XmlDocument()      
  8. doc.PreserveWhitespace = True      
  9. doc.XmlResolver = None      
  10. doc.Load(sgmlReader)      
  11. eturn doc  

利用webrequest写一个支持cookie和网页编码的抓网页方法

 
 
  1. def getWebData(url, method, data = None, cookie = None, encoding = "UTF-8"):      
  2.    req = WebRequest.Create(url)      
  3.    req.Method = method          
  4.    if cookie != None:          
  5.       req.CookieContainer = cookie          
  6.    if data != None:          
  7.       stream = req.GetRequestStream()          
  8.       stream.Write(data, 0, data.Length)              
  9.    rsp = req.GetResponse()      
  10.    reader = StreamReader(rsp.GetResponseStre(),            
  11.    UTF8.GetEncoding(encoding))            
  12.    return reader  

写一个类来定义抓取结果,这个类不需要在c#项目里定义,到时候直接用c# 4.0的dynamic关键字就可以使用

 
 
  1. class Post:  
  2.     def __init__(self, hit, comments, title, link, author):  
  3.         self.hit = hit  
  4.         self.comments = comments   
  5.         self.title = title  
  6.         self.link = link  
  7.         self.author = author  

定义主要工作的类,__init__大概相当于构造函数,我们传入编码参数,并初始化cookie容器和解析结果,[]是python里的列表,大约相当于c#的List

 
 
  1. class BaiDu:  
  2.     def __init__(self,encoding):  
  3.         self.cc = self.cc = CookieContainer()  
  4.              self.encoding = encoding 
  5.             self.posts = []     

接下来定义抓取方法,调用getWebData抓网页,然后用fromHtml转换成xml,剩下的就是xml操作,和.net里一样,一看便知

 
 
  1. def getPosts(self, url):  
  2.         reader = getWebData(url, "GET", None, self.cc, self.encoding)  
  3.         doc = fromHtml(reader)  
  4.         trs = doc.SelectNodes("html//table[@id='thread_list_table']/tbody/tr")       
  5.         self.parsePosts(trs)  
  6.  
  7. def parsePosts(self, trs):  
  8.         for tr in trs:  
  9.             tds = tr.SelectNodes("td")  
  10.             hit = tds[0].InnerText  
  11.             comments = tds[1].InnerText  
  12.             title = tds[2].ChildNodes[1].InnerText  
  13.             link = tds[2].ChildNodes[1].Attributes["href"]   
  14.             author = tds[3].InnerText  
  15.  
  16.             post = Post(hit, comments, title, link, author)  
  17.             self.posts.append(post)  

c#代码要创建一个脚本运行环境,设置允许调试,然后执行baidu.py,最后创建一个Baidu的类的实例,并用dynamic关键字引用这个实例

 
 
  1. Dictionary options = new Dictionary();      
  2.   options["Debug"] = true;            
  3.   ScriptEngine engine = Python.CreateEngine(options);            
  4.   ScriptScope scope = engine.ExecuteFile("baidu.py");            
  5.   dynamic baidu = engine.Operations.Invoke(scope.GetVariable("BaiDu"), "GBK");  

接下来调用BaiDu这个python类的方法获取网页抓取结果,然后输出就可以了

 
 
  1. baidu.getPosts("http://tieba.baidu.com/f?kw=seo");             
  2.    dynamic posts = baidu.posts;          
  3.    foreach (dynamic post in posts)            
  4.  {                   
  5.      Console.WriteLine("{0} (回复数:{1})(点击数:{2})[作者:{3}]",                      
  6.      post.title,                  
  7.  post.comments,                     
  8.   post.hit,                   
  9.  post.author);           
  10.  }  

分享标题:利用IronPython做更灵活的网页爬虫
分享路径:http://www.36103.cn/qtweb/news41/25041.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联