Chrome Extension – how to. Кратък урок за създаване на Chrome добавка.

Ще се опитам да опиша простичко, как се разработва прост extension add-on за Chrome. Понякога е много полезно да се работи с подобни скриптове, особено при скрапване на web-съдържание, когато конвенционалните методи не работят или изискват прекалено много усилия.
За да се създаде подобен скрипт с потребителски интерфейс ще са ни необходими няколко файла:
manifest.json – всяка добавка (extension) за Chrome (а и за другите браузери) съдържа подобен скрипт, който предоставя важна информация на браузера. Повече тук: Manifest File Format
popup.html – стандартно наименование на файла с потребителския интерфейс, който се появява при клик с мишката върху добавката. Разбира се, можем да създадем добавка, която няма нужда от потребителски интерфейс, но в случая аз искам да имам. Името на този файл се посочва в manifest.json.
popup.js – файл, който се зарежда чрез popup.html. Можем и да нямаме подобен файл и да поместим javascript кода направо в popup.html. Но тенденциите в модерното програмиране съветват да се диференцира всичко – стилове, скриптове, html. В моя случай popup.js е двигателя на Chrome добавката. Той посочва какво, кога и къде да се активира.
getPagesSource.js – файл за инжектиране в web-страницата и извлича информацията от нея. Този файл се зарежда от popup.js.
icon.png – някаква иконка, която да се показва в листата с добавките на Chrome.

Нека създадем скрипт, който извлиза съдържанието на определени тагове, като използваме javascript функцията querySelectorAll(). Много приятна функция, която заменя в известна степен нуждата от XPath при web-скрапинга.

Да започваме! Първо създаваме manifest.json, като описваме какво прави тая добавка:

1
2
3
4
5
6
7
8
9
10
11
{
  "name": "Simple web scraper",
  "version": "1.0",
  "manifest_version": 2,
  "description": "Get content from tags through querySelector",
  "browser_action": {
    "default_icon": "icon.png",
    "default_popup": "popup.html"
  },
  "permissions": ["tabs", "<all_urls>"]
}

След това си правим потребителския интерфейс popup.html – бутончета, поленца, форми, стилове, каквото ни е кеф. В случая ще се огранича на минимума за моите нужди – текстово поле, бутон, слой за резултата:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html style=''>
<head>
 
</head>
<body style="width:400px;">
 
	<input type="text" id="selector" style="width:300px;" />
	<button id="getselector">Get Selector</button><br /><hr />
 
	<div id='message'>Injecting Script....</div>
 
	<script src='popup.js'></script>
</body>
</html>

В по-горния скрипт се вижда, че зареждам popup.js. Неговото съдържание е следното:

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
chrome.runtime.onMessage.addListener(function(request, sender) {
  if (request.action == "getSlectedContent") {
    message.innerHTML = request.source;
  }
});
 
document.querySelector('#getselector').addEventListener('click', winLoad);
 
function winLoad() {
 
  var message = document.querySelector('#message');
  var inputSel = document.querySelector('#selector').value;
 
  var queryInfo = {
    active: true,
    currentWindow: true
  };
 
  chrome.tabs.query(queryInfo, function(tabs) {
    chrome.tabs.sendMessage(
      tabs[0].id, {
        customSelector: inputSel
      },
      function(response) {
    });
  });
 
  chrome.tabs.executeScript(null, {
    file: "getPageContent.js"
  }, function() {
    if (chrome.runtime.lastError) {
      message.innerText = 'There was an error injecting script : \n' + chrome.runtime.lastError.message;
    }
  });
}

Чрез popup.js зарежда javascripta, който се инжектира в страницата – getPageContent.js:

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
chrome.runtime.onMessage.addListener(function(request, sender) {
  selElements(document, request.customSelector);
});
 
function selElements(document_root, s){
 
  // Tova go dobaviam zaradi kefa da polzvam foreach() v JavaScript
  var forEach = function (array, callback, scope) {
    for (var i = 0; i < array.length; i++) {
    callback.call(scope, i, array[i]);
    }
  };
 
  var myNodeList = document.querySelectorAll(s);
  var concatenateall = '';
  forEach(myNodeList, function (index, value) {
    concatenateall = concatenateall + value.innerHTML + "<hr />";
  });
 
  // return concatenateall;
  chrome.runtime.sendMessage({
    action: "getSlectedContent",
    source: concatenateall
  });
}

