I usually create some small scraping script for my daily life. - Getting all comic's image and converting to e-book for my Kindle. - Surveying info for buying new house. - Helping my wife in collecting data for her new writing. - Transferring all my Facebook fanpage post to my personal blog And I did enjoyed my journey in scraping thing to make my life easier and full of joy.
Wonderful, are you also sharing your scripts with everyone?
Scrapism
21–30 of 30 posts
Re: Scrapism
#22A trick I think would be useful to include here is running scrapers in GitHub Actions that write their results back to the repository. This is free(!) to host, and the commit log gives an enormous amount of detail about how the scraped resource changed over time. I wrote more about this trick here: https://simonwillison.net/2020/Oct/9/git-scraping/ Here are 267 repos that are using it: https://github.com/topics/git-s…
I feel like this is bad manners. The runners are a shared resource and you risk getting their IPs blacklisted by the sites you're scraping. I think a strict reading of the GitHub Actions TOS may prohibit this sort of usage, too. > ... for example, don't use Actions as a content delivery network or as part of a serverless application ... > Actions should not be used for: ... any other activity unrelated to the product…
Re: Scrapism
#23It might be worth adding a section on distributed anonymous scrapers that use some form of messaging middleware to distribute the URLs to scrape. Regarding the anonymous aspect (independent of job distribution, of course), you could walk them through using https://github.com/aaronsw/pytorctl or even a rotating tor proxy. This is how I scraped all those Instagram locations + metadata we discussed about five years ago. Hope you’re doing well!
Re: Scrapism
#24This is from 2020. Besides a small change to the "Introduction to the Command Line" section, it has not been updated. Back in 2015, the author reported using CasperJS to scrape public LinkedIn profiles. The author reported this was a PITA. Here the author recommends using WebDriver implementations, e.g., chromedriver or geckodriver, in addition to scripting language frameworks such as Puppeteer and Selenium. Is scrap…
Hi - I'd be interested to hear more details about what approaches you suggest!
Retrieving the HTML
echo https://www.nytimes.com|yy025|nc -vv proxy 80 > 1.htm
yy025 is a flexible utility I wrote to generate custom HTTP from URLs. It is controlled through environmental variables. nc is a tcpclient, such as netcat. proxy is a HOSTS file entry for a localhost TLS proxy. The sequence "yy025|tcpclient" is normally contained in a shell script that adds a tag, something like #! /bin/sh
yy025 5>.1 >.2
read x ";
nc -vv proxy 80
yy045 is a utility that removes chunked transfer encoding.The benefit of using separate, small programs that do one thing will be illustrated in the solution for Problem 3.
Re: Scrapism
#25This is from 2020. Besides a small change to the "Introduction to the Command Line" section, it has not been updated. Back in 2015, the author reported using CasperJS to scrape public LinkedIn profiles. The author reported this was a PITA. Here the author recommends using WebDriver implementations, e.g., chromedriver or geckodriver, in addition to scripting language frameworks such as Puppeteer and Selenium. Is scrap…
Hi - I'd be interested to hear more details about what approaches you suggest!
NB. In 1.htm, NYT is using the tag for headlines, not as in the 2020 video.
Solution A - Use UNIX utilties
grep -o "]*>[^\//p'
The grep utility is ubiquitous, but the -o option is not.https://web.archive.org/web/20201202103125/https://pubs.open...
For example, Plan9 grep does not have an -o option.
This solution is fast and flexible, but not portable.
There are myriad other portable solutions using POSIX UNIX utilities such as sh, tr and sed. For small tasks like those in "web scraping" tutorials these can still be faster than Python (due to Python start up time alone).
Solution B - Use flex to make small, fast, custom utilities
Create a file called 1.l that contains
int fileno(FILE *);
#define jmp (yy_start) = 1 + 2 *
#define echo do {if(fwrite(yytext,(size_t)yyleng,1,yyout)){}}while(0)
%s xa xb
%option noyywrap noinput nounput
%%
\\> jmp xb;
\[^
Then compile with something like flex -8iCrf 1.l
cc -std=c89 -Wall -pedantic -I$HOME -pipe lex.yy.c -static -o yy1
And finally, yy1
This is faster than Python.Solution C - Extract values from JSON instead of HTML
The file 1.htm contains a large proportion of what appears to be JSON.
I wrote a quick and dirty WIP JSON reformatter that takes web pages as input called yy059. https://news.ycombinator.com/item?id=31174088
yy059
Sure enough, the JSON contains the headlines. One could rewrite Solution B to extract from the JSON instead of the HTML.Re: Scrapism
#26This is from 2020. Besides a small change to the "Introduction to the Command Line" section, it has not been updated. Back in 2015, the author reported using CasperJS to scrape public LinkedIn profiles. The author reported this was a PITA. Here the author recommends using WebDriver implementations, e.g., chromedriver or geckodriver, in addition to scripting language frameworks such as Puppeteer and Selenium. Is scrap…
Hi - I'd be interested to hear more details about what approaches you suggest!
Create a file called 2.l containing
int fileno(FILE *);
#define jmp (yy_start) = 1 + 2 *
#define echo do {if(fwrite(yytext,(size_t)yyleng,1,yyout)){}}while(0)
%s xa xb
%option noyywrap noinput nounput
%%
\\40href=\" jmp xb;
\" jmp 0;
[^\"]* echo;putchar(10);
.|\n
%%
int main(){ yylex();exit(0);}
Compile flex -8iCrf 1.l
cc -std=c89 -Wall -pedantic -I$HOME -pipe lex.yy.c -static -o yy1
And finally, yy2
This faster than Python and requires fewer resources.Re: Scrapism
#27This is from 2020. Besides a small change to the "Introduction to the Command Line" section, it has not been updated. Back in 2015, the author reported using CasperJS to scrape public LinkedIn profiles. The author reported this was a PITA. Here the author recommends using WebDriver implementations, e.g., chromedriver or geckodriver, in addition to scripting language frameworks such as Puppeteer and Selenium. Is scrap…
Hi - I'd be interested to hear more details about what approaches you suggest!
Create a file called 3.l containing
int fileno(FILE *);
#define jmp (yy_start) = 1 + 2 *
%s xa xb xc
%option noyywrap noinput nounput
%%
\"" yyterminate();
\" putchar(10);jmp xa;
[^\"]* fprintf(stdout,"%s%s","https://newyork.craigslist.org",yytext);
.|\n
%%
int main(){ yylex();exit(0);}
Compile flex -8iCrf 1.l
cc -std=c89 -Wall -pedantic -I$HOME -pipe lex.yy.c -static -o yy3
yy3 extracts and prints the URLs for the job pagesCreate a file called 4.l containing
int fileno(FILE *);
#define jmp (yy_start) = 1 + 2 *
#define echo do{if(fwrite(yytext,(size_t)yyleng,1,yyout)){}}while(0)
%s xa xb xc xd xe
%option noyywrap noinput nounput
%%
\\\"\> jmp xc;
[^\ jmp xe;
\[0-9]* echo;putchar(10);
.|\n
%%
int main(){ yylex();exit(0);}
Compile flex -8iCrf 1.l
cc -std=c89 -Wall -pedantic -I$HOME -pipe lex.yy.c -static -o yy4
yy4 extracts and prints the job catgeory name and totalcountWe can either solve this in steps where we create files or we can do it as a single pipeline. I personally find breaking a problem into discrete steps is easier.
In steps
echo http://newyork.craigslist.org|yy025|nc -vv proxy 80|yy045 > 1.htm;
ka;yy3 2.htm;ka-;
yy4
As a single pipeline echo http://newyork.craigslist.org|yy025|nc -vv proxy 80|y045|yy3|(ka;yy025)|nc -vv proxy 80|yy045|yy4;ka-
Shortened further by using a shell script called nc0 for the yy025|nc|yy045 sequence echo https://newyork.craigslist.org|nc0|yy3|(ka;nc0)|yy4
Thanks to yy025, we are using HTTP/1.1 pipelining. This is a feature of HTTP that almost 100% of httpd's support (I cannot name one that doesn't) however neither "modern" browsers nor cURL cannot take advantage of it. Multiple HTTP request are made over a single TCP connection. Unlike the Python tutorial in the video we are not "hammering" a server with multiple TCP connections at the same time, nor are we making a number of successive TCP connections that could "trigger a block". We are following the guidance of the RFCs which historically recommended that clients not open many connections to the same host at the same time. Here we only open one for retrievng all the jobs pages. Adding a delay between requests is unnecessary. We allow the server to return the results at its own pace. For most websites, this is remarkably fast. Craigslist is an anamaly and is rather slow.What are ka and ka-. yy025 sets HTTP headers acording to environmental variables. For example, the value of Connection is set to "close" by default. To change it,
Connection=keep-alive yy025 0.htm
Another way is to use aliases alias ka="export Connection=keep-alive;set|sed -n /^Connection/p";
alias ka-="export Connection=close;set|sed -n /^Connection/p";
ka;yy025 0.htm;ka-
yy025 is intended to be used with djb's envdir. Custom sets of headers can thus be defined in a directory.This solution uses less resources, both on the client side and on the server side, than a Python approach. It is probably faster, too.
Re: Scrapism
#28Earlier quoted context omitted.
Hi - I'd be interested to hear more details about what approaches you suggest!
Problem 2 - Extract href value from tags in NYT front page Create a file called 2.l containing int fileno(FILE *); #define jmp (yy_start) = 1 + 2 * #define echo do {if(fwrite(yytext,(size_t)yyleng,1,yyout)){}}while(0) %s xa xb %option noyywrap noinput nounput %% \ \40href=\" jmp xb; \" jmp 0; [^\"]* echo;putchar(10); .|\n %% int main(){ yylex();exit(0);} Compile flex -8iCrf 1.l cc -std=c89 -Wall -pedantic -I$HOME -pi…
Can't see reaching for something like that instead of something like
curl -s url | htmlq a --attribute href