网页音频抓取(​示例​​下载​朋友问到这样一个问题,需要实现如下功能(图) )

优采云 发布时间: 2022-03-30 10:05

  网页音频抓取(​示例​​下载​朋友问到这样一个问题,需要实现如下功能(图)

)

  ​​​

  示例​​下载​​​

  有朋友问了这样一个问题,需要实现以下功能

  1、打开一个空运公司的查询网页,比如​​​​,页面有两个文本框供用户输入业务代码,比如,

  2、然后点击“Go”按钮,下一页显示查询结果

  现在需要程序自动执行以上步骤,将查询结果提取出来做后续处理。

  要完成这样的功能,首先要解决以下问题:

  l 可以使用程序在后台向目标网页发布数据

  l 可以接收对方返回的HTML结果页面

  l 分析页面并提取所需结果的能力

  经过一番研究和实验,我解决了上述问题,下面分别介绍。

  1.使用程序将指定的数据post到目标网页,并接收结果网页

  我首先使用网络嗅探器来捕捉浏览器与其他网页在使用IE手动查询时的HTTP协议交互过程。推荐使用Ultra Network Sniffer,它有连接监控功能,可以监控一个程序的所有连接,避免其他无关数据包的干扰。如图所示

  在查询页面输入数据后,点击“Go”按钮,sniffer抓到的数据包如下图

  请注意第三行,有一个Post包,这是我们需要的,

  它发送的网页地址是:

  它发布的数据是:awbpre=180&awbnum=36898035&x=17&y=9

  显然180和36898035可以替换,需要注意的是,发送的目的网页不再是我们直接在浏览器中输入的初始页面​​​​

  接下来我们使用程序发送这个数据,代码如下

  public static string GetPage(string url, string postData,string encodeType,out string err)<br /><br /> {<br /><br /> Stream outstream = null;<br /><br /> Stream instream = null;<br /><br /> StreamReader sr = null;<br /><br /> HttpWebResponse response = null;<br /><br /> HttpWebRequest request = null;<br /><br /> Encoding encoding = Encoding.GetEncoding(encodeType);<br /><br /> byte[] data = encoding.GetBytes(postData);<br /><br /> // 准备请求...<br /><br /> try<br /><br /> { <br /><br /> // 设置参数<br /><br /> request = WebRequest.Create(url) as HttpWebRequest;<br /><br /> CookieContainer cookieContainer = new CookieContainer();<br /><br /> request.CookieContainer = cookieContainer;<br /><br /> request.AllowAutoRedirect = true;<br /><br /> request.Method = "POST";<br /><br /> request.ContentType = "application/x-www-form-urlencoded";<br /><br /> request.ContentLength = data.Length;<br /><br /> outstream = request.GetRequestStream();<br /><br /> outstream.Write(data,0,data.Length);<br /><br /> outstream.Close();<br /><br /> //发送请求并获取相应回应数据<br /><br /> response = request.GetResponse() as HttpWebResponse;<br /><br /> //直到request.GetResponse()程序才开始向目标网页发送Post请求<br /><br /> instream = response.GetResponseStream();<br /><br /> sr = new StreamReader( instream, encoding );<br /><br /> //返回结果网页(html)代码<br /><br />string content = sr.ReadToEnd();<br /><br /> err = string.Empty;<br /><br /> return content;<br /><br /> }<br /><br /> catch(Exception ex)<br /><br /> {<br /><br /> err = ex.Message;<br /><br /> return string.Empty;<br /><br /> }<br /><br />}

  上面的代码通俗易懂,就不多废话了,简单说几个注意点:

  如果你的程序需要保留SessionID,比如ASP.NET中的SessionID。比如自动登录后,可能需要进行后续处理,所以需要将上一个请求返回的cookieContainer分配给新的请求,然后再将请求发送到下一页,因为cookieContainer中预留了一个名为ASPNETSessionID的cookie。

  如果你的 Post 的目标页面是 ASP.NET 页面,那么在要提交的 Form 中一般会有一个 __ViewState 隐藏的 Input 字段。服务器返回的网页源代码的ViewState示例如下,

  <br /><br /><br /><br /><br /><br /><br /><br /><br /><br />

  然而,嗅探器中捕获的 Post 数据是:

  __VIEWSTATE=dDwtMzg4MDA0NzA7Oz7%2BjHQ0vF37%2Fga2CitRkQ3sfg%2BePg%3D%3D&amp;用户名=管理员&amp;密码=123&amp;提交=按钮0

  请注意,这里ViewState的数据和上一个有点不同。不同的是,“+/=”等符号已经转换成%2B、%2F、%3D等,实际上是URL ViewState Encoding的值,可以使用System.Web.HttpUtility.UrlEncode( ) 方法来做这个转换

  当然,如果只需要一次性访问页面,就不用管这些了,根据sniffer抓到的结果发送数据即可,但如果需要根据ViewState动态处理页面返回的值,则需要注意这一点。

  2.从 HTML 页面代码中提取信息

  要从 HTML 网页中提取信息,您必须首先将网页代码格式化为 XML 文件,然后您可以使用 XPath 轻松提取您想要的信息。要将 HTML 格式化为 XML,目前有多种选择。

  1、Chris Lovett 的 SgmlReader:

  2、Simon Mourier 的 .NET Html 敏捷包

  ​​​​

  我选择了 SgmlReader。通过实际使用,我发现SgmlReader并不完美。有时候格式化的xml的嵌套关系会出错,但即便如此,根据他格式化的文本,提取数据就足够了。

  public static DataSet ParsePage(string pageContent, string xpath, out string err)<br /><br /> {<br /><br /> err = string.Empty;<br /><br /> string pageContent = this.tbHTML.Text;<br /><br /> StreamReader streamReader = null;<br /><br /> StringWriter strWriter = null;<br /><br /> SgmlReader sgmlReader = null;<br /><br /> XmlTextWriter xmlWriter = null;<br /><br /> try<br /><br /> {<br /><br /> sgmlReader = new SgmlReader();<br /><br /> sgmlReader.DocType = "HTML";<br /><br /> sgmlReader.InputStream = new StringReader(pageContent);<br /><br /> strWriter = new StringWriter();<br /><br /> xmlWriter = new XmlTextWriter(strWriter);<br /><br /> xmlWriter.Formatting = Formatting.Indented;<br /><br /> while (sgmlReader.Read())<br /><br /> {<br /><br /> if (sgmlReader.NodeType != XmlNodeType.Whitespace)<br /><br /> {<br /><br /> xmlWriter.WriteNode(sgmlReader, true);<br /><br /> }<br /><br /> }<br /><br /> string wellFormedHTML = strWriter.ToString();<br /><br /> this.tbHTML.Text = wellFormedHTML;<br /><br /> string xpath = this.tbXPath.Text;<br /><br /> XPathDocument doc = new XPathDocument(new StringReader(wellFormedHTML));<br /><br /> XPathNavigator nav = doc.CreateNavigator();<br /><br /> XPathNodeIterator nodes = nav.Select(xpath);<br /><br /> while (nodes.MoveNext())<br /><br /> {<br /><br /> this.tbResult.Text += nodes.Current.Value+"\n";<br /><br /> }<br /><br /> }<br /><br /> catch (Exception exp)<br /><br /> {<br /><br /> string err = exp.Message;<br /><br /> MessageBox.Show("错误:"+err);<br /><br /> }<br /><br />}<br /><br />}

  根据上面的代码,目前主要的问题是设置正确的XPath。有一篇关于代码项目 文章 的文章提供了一个简单的 XPath 查询工具。我对它做了一些修改,主要是增加了在节点的body中搜索某个字符串的功能,方便你根据得到的HTML页面查询XPath

  调试 XPath 查询:​​​​

  例如,下面是一个根据查询结果格式化的 XML 文本片段。信息的 XPath 是

  //div[@class=”content”]/DIV[@id=”tblwithbck”]/TABLE/TR/TD/TABLE/TR/TD/DIV[@class=”data”]

  需要注意的是,XPath中的每条路径都是区分大小写的,我只是一开始没有注意这个问题,犯了一些错误。

  <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />2 piece(s) 42 K departed on flight KE6316/04JUN from PVG to ICN<br /><br /><BR /><br /><br />Actual Time of Flight-Departure : 19:20<br /><br /><BR /><br /><br />Scheduled Time of Flight-Arrival : 21:55<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />2 piece(s) 42 K departed on flight 9S0910/06JUN from ICN to DFW<br /><br /><BR /><br /><br />Actual Time of Flight-Departure : 22:15<br /><br /><BR /><br /><br />Scheduled Time of Flight-Arrival : 05:35+1<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />2 piece(s) 42 K departed on flight 3A3617/07JUN from DFW to ELP<br /><br /><BR /><br /><br />Actual Time of Flight-Departure : 22:00<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />2 piece(s) 42 K arrived in ELP from flight 3A3617<br /><br /><BR /><br /><br />Scheduled arrival : 08 JUN<br /><br /><BR /><br /><br />Goods checked in at : 11:00<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />Arrival docs delivered for 2 piece(s) 42 K on 09 JUN at 09:48 in ELP<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线