Това е.
Сега остава да заредим добавката в Chrome. Това става като отворим More Tools -> Extensions. След това кликаме на бутона Load unpacked и избираме директорията с файловете на нашата добавка.
На базата на тази добавка могат да се направят много други, тъй като съдържа базата за писане на добавки за Chrome.

Сорс кода може да се изтегли от тук: Chrome_Extension-Simple.zip

Кратко видео, което показва как може да се ползва добавката:

Bootstrap and tinyMCE examples

Bootstrap и tinyMCE са ми редовна комбинация. И за да не откривам топлата вода всеки път, ще постна малко подсетки с прост мой плъгин за tinyMCE.
Важно е да се промени javascript променливата current_host.
Bootstrap 3 and tinyMCE editor - examples
Demo
Download

Bootstrap 3 – custom menu, fixed bottom, header, back to top

В програмирането има едно правило, което перефразирано гласи да не търсиш топлата вода всеки път. За това качвам няколко базови кода за Bootstrap 3, които съм писал или копирал и променял. Помогнал съм си леко с Less за някои стилове.

Custom menu
Нищо ново. Добавено е само малко CSS-кодиране на менюто, което се предлага стандартно с Bootstrap.

Bootstrap 3- custom menu

Bootstrap 3- custom menu

Демо

Header
Напаснал съм отделните слоеве с помощта на Boostrap стиловете col-*-push и col-*-pull, така че да има приличен респонзив.

Bootstrap 3- header

Bootstrap 3- header

Bootstrap 3- header

Демо

Fixed bottom
Фиксиран фуутер за мобилни устройства – особено полезно при писане на мобилно приложение, базирано на HTML.

Bootstrap 3- fixed bottom

Bootstrap 3- fixed bottom

Демо

Back to top бутон
Клиентите често искат подобна опция. Кода е няколко реда и има и малко JavaScript, освен CSS-а.

Bootstrap 3- back to top

Демо

Допълнително в архива съм добавил и Bootstrap 3 – login form.

Изтегляне на кода: header_menu_fixed-bottom_back-to-top_login-form.zip

===============
Добавям и още 2 вертикални менюта

Bootstrap 3 – Drop Down menu – only CSS
Bootstrap 3 - CSS Drop Down menu - CSS_only
Демо
Изтегляне

Bootstrap 3 – Drop Down menu – CSS and JavaScript
Bootstrap 3 - CSS Drop Down menu - CSS and JS
Демо
Изтегляне

===============
Bootstrap 3 – h-background line – CSS only

bs3 - horizontal backgrounnd line
Demo
Download

Bootstrap 3 – Login form

Bootstrap 3 - Login Form
От известно време се каня да променя логин формата за админ панела на проектите, които правя. Направих една форма, която не знам дали ще ползвам, но ще ми е полезна като отправна точка. За да си помогна за стиловете използвах Less (език за стилови множества или CSS) и GUI-то SimpLESS – портабъл е и работи доста леко за разлика от други подобни.

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// 		MIXINS
//  ==========================================
.rounded-corners (@radius1: 5px, @radius2: 5px, @radius3: 5px, @radius4: 5px) { 
	-webkit-border-radius: @radius1 @radius2 @radius3 @radius4; 
	-moz-border-radius: @radius1 @radius2 @radius3 @radius4; 
	-ms-border-radius: @radius1 @radius2 @radius3 @radius4; 
	-o-border-radius: @radius1 @radius2 @radius3 @radius4; 
	border-radius: @radius1 @radius2 @radius3 @radius4; 
}
 
.drop-shadow (@x: 0, @y: 1px, @blur: 2px, @spread: 0, @alpha: 0.25) {
	-webkit-box-shadow:	@x @y @blur @spread rgba(0, 0, 0, @alpha);
	-moz-box-shadow:	@x @y @blur @spread rgba(0, 0, 0, @alpha);
	box-shadow:		@x @y @blur @spread rgba(0, 0, 0, @alpha);
}
 
.gradient (@startColor: #eee, @endColor: white) {
	background-color: @startColor;
	background: -webkit-gradient(linear, left top, left bottom, from(@startColor), to(@endColor));
	background: -webkit-linear-gradient(top, @startColor, @endColor);
	background: -moz-linear-gradient(top, @startColor, @endColor);
	background: -ms-linear-gradient(top, @startColor, @endColor);
	background: -o-linear-gradient(top, @startColor, @endColor);
}
 
 
 
