首先声明,这里并不是我用perl来写个算法。如果需要算法相关的东西,得去看文献。
这里,其实只是借对格兰氏阳性细菌蛋白质定位的预测为例,来说明如何利用他人提供的在线查询功能来实现批处理。
假设现在有一个完整的基因组需要您去预测它当中的每一个开放阅读框翻译出来的蛋白质可能的细胞内定位,怎么办呢?手工一个一个提交到网站上去?一共会有四五千个蛋白,等你提交完,你的手和大脑都会不工作了吧?要不自己下载个软件来本地预测吧?我试过去安装那些要求的软件环境,也许是我的系统过新吧,一个c语言库的版本,一个g77让我就头大得不知道该怎么继续下去。于是我还是下定决心,用perl的lwp来伪装成浏览器提交申请,自动批处理吧。也许一觉醒来,全部都做完了。
我们要用到的网站是http://www.psort.org/psortb/。据网站上宣传,Based on a study last performed in 2010, PSORTb v3.0.2 is the most precise bacterial localization prediction tool available. 第二个原因就是can currently submit one or more Gram-positive or Gram-negative bacterial sequences or archaeal sequences in FASTA format。这对于研究格兰氏阳性菌的我来说的确很不错的网站。
最基本的,用lwp来虚拟提交一份表单上去:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #!/usr/bin/perl use LWP::UserAgent; $ua = LWP::UserAgent->new; $ua->agent("Mozilla 8.0 beta"); use HTTP::Request::Common qw(POST); my $req = (POST 'http://www.psort.org/psortb/results.pl', ["seq" => ">$genes{name}\n$genes{translation}", "organism" => "bacteria", "gram"=>"positive", "advancedgram"=>"none", "format"=>"long", "sendresults"=>"display"); $request = $ua->request($req); print $request->as_string; |
结果得到的,怎么都是500 Internal Server Error。于是在网上狂google,也没有找到直接的答案。半夜两点,突然想起,为什么不自己想法来解决问题。于是开始用tcpdump抓包,对比从firefox发送出去的包和perl发送出去的包,具体看看有什么不同。
windows下需要先去下载一个可用的tcpdump来。如果使用linux或者mac x的话,可以直接使用,需要注意的就是需要su或者sudo的权限。tcpdump是用来抓包的。接着还需要下载wireshark来分析包。wireshark是跨平台的。
tcpdump抓包并保存为文件的命令为:tcpdump -w [filename] host [host.ip],此外,为了保证抓取的包的完整性,用-s参数指定帧大小也是很必要的,下面就是一个抓取的实际例子:
sudo /usr/sbin/tcpdump -w data -s 10240 host 142.58.106.205 |
这个ip可以通过ping www.psort.org来获得。分别使用firefox和perl提交一个测试性的序列给www.psort.org来抓包。抓取完毕后按 Ctrl + C即可终止抓取。
接下来就是使用wireshark来分析包。
对于TCP协议,它支持跟踪模式(Follow TCP Stream),即将本次TCP会话的所有内容在同一个窗口列出来,可以更直观的看到会话进程:
我们注意到,它有许多文件头,比如说 keep-live啊之类的。我们把它一一都实现了。还用就是注意到它post的数据是由boundary分割的。我们也需要把它实现。查了一下libwww-perl > HTTP::Request::Common的说明文件,具体编写代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #!/usr/bin/perl use LWP::UserAgent; push(@LWP::Protocol::http::EXTRA_SOCK_OPTS, SendTE => 0); $ua = LWP::UserAgent->new; $ua->conn_cache(LWP::ConnCache->new( )); $ua->default_header('Keep-Alive'=>"115"); $ua->agent("Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 ( .NET CLR 3.5.30729)"); $ua->default_header('Accept-Encoding' => "gzip,deflate"); $ua->default_header('Accept-Language' => "en-us,en;q=0.5"); push @{$ua->requests_redirectable},'POST'; $ua->default_header('Accept-Charset' =>"GB2312,utf-8;q=0.7,*;q=0.7"); $ua->default_header('Referer'=>"http://www.psort.org/psortb/"); $ua->default_header('Accept'=>"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); $ua->default_header('Host'=>"www.psort.org"); use HTTP::Request::Common qw(POST); use LWP::ConnCache; my $req = (POST 'http://www.psort.org/psortb/results.pl', Content_Type => 'form-data', Content => ["organism" => "bacteria", "gram"=>"positive", "advancedgram"=>"none", "format"=>"long", "sendresults"=>"display", "email"=>"", "seqs" => ">GI:300434440\ MKNLWNIFKKGLIAENPIFVLALSLCPALATTSTAVNGFTMGIC\ VLFVITCNNTVVSIIKNVVNPKVRVPVYITCIATIVTVVELVMQAYAPLLYKQLGIYL\ ALVVVFAIILARAETFASKNPVVPSFFDGLGMGCGFTLALTIIGMIRELFGSGAIFGV\ NVFGASYNPALIMILPPGGFILIGYLVAIVKVYNQHMEKIKMQKLEKANGGEA", "submit"=>"Submit" ]); $request = $ua->request($req); print $request->as_string; |
看到返回结果成功,下面的事情就是把程序当中需要提交的序列从文件当中读取出来依次提交上去就可以了。