我开发了一个使用 Apache-JMeter 的网络爬虫。
我创建了一个记录 Controller 来将请求/响应记录为 jmx 树。
要记录 jmx,我有两种选择,要么在我的代码中集成 JMeter api,要么使用 JMeter GUI,我选择两者进行测试。所以我从代码和 gui 运行 apache-jmeter 来并排记录请求/响应。下面是一个请求的Code-Base-JMeter和GUI-Base-JMeter的jmx结果
代码库-JMeter
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testname="19 /rural-property-for-sale/yorkshire/north-yorkshire/holmeonspaldingmoor-26186193/" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.implementation">HttpClient4</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.use_keepalive">false</boolProp>
<stringProp name="HTTPSampler.domain">www.uklandandfarms.co.uk</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<stringProp name="HTTPSampler.port">0</stringProp>
<stringProp name="HTTPSampler.protocol">http</stringProp>
<stringProp name="HTTPSampler.path">/rural-property-for-sale/yorkshire/north-yorkshire/holmeonspaldingmoor-26186193/</stringProp>
<elementProp name="HTTPSampler.header_manager" elementType="HeaderManager" guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
<collectionProp name="HeaderManager.headers">
<elementProp name="Cache-Control" elementType="Header">
<stringProp name="Header.name">Cache-Control</stringProp>
<stringProp name="Header.value">no-cache</stringProp>
</elementProp>
<elementProp name="Accept-Encoding" elementType="Header">
<stringProp name="Header.name">Accept-Encoding</stringProp>
<stringProp name="Header.value">gzip</stringProp>
</elementProp>
<elementProp name="Pragma" elementType="Header">
<stringProp name="Header.name">Pragma</stringProp>
<stringProp name="Header.value">no-cache</stringProp>
</elementProp>
<elementProp name="User-Agent" elementType="Header">
<stringProp name="Header.name">User-Agent</stringProp>
<stringProp name="Header.value">Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.112 Safari/535.1</stringProp>
</elementProp>
<elementProp name="Accept" elementType="Header">
<stringProp name="Header.name">Accept</stringProp>
<stringProp name="Header.value">text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2</stringProp>
</elementProp>
</collectionProp>
</elementProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.image_parser">true</boolProp>
</HTTPSamplerProxy>
GUI-Base-JMeter
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="32 /" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">www.uklandandfarms.co.uk</stringProp>
<stringProp name="HTTPSampler.port"></stringProp>
<stringProp name="HTTPSampler.protocol">http</stringProp>
<stringProp name="HTTPSampler.contentEncoding">utf-8</stringProp>
<stringProp name="HTTPSampler.path">/</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<boolProp name="HTTPSampler.image_parser">true</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="HTTPSampler.implementation">HttpClient4</stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree>
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
<collectionProp name="HeaderManager.headers">
<elementProp name="Accept-Language" elementType="Header">
<stringProp name="Header.name">Accept-Language</stringProp>
<stringProp name="Header.value">en-GB,en;q=0.5</stringProp>
</elementProp>
<elementProp name="Upgrade-Insecure-Requests" elementType="Header">
<stringProp name="Header.name">Upgrade-Insecure-Requests</stringProp>
<stringProp name="Header.value">1</stringProp>
</elementProp>
<elementProp name="Accept-Encoding" elementType="Header">
<stringProp name="Header.name">Accept-Encoding</stringProp>
<stringProp name="Header.value">gzip, deflate</stringProp>
</elementProp>
<elementProp name="User-Agent" elementType="Header">
<stringProp name="Header.name">User-Agent</stringProp>
<stringProp name="Header.value">Mozilla/5.0 (Windows NT 10.0; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0</stringProp>
</elementProp>
<elementProp name="Accept" elementType="Header">
<stringProp name="Header.name">Accept</stringProp>
<stringProp name="Header.value">text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</stringProp>
</elementProp>
</collectionProp>
</HeaderManager>
<hashTree/>
</hashTree>
录音之间的差异
1) HTTPSamplerProxy 树在 GUI-Base-JMeter 重新编码的 header 部分之前结束,而 HTTPSamplerProxy 树在 Code- 的最后结束基础JMeter
2) HeaderManager 在GUI-Base-JMeter 中是标签,而在Code-Base-JMeter 中是elementProp 标签的属性值。
3) HeaderManager 是 GUI-Base-JMeter 中 HTTPSamplerProxy 的兄弟,而 elementProp 标签(属于 HeaderManager property-value) 是 HTTPSamplerProxy 的子级。
两个录音的整体布局基本上是不同的。我希望 Code-Base-JMeter 记录与 GUI-Base-JMeter 重新编码相同。
我正在使用 Apache-JMeter 3.2(用于 GUI 和代码)
下面是代码
初始化
public void init(Integer port) throws Exception {
JMeterUtils.setJMeterHome(Constants.JMETER_HOME);
JMeterUtils.loadJMeterProperties(JMeterUtils.getJMeterBinDir() + "/jmeter.properties");
JMeterUtils.initLocale();
LoopController loopController = new LoopController();
loopController.setEnabled(true);
loopController.setLoops(1);
RecordingController rc = new RecordingController();
rc.setName("Recording Controller");
TestPlan testPlan = new TestPlan();
ThreadGroup threadGroup1 = new ThreadGroup();
threadGroup1.setSamplerController(loopController);
threadGroup1.addTestElement(rc); // Target
ListedHashTree testPlanTree = new ListedHashTree();
testPlanTree.add(testPlan);
testPlanTree.add(threadGroup1, testPlan);
this.treeModel = new JMeterTreeModel(new Object());
JMeterTreeNode root = (JMeterTreeNode) treeModel.getRoot();
treeModel.addSubTree(testPlanTree, root);
proxy = new ProxyControl();
proxy.setNonGuiTreeModel(treeModel);
proxy.setTarget(treeModel.getNodeOf(threadGroup1));
proxy.setGroupingMode(2); // GROUPING_IN_SIMPLE_CONTROLLERS = 2
// proxy.setGroupingMode(3); // GROUPING_STORE_FIRST_ONLY = 3
proxy.setSamplerTypeName("2"); // SAMPLER_TYPE_HTTP_SAMPLER_HC4 = "2"
proxy.setRegexMatch(Boolean.TRUE);
proxy.setPort(port); // Global Settings -> Port
proxy.setCaptureHttpHeaders(Boolean.TRUE);
proxy.setSamplerFollowRedirects(Boolean.TRUE);
// proxy.setSamplerRedirectAutomatically(Boolean.TRUE);
proxy.setSamplerDownloadImages(Boolean.TRUE);
treeModel.addComponent(proxy, (JMeterTreeNode) root.getChildAt(1));
}
启动JMeter
this.proxy.startProxy();
停止/记录 JMeter
/**
* The method stop() is use to stop JMeter recording controller proxy.
*
* @return The tree that is recorded till now
*/
public String stop() {
OutputStream out = null;
try {
this.proxy.stopProxy();
if (this.treeModel == null) {
return null;
}
out = new ByteArrayOutputStream();
HashTree tree = treeModel.getTestPlan();
JMeter.convertSubTree(tree);
SaveService.saveTree(tree, out);
} catch (Exception e) {
return null;
}
return out.toString();
}
最佳答案
警告:这不是合法的解决方案/答案,它只是一种解决方法,因为还没有人给我任何解决方案。
我制作了一个 xslt 表达式来将 Code-Base-JMeter-Jmx 转换为 Gui-Base-JMeter-Jmx
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="/">
<xsl:apply-templates />
<hashTree>
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
<xsl:copy-of select="HTTPSamplerProxy/elementProp[@elementType = 'HeaderManager']/collectionProp[@name='HeaderManager.headers']" />
</HeaderManager>
<hashTree />
</hashTree>
</xsl:template>
<xsl:template match="HTTPSamplerProxy/elementProp[@elementType = 'HeaderManager']" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
现在,如果在 JMeter 的下一个版本中他们更改了 jmx/xml 输出,那么我必须再次更改我的 xslt 以适应更改,这根本不是一个好方法。
所以我仍然渴望有一个合法的解决方案。
关于java - JMeter Recording Controller 记录不同格式的请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48334610/
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我有两个Rails模型,即Invoice和Invoice_details。一个Invoice_details属于Invoice,一个Invoice有多个Invoice_details。我无法使用accepts_nested_attributes_forinInvoice通过Invoice模型保存Invoice_details。我收到以下错误:(0.2ms)BEGIN(0.2ms)ROLLBACKCompleted422UnprocessableEntityin25ms(ActiveRecord:4.0ms)ActiveRecord::RecordInvalid(Validationfa
这个问题在这里已经有了答案:Railsformattingdate(4个答案)关闭4年前。我想格式化Time.Now函数以显示YYYY-MM-DDHH:MM:SS而不是:“2018-03-0909:47:19+0000”该函数需要放在时间中.现在功能。require‘roo’require‘roo-xls’require‘byebug’file_name=ARGV.first||“Template.xlsx”excel_file=Roo::Spreadsheet.open(“./#{file_name}“,extension::xlsx)xml=Nokogiri::XML::Build
我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西:
rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最