// 		Colors
//  ==========================================
@silver_light: #edf1f2;
@silver_white: #f7f8fa;
@silver_dark: #eef7fc;
@silver_border: #c3d5d9;
@grey: #8f8f8f;
@blue_dark: #76ccea;
@blue_light: #badff2;
 
 
// 		Styles
//  ==========================================
body {
	background-color: @silver_light;
}
 
.container.lf{
	width: 322px;
	color: @grey;
	a {color: @grey;}
 
		.logf {
			margin-top: 50px;
			.rounded-corners(5px, 5px, 5px, 5px);
			.drop-shadow(0px, 0px, 6px, 2px, 0.05);
		}
 
		.lfhead, .lfbody, .lffooter{
			border: 1px solid @silver_border;
			background-color: @silver_white;
			min-height: 20px;
			// line-height: 15px;
		}
 
		.lfhead {
			border-bottom: 0;
			.rounded-corners(5px, 5px, 0, 0);
		}
 
		.lfbody {
			border-top: 0;
			border-bottom: 0;
 
			.input-group-addon {
				color: @grey;
			}
			 .form-control:focus {
			 	.drop-shadow(0px, 0px, 6px, 2px, 0.05);
			 	border-color: @blue_dark;
			 }
		}
 
		.lffooter {
			background-color: @silver_dark;
			.rounded-corners(0, 0, 5px, 5px);
			padding-top: 16px;
 
			.text-left {
				padding-top: 8px;
			}
 
			label {
				font-weight: normal;
				color: @grey;
			}
 
			input[type='button'], input[type='reset'], input[type='submit'] {
				.rounded-corners(18px, 18px, 18px, 18px);
				border-color: @blue_dark;
				.gradient(@blue_light, @blue_dark);
				font-weight: bold;
				.drop-shadow(0px, 1px, 2px, 1px, 0.10);
				text-shadow: 1px 1px @blue_dark;
 
				&:hover {
					.gradient(@blue_dark, @blue_light);
				}
			}
		}
 
	.lflinks {
		padding-top: 8px;
	}
 
}

HTML кода:

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
37
38
39
<div class="container lf">
   <div class="row logf text-center">
      <form action="" method="post" >
         <div class="col-xs-12 lfhead">
         </div>
         <div class="col-xs-12 lfbody">
            <div class="form-group">
               <div class="input-group">
                  <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
                  <input id="email" type="email" class="form-control" name="email" value="" tabindex="1" placeholder="Email Address">
               </div>
            </div>
            <div class="form-group">
               <div class="input-group">
                  <span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
                  <input id="password" type="password" class="form-control" name="password" value="" tabindex="2" placeholder="Password">                    
               </div>
            </div>
         </div>
         <div class="col-xs-12 lffooter">
            <div class="col-xs-6">
               <div class="form-group text-left">
                  <input type="checkbox" tabindex="3" class="" name="remember" id="remember">
                  <label for="remember"> Remember Me</label>
               </div>
            </div>
            <div class="col-xs-6">
               <div class="form-group text-right">
                  <input type="submit" name="login-submit" tabindex="4" class="btn btn-primary" value="Login">
               </div>
            </div>
         </div>
      </form>
   </div>
   <div class="row lflinks">
      <div class="col-xs-6 text-left"><a href="">Register</a></div>
      <div class="col-xs-6 text-right"><a href="">Forgot password</a></div>
   </div>
</div>

Останалото форматиране си идва от Bootstrap 3.
Демо на страницата: BS3 Login Form
Download: bs3-login_form.zip

Bootstrap 3 dropdown login form example

Търсих си неразкрасена логин форма за Bootstrap 3. Трябваше да я набутам в бутон на на nav-панела. Не намерих нищо свястно, ам тя работата е елементарна. Ще покажа 2 различни примера.
Bootstrap login form - dropdown, popover
BS3 Login form с popover и html код разположен някъде в страницата:
Javascript – поставя се най-долу в кода на страницата

1
2
3
4
5
6
7
$('button[data-toggle=popover]').popover({ 
    html : true,
    //trigger: "click", // може да се смени
    content: function() {
      return $('#popover_content_wrapper').html();
    }
});

