模拟HTTP请求实现网页自动操作及数据采集的方法
前言
网页可分为信息提供和业务操作类,信息提供如新闻、股票行情之类的网站。业务操作如网上营业厅、oa之类的。当然,也有很多网站同时具有这两种性质,像微博、豆瓣、淘宝这类网站,既提供信息,也实现某些业务。
普通上网方式一般都是手动操作(这个不需要解释:d)。但有时候人工手动操作的方式可能就无法胜任了,如爬取网络上大量数据,实时监测某个页面的变化,批量操作业务(如批量发微博,批量淘宝购物)、刷单等。由于操作量大,而且都是重复的操作,人工操作效率低下,且易出错。这时候就可以使用软件来自动操作了。
本人开发过多个这类软件,有网络爬虫、自动批量操作业务这类的。其中使用到的一个核心功能就是模拟http请求。当然,有时会使用https协议,而且网站一般需要登陆后才能进一步操作,还有最重要的一点就是弄清楚网站的业务流程,即知道为了实现某个操作该在什么时候向哪个页面以什么方式提交什么数据,最后,要提取数据或知道操作结果,就还需要解析html。本文将一一阐述。
本文使用c#语言来展示代码,当然也可以用其它语言实现,原理是一样的。以登陆京东为实例。
模拟http请求
c#模拟http请求需要使用到如下类:
•webrequest
•httpwebrequest
•httpwebresponse
•stream
先创建一个请求对象(httpwebrequest),设置相关的headers信息后发送请求(如果是post,还要把表单数据写入网络流),如果目标地址可访问,会得到一个响应对象(httpwebresponse),从相应对象的网络流中就可读出返回结果。
示例代码如下:
string contenttype = "application/x-www-form-urlencoded"; string accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/x-silverlight, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-silverlight-2-b1, */*"; string useragent = "mozilla/5.0 (windows nt 6.3; wow64) applewebkit/537.36 (khtml, like gecko) chrome/34.0.1847.116 safari/537.36"; public string get(string url, string encode = default_encode) { httpwebrequest request = webrequest.create(url) as httpwebrequest; inithttpwebrequestheaders(request); request.method = "get"; var html = readhtml(request, encode); return html; } public string post(string url, string param, string encode = default_encode) { encoding encoding = system.text.encoding.utf8; byte[] data = encoding.getbytes(param); httpwebrequest request = webrequest.create(url) as httpwebrequest; inithttpwebrequestheaders(request); request.method = "post"; request.contentlength = data.length; var outstream = request.getrequeststream(); outstream.write(data, 0, data.length); var html = readhtml(request, encode); return html; } private void inithttpwebrequestheaders(httpwebrequest request) { request.contenttype = contenttype; request.accept = accept; request.useragent = useragent; } private string readhtml(httpwebrequest request, string encode) { httpwebresponse response = request.getresponse() as httpwebresponse; stream stream = response.getresponsestream(); streamreader reader = new streamreader(stream, encoding.getencoding(encode)); string content = reader.readtoend(); reader.close(); stream.close(); return content; }
可以看出,get和post方法的代码大部分都相似,所以代码进行了封装,提取了相同代码作为新的函数。
https请求
当网站使用https协议时,以上代码就可能会出现以下错误:
the underlying connection was closed: could not establish trust relationship for
原因是证书错误,用浏览器打开会出现如下页面:
当点击继续前往xxx.xx(不安全)时,就可继续打开网页。在程序中,也只要模拟这一步就可以继续了。c#中只需设置servicepointmanager.servercertificatevalidationcallback代理,在代理方法中直接返回true就行了。
private httpwebrequest createhttpwebrequest(string url) { httpwebrequest request; if (ishttpsprotocol(url)) { servicepointmanager.servercertificatevalidationcallback = new remotecertificatevalidationcallback(checkvalidationresult); request = webrequest.create(url) as httpwebrequest; request.protocolversion = httpversion.version10; } else { request = webrequest.create(url) as httpwebrequest; } return request; } private httpwebrequest createhttpwebrequest(string url) { httpwebrequest request; if (ishttpsprotocol(url)) { servicepointmanager.servercertificatevalidationcallback = new remotecertificatevalidationcallback(checkvalidationresult); request = webrequest.create(url) as httpwebrequest; request.protocolversion = httpversion.version10; } else { request = webrequest.create(url) as httpwebrequest; } return request; }
这样,就可正常访问https网站了。
记录cookies实现身份认证
有些网站需要登录才能执行下一步操作,比如在京东购物需要先登录。网站服务器使用session来记录客户端用户,每一个session对应一个用户,而前面的代码每次创建一个请求都会重新建立一个session。即使登录成功,在执行下一步操作由于新创建了一个连接,登录也是无效的。这时就得想办法让服务器认为这一系列的请求来自同一个session。
客户端只有cookies,为了在下次请求的时候让服务器知道该客户端对应哪个session,cookies中会有一个记录session id的记录。所以,只要cookies相同,对服务器来说就是同一个用户。
这时需要使用到cookiecontainer,顾名思义,这就是一个cookies容器。httpwebrequest有一个cookiecontainer属性。只要把每次请求的cookies都记录在cookiecontainer,下次请求时设置httpwebrequest的cookiecontainer属性,由于cookies相同,对于服务器来说就是同一个用户了。
public string get(string url, string encode = default_encode) { httpwebrequest request = webrequest.create(url) as httpwebrequest; inithttpwebrequestheaders(request); request.method = "get"; request.cookiecontainer = cookiecontainer; httpwebresponse response = request.getresponse() as httpwebresponse; foreach (cookie c in response.cookies) { cookiecontainer.add(c); } }
分析调试网站
以上就实现了模拟http请求,当然,最重要的还是分析站。一般的情况都是没有文档、找不到网站开发人员,从一个黑盒子开始探索。分析工具有很多,推荐使用chrome+插件advanced rest client,chrome的开发者工具能让我们知道打开一个网页时后台做了哪些操作与请求,advanced rest client可模拟发送请求。
比如在登录京东时,会提交如下数据:
我们还能看到京东的密码居然是明文传输,安全性很让人担心啊!
还能看到返回的数据:
返回的是json数据,不过\u8d26这些是什么?其实这是unicode编码,使用unicode编码转换工具,即可转换成可读的文字,比如这次返回的结果是:账户名与密码不匹配,请重新输入。
解析html
http请求获得的数据一般是html格式,有时也可能是json或xml。需要解析才能提取有用数据。解析html的组件有:
•html parser。多个平台可用,如java/c#/python。很久没用了。
•htmlagilitypack。通过通过xpath来解析hmtl。一直使用。 关于xpath教程,可以看w3school的xpath教程。
结语
本文介绍了开发模拟自动网页操作所需要的技能,从模拟http/https请求,到cookies、分析网站、解析html。代码旨在说明使用方法,并非完整代码,可能无法直接运行。
以上这篇模拟http请求实现网页自动操作及数据采集的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
上一篇: ASP.NET实现上传Excel功能