Categories
Challenge Development

AirTable scrape challenge

I need to get info from AirTable, see a table example.

The problem is that data are loaded highly dynamically. HTML contains only the information that you currently see on the browser screen.

enter image description here

If there are a lot of records then it is difficult to collect such a table. One of the possible ways is to calculate the size of the screen and rows in the table. Then using the browser automation and use to make a script that will scroll through it bit by bit and collect data.

Is there any other feasible way to get data of a table? For example there is a HTTP requests coding way to get dynamic data.

JS infinite scroll does not work for AirTable either.

Please comment down here if having some tips, hints.

Categories
Featured Monetize

2022 laid off [tech] Specialists Data Set

Companies like Facebook owner Meta, e-commerce behemoth Amazon and ride-hailing firm Lyft have announced job cuts in recent weeks as the US tech industry deals with an uncertain economic climate.

DW, 01.12.2022

Data Set

So, we’ve got lists (as a data directory) of those laid off tech professionals (from open sources). If someone is interesting in the data, we would gladly share it for a cost (starting from $5 per entry). The filtering by role, expertise and location is available.

Sample

Take a look at a data sample (no emails) below.

Please enquire me at: igor [dot] savinkin [at] gmail [dot] com for a customized data set.

Categories
Development

Google Sheets or MS Excel to scrape business directories ?

We’ve already stated some Tips and Tricks of scraping business directories or data aggregators sites. Yet recently someone has asked us to do aggregators’ scraping in the context of Google Sheets and/or MS Excel.

Categories
Challenge Development

Yelp scraping for high quality B2B leads

Recently we’ve performed the Yelp business directory scrape for acquiring high quality B2B leads (company + CEO info). This forced us to apply many techniques like proxying, external company site scrape, email verification and more.

Categories
Development Guest posting

Scrape ‘Ticketmaster’ using Selenium with Python

We’ve got some code provided by Akash D. working on ticketmaster.co.uk. He automates browser (Chrome as well as Edge) using Selenium with Python. The rotating authenticated proxies are leveraged to keep undetected. Yet, the site is protected with Distil network.

Categories
Challenge Development

Bypass GoDaddy Firewall thru VPN & browser automation

Recently we encountered a website that worked as usual, yet when composing and running scraping script/agent it has put up blocking measures.

In this post we’ll take a look at how the scraping process went and the measures we performed to overcome that.

Categories
Development

Scrapy to get dynamic business directory data thru API

In this post I want to share on how one may scrape business directory data, real estate using Scrapy framework.

Categories
Development

PHP Curl POSTing JSON example

We share here the example of CURL POSTing JSON data to obtain an Octoparse API token.

<?php
$base_url = "https://openapi.octoparse.com";
$token_url = $base_url . '/token';

$post =[
    'username' => 'igorsavinkin',
	'password' => '<xxxxxx>', 
	'grant_type' => 'password' 
];

$payload = json_encode($post);

$headers = [
	'Content-Type: application/json' ,
	'Content-Length: ' . strlen($payload)
];

$timeout = 30;
$ch_upload = curl_init(); 
curl_setopt($ch_upload, CURLOPT_URL, $token_url);
if ($headers) { 
	curl_setopt($ch_upload, CURLOPT_HTTPHEADER, $headers);
} 
curl_setopt($ch_upload, CURLOPT_POST, true); 
curl_setopt($ch_upload, CURLOPT_POSTFIELDS, $payload /*http_build_query($post)*/ );
curl_setopt($ch_upload, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch_upload, CURLOPT_CONNECTTIMEOUT, $timeout);
$response = curl_exec($ch_upload);

if (curl_errno($ch_upload)) {
    echo 'Curl Error: ' . curl_error($ch);
}

curl_close($ch_upload); 
//echo 'Response length: ', strlen($response);
echo  $response ;
$fp = fopen('octoparse-api-token.json', 'w') ;
fwrite($fp, $response );
fclose($fp);
Categories
Development Web Scraping Software

My experience of choosing web scraping platform for company critical data feed

Recently we engaged with the online e-commerce startup for the need of gov. tenders/RFP scraping. Since the project size is immense , we have to switch from the hand made scripting extractors to a enterprise grade scraping platform. Below I share my experience of the scraping platforms as a feature table.

   Service   ResidentialCost/monthTraffic/month$ per GBRotatingIP whitelistingPerformance and moreNotes
MarsProxies
N/AN/A3.5yesyes 500K+ IPs, 190+ locations
Test results
SOCKS5 supported
Proxy grey zone restrictions
Oxylabs.io
N/A25 GB9 - 12

"pay-as-you-go" - 15
yesyes100M+ IPs, 192 countries

- 30K requests
- 1.3 GB of data
- 5K pages crawled
Not allowing to scrape some of grey zone targets, incl. Linkedin.
Smartproxy
Link to the price page

N/A5.2 - 7

"pay-as-you-go" - 8.5
yesyes65M+ IPs, 195+ countriesFree Trial
Not allowing to scrape some of grey zone targets, incl. Linkedin.
Infatica.io
N/AN/A3 - 6.5