HTML-кода:

1
2
3
4
5
6
7
8
9
10
11
12
<div id="popover_content_wrapper" style="display: none">
  <form action="" role="form">
    <div class="form-group">
      <label for="user">User</label>
      <input type="text" class="form-control" id="user" placeholder="User" />
      <label for="password">Password</label>
      <input type="password" class="form-control" id="password" placeholder="Password" />
    </div>
      <button type="submit" class="btn btn-default">Sign in</button>
 
  </form>
</div>

BS3 Login form с dropdown:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<li>
 
  <div class="dropdown">
    <button type="button" class="btn btn-default navbar-btn" data-toggle="dropdown">Login</button>
 
    <div class="dropdown-menu" style="padding: 10px; background: #ddd">
      <form action="" role="form">
        <div class="form-group">
          <label for="user">User</label>
          <input type="text" class="form-control" id="user" placeholder="User" />
          <label for="password">Password</label>
          <input type="password" class="form-control" id="password" placeholder="Password" />
        </div>
        <button type="submit" class="btn btn-default">Sign in</button>
      </form>
    </div>
  </div>
 
</li>

Пример с 2-те форми може да се види тук:
Bootstrap 3 dropdown login form example

CSS – Attribute Selectors

CSS – Attribute Selectors

CSS разполага с няколко “странни” символа, които в други езици са известни като wildcards. Тези символи представляват селектори на текст и могат да съвпадат с части от текста.

  • [att^=val] – започва с “val”
  • [att$=val] – завършва с “val”
  • [att*=val] – съдържа “val”