"pay-as-you-go" - 8
yesyesOver 95% success
*Bans from Cloudflare are also few, less than 5%.
Black list of sites —> proxies do not work with those.
  • 1000 ports for one Proxy List
  • Up to 20 Proxy Lists at a time
  • Using via API Tool
  • ISP-level targeting
  • Rotation time selection
Mango Proxy
N/A1-50 GB3-8"pay-as-you-go" - 8yesyes90M+ IPs, 240+ countries
IPRoyal
N/AN/A$4.55yesyes32M+ IPs, 195 countriesNot allowing to scrape some of grey zone targets, incl. Facebook. List of bloked sites.
Rainproxy.io yes$ 4from 1 GB4yes
BrightDatayes15
ScrapeOps Proxy AggregatoryesAPI Credits per monthN/A N/AyesAllows multithreading, the service provides browsers at its servers. It allows to run N [cloud] browsers from a local machine.
The number of threads depends on the subscription: min 5 threads.
The All-In-One Proxy API that allows to use over 20+ proxy providers from a single API
Lunaproxy.comyesfrom $15x Gb per 90 days0.85 - 5 Each plan allows certain traffic amount for 90 days limit.
LiveProxies.ioyesfrom $454-50 GB5 - 12yesyesEg. 200 IPs with 4 GB for $70.00, for 30 days limit.
Charity Engine -docsyes-- starting from 3.6
Additionally:
CPU computing
- from $0.01 per avg CPU core-hour
- from $0.10 per GPU-hour - source.
failed to connect so far
proxy-sale.comyesfrom $17N/A
3 - 6

"pay-as-you-go" - 7
yesyes10M+ IPs, 210+ countries30 days limit for a single proxy batch
Tabproxy.comyesfrom $15N/A
0.8 - 3
(lowest price is for a chunk of 1000 GB)
yesyes 200M+ IPs, 195 countries,30-180 days limit for a single proxy batch (eg. 5 GB)
proxy-seller.comyesN/A
N/A
4.5 - 6

"pay-as-you-go" - 7
yesyes15M+ IPs, 220 countries- Generation up to 1000 proxy ports in each proxy list
- HTTP / Socks5 support
- One will be able to generate an infinite number of proxies by assigning unique parameters to each list
Categories
Development

Simple Apify Puppeteer crawler

The Apify crawler is to gather names, addresses, emails of the web urls.

const Apify = require('apify');
var total_data=[];
const regex_name = /[A-Z][a-z]+\s[A-Z][a-z]+(?=\.|,|\s|\!|\?)/gm
const regex_address = /stand:(<\/strong>)?\s+(\w+\s+\w+),?\s+(\w+\s+\w+)?/gm;
const regex_email = /(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/i;
Apify.main(async () => {
    const requestQueue = await Apify.openRequestQueue('123');
    await requestQueue.addRequest(new Apify.Request({ url: 'https://www.freeletics.com/de/pages/imprint/' }));
    await requestQueue.addRequest(new Apify.Request({ url: 'https://di1ara.com/pages/impressum' }));
	console.log('\nStart PuppeteerCrawler\n');
    const crawler = new Apify.PuppeteerCrawler({
        requestQueue,
        handlePageFunction: async ({ request, page }) => {
            const title = await page.title();
            console.log(`Title of ${request.url}: ${title}`);
			const page_content = await page.content();
            console.log(`Page content size:`, page_content.length);
            let obj = { 'url' : request.url }; 
	 
			console.log('Names:');
			while ((m = regex_name.exec(page_content)) !== null) {
				// This is necessary to avoid infinite loops with zero-width matches
				if (m.index === regex_name.lastIndex) {
					regex_name.lastIndex++;
				}
				
				// The result can be accessed through the `m`-variable.
				m.forEach((match, groupIndex) => {
					console.log(`Found match, group ${groupIndex}: ${match}`);
					if (match !='undefined' ) { 
						obj['names'] +=  match + ', ';
					}
				}); 
				
				
			}	
			console.log('\nAddress:');
			while ((m = regex_address.exec(page_content)) !== null) {
				// This is necessary to avoid infinite loops with zero-width matches
				if (m.index === regex_address.lastIndex) {
					regex_address.lastIndex++;
				}
				
				// The result can be accessed through the `m`-variable.
				m.forEach((match, groupIndex) => {
					console.log(`Found match, group ${groupIndex}: ${match}`);
				});
				m[0] = m[0].includes('</strong>') ? m[0].split('</strong>')[1] : m[0];
				m[0] = m[0].replace('<', '');
				obj['address']= m[0] ?? '';
			}
			console.log('\Email:');
			while ((m = regex_email.exec(page_content)) !== null) {
				// This is necessary to avoid infinite loops with zero-width matches
				if (m.index === regex_email.lastIndex) {
					regex_email.lastIndex++;
				}
				
				// The result can be accessed through the `m`-variable.
				m.forEach((match, groupIndex) => {
					console.log(`Found match, group ${groupIndex}: ${match}`);
				}); 
				if (m[0]) 
				{
					obj['email'] = m[0];
					break;
				}
			}
			total_data.push(obj);
			console.log(obj);
        },
        maxRequestsPerCrawl: 2000000,
        maxConcurrency: 20,
    });
    await crawler.run();
	console.log('Total data:');
	console.log(total_data);
});