Атрибут селекторите могат да се използват за всякакви атрибути на таговете, като класове (.class1, class2…) или идентификатори(#id1, id2…), href, title, name и т.н.

Примери за прилагане на стилове с атрибут селектора “започва с”:
begin with css selector
The “begins with” CSS selector – DEMO

Примери за прилагане на стилове с атрибут селектора “завършва с”:
ends with css selector
The “ends with” CSS selector – DEMO

Примери за прилагане на стилове с атрибут селектора “съдържа”:
contains css selector
The “contains” CSS selector – DEMO

Simple JavaScript rich text format editor

Прост, базов RTF редактор за сайт
JS_WisWyg_Editor_by_Ned
Дълго съм се чудил кой е най-подходящия JavaScript Wysiwyg редактор с най-много възможности за напасване към сайт. Ползвал съм NicEdit, TinyMCE и други, които сам съм писал, неподдържащи rich text format (RTF). Обаче напасването на тези редактори към различни дизайни е развибащо от към бачкане и тестване в различните браузери. Реших да почопля няколко такива редактора и да разбера кое е толкова загадъчно и сложно, за да се напише подобен редактор. Истината е тривиална и се казва – iFrame. Този таг се ползва в почти всички подобни редактори, точно заради поддръжката му на RTF. При събмитване на формата, цялото съдържание на iform се подава на textarea, който си седи удобно скрит.

Това е моят редактор, без CSS-форматиране, като в примера добавям и опция за обработка на текста от базата данни, където присъства без тагове, с ексейпнати малко по-рискови символи.

<?php
$field = '<a href="aloooha">Test\'ed. kavicha</a> dyra, byra.<br />Още текст и още "кирилица".';
$clearpost = $field;
 
 
if(isset($_POST['button'])){
	echo $_POST['myTextArea'];
	$clearpost = $_POST['myTextArea'];
}
 
//$clearpost = preg_replace('@delete|select|insert|update|where@i',"", $clearpost); // Почистване на 
//$clearpost = preg_replace('/[\x7f-\xff]/', "", $clearpost); // Clear Dirty Data
$clearpost = preg_replace("/;/", "&#59;", $clearpost);
$clearpost = preg_replace("/\*/", "&#42;", $clearpost);
$clearpost = preg_replace("/\r\n/", "<br />", $clearpost);
$clearpost = preg_replace("/\r/", "<br />", $clearpost);
$clearpost = preg_replace("/\n/", "<br />", $clearpost);
$clearpost = preg_replace("/</", "&lt;", $clearpost);
$clearpost = preg_replace("/=/", "&#61;", $clearpost);
$clearpost = preg_replace("/>/", "&gt;", $clearpost);
$clearpost = preg_replace("/\'/", "&#39;", $clearpost);
$clearpost = preg_replace("/\`/", "&#96;", $clearpost);
$clearpost = preg_replace("/\"/", "&quot;", $clearpost);
 
if (!get_magic_quotes_gpc()) $clearpost = preg_replace('@\\\@', "&#92;", $clearpost);
else {
	$clearpost = stripslashes($clearpost);
	$clearpost = preg_replace('@\\\@', "&#92;", $clearpost);
}
 
 
$clearpost = preg_replace("/&#39;/", "\&#39;", $clearpost); // Ескейпване на единичната кавичка, за да може да се показва в iframe!!!
?>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=windows-1251" /> 
<script src="wiswyg_ned/nedEditor.js"></script>
<script type="text/javascript">
 
window.onload=function(){
	iFrameOn();
	if(isIE){
		var myFrame = document.getElementById('richTextField');
		var frameDoc = myFrame.contentDocument || myFrame.contentWindow;
 
		if (frameDoc.document){
		  frameDoc = frameDoc.document;
		}
		frameDoc.write ('<?php echo html_entity_decode($clearpost, ENT_QUOTES); ?>') ;
	} else {
		window.frames['richTextField'].document.body.innerHTML = '<?php echo html_entity_decode($clearpost, ENT_QUOTES); ?>' ;
	}
}
</script>
</head>
<!-- <body onLoad="iFrameOn();" > -->
<body>
<form action="" enctype="multipart/form-data" name="myForm" id="myform" method="post">
<div id="wysiwyg_cp" style="padding:8px; width:700px;">
	<input type="button" onClick="iBold()" value="B"> 
	<input type="button" onClick="iUnderline()" value="U">
	<input type="button" onClick="iItalic()" value="I">
	<input type="button" onClick="iFontSize()" value="Text Size">
	<input type="button" onClick="iForeColor()" value="Text Color">
	<input type="button" onClick="iHorizontalRule()" value="HR">
	<input type="button" onClick="iUnorderedList()" value="UL"><br />
	<input type="button" onClick="iOrderedList()" value="OL">
	<input type="button" onClick="iLink()" value="Link">
	<input type="button" onClick="iUnLink()" value="UnLink">
	<input type="button" onClick="iImage()" value="Image">
	<input type="button" onClick="iRemoveFormat()" value="Remove Format"> 
</div>
	<!-- Hide(but keep)your normal textarea and place in the iFrame replacement for it -->
	<textarea style="display:none;" name="myTextArea" id="myTextArea" cols="100" rows="14"></textarea>
 
	<iframe name="richTextField" id="richTextField" ></iframe>
	<br />
	<input type="submit" name="button" id="button" value="Make Changes" onClick="javascript:submit_form();"/>
</form>
</body>
</html>

Съдръжанието на JavaScript файла:

// Check Browser
var isOpera = !!(window.opera && window.opera.version);  // Opera 8.0+
var isFirefox = testCSS('MozBoxSizing');                 // FF 0.8+
var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
    // At least Safari 3+: "[object HTMLElementConstructor]"
var isChrome = !isSafari && testCSS('WebkitTransform');  // Chrome 1+
var isIE = /*@cc_on!@*/false || testCSS('msTransform');  // At least IE6
 
function testCSS(prop) {
    return prop in document.documentElement.style;
}
//====================
 
 
function iFrameOn(){ 
    richTextField.document.designMode = 'On';
    //window.frames['richTextField'].document.body.innerHTML = '<a href="aloooha">Aloha</a> dyra, byra.<br />Още текст има тук.';	
}
function iRemoveFormat(){
    richTextField.document.execCommand('removeformat',false,null); 
}
function iBold(){
    richTextField.document.execCommand('bold',false,null); 
}
function iUnderline(){
    richTextField.document.execCommand('underline',false,null);
}
function iItalic(){
    richTextField.document.execCommand('italic',false,null); 
}
function iFontSize(){
    var size = prompt('Enter a size 1 - 7', '');
    richTextField.document.execCommand('FontSize',false,size);
}
function iForeColor(){
    var color = prompt('Define a basic color or apply a hexadecimal color code for advanced colors:', '');
    richTextField.document.execCommand('ForeColor',false,color);
}
function iHorizontalRule(){
    richTextField.document.execCommand('inserthorizontalrule',false,null);
}
function iUnorderedList(){
    richTextField.document.execCommand("InsertOrderedList", false,"newOL");
}
function iOrderedList(){
    richTextField.document.execCommand("InsertUnorderedList", false,"newUL");
}
function iLink(){
    var linkURL = prompt("Enter the URL for this link:", "http://"); 
    richTextField.document.execCommand("CreateLink", false, linkURL);
}
function iUnLink(){
    richTextField.document.execCommand("Unlink", false, null);
}
function iImage(){
    var imgSrc = prompt('Enter image location', '');
    if(imgSrc != null){
        richTextField.document.execCommand('insertimage', false, imgSrc); 
    }
}
function submit_form(){
    var theForm = document.getElementById("myform");
    theForm.elements["myTextArea"].value = window.frames['richTextField'].document.body.innerHTML;
    theForm.submit();
}

Сорс кода: wiswyg_by_ned.rar
Demo нa кода.

Нова версия на BGHotelCMS

Най-накрая намерих малко време да обновя проекта си, с който искам да подпомогна българския туризъм – BGHotelCMS 1.01.
Кода го пренаписах от нулата, като използвах PHP MiniTemplator, за да разделя програмирането от дизайна. Това ми помогна да съкратя доста кодирането и ми позволява да създавам и добавям много лесно нови теми за дизайна.

Повече подробности за този проект могат да се видят на страницата му – http://bghotelcms.nediko.info/

Web Mechanize engines

Съществуват много приложение на ботовете за автоматизиране на web-среда, т. нар. Web Mechanize engines. Тук ще разгледам няколко такива системи за механизиране и автоматизиране на работата с web-страници.

Приложение на Mechanize-ботовете

С помощта на скриптовете за автоматизиране на Web могат да се:

  • Попълват множество бланки и формуляри с еднородна информация
  • Търси в мрежата
  • Автоматизират регистрации. Примерно автоматизирано попълване на бланки за Гражданска отговорност.
  • Извличане на информация от множество сайтове наведнъж и съхраняването и.

и т.н.

Някои по-популярни Mechanize системи

WWW::Mechanize – Perl модул, написан от Jesse Vincent. Един от първите подобни модули за автоматизирано браузване.
mechanize – Python алтернатива на по-горния модул. Включва достъпните (супер лесни за работа даже) mechanize.Browser и mechanize.UserAgentBase имплементации на urllib2.OpenerDirector.
LWP – The World-Wide Web библиотека отново за Perl.
twill – базиран на Python изключително прост език за автоматизирано браузване. Изпълнява се от команден ред и изисква Python 2.3 или по-нов.
zope.testbrowser – още един модул за Python.
Watir – библиотека на Ruby за автоматизирано браузване. Супер лесна за работа.
Scriptable Browser – PHP алтернатива на горните модули. Все още има какво да се желае, но определено доста интересен проект.
Snoopy – PHP клас, който също е насочен към автоматизирано браузване.
Compass_Mechanize – PHP пакет, който е наречен от авторите “WWW::Mechanize for PHP”. Изисква Zend Framework.

Firefox Mechanize extensions

Освен посочените по-горе модули или езици, съществуват и приложения, които работят в средата на браузъра. Ще посоча някои механизатори за Firefox:
iMacros – Един от най-яките автоматизатори. Записва всички събития и генерира изключително лек и четим код. Не е нужно да изучвате скриптов език. Супер елементарно се работи с тази добавка.
iMacros Command Line – това брилянтно разширение разполага и с поддръжка на командния ред.
Chickenfoot – много любим механизатор. Има си собствен език за писане на скриптовете, който е доста лесен. Разполага и с рекордер на събитията, както и старт от командния ред: firefox -cf-run.
DejaClick – още една добавка за Firefox, която може да записва събития. Генерира малко трудно-четими скриптове, иначе пък си има някои полезни опции.
Selenium IDE – един от първите автоматизиращи плъгини за Firefox. Помня, че четох за него преди поне 6-7 години, дет се вика от зората на пандата. Не съм го ползвал, защото тогава не ми е бил необходим, но определено заслужава да е в този списък.

Разбира се има и много стари и достъпни методи за автоматизиране на по-леки задачи в Web. Например с cURL и wget понякога могат да се постигнат чудеса.