Como eu lutei contra o roubo ... usando php


Quando pagamos diariamente pelos serviços, é uma compra de serviços.
Quando pagamos diariamente por nada (às vezes sem nem mesmo saber) - isso é roubo.

Boa tarde, leitores de Habr!

Como tudo começou


Eu queria roubar menos, e vamos lutar contra isso! Mas, manualmente, era muito cansativo, longo e ineficaz; então surgiu a ideia de automatizar esse negócio.

Sobre qual dos "roubos" eu? Sobre onde nós, caminhando na Internet, clicamos no botão "assistir vídeo", alguma página é carregada, por algum motivo o vídeo não é reproduzido, saímos e seguimos adiante, mas, na verdade, "voluntariamente" ativamos o serviço para receber o que algo que ninguém jamais viu por uma taxa nominal de 30 rublos por dia em sua conta de celular. Nas pessoas, isso é chamado de wap-click ou assinaturas móveis, e as operadoras móveis criam vários nomes bonitos. Ainda assim, não inclua o roubo de botões de vídeo na lista de serviços.

Aqui está um pouco mais detalhadamente. E aqui está uma história sobre uma boa maneira de "ganhar dinheiro".

Existem muitos casos descritos de assinaturas não totalmente voluntárias, por exemplo. Não escrito - muito mais.

Os lutadores também têm:


O que e por que foi automatizado


Pesquise e bloqueie anúncios no painel do editor do Google AdSense.
O objetivo é aumentar a eficiência do bloqueio e liberar o tempo gasto na limpeza manual.

A essência do problema e as soluções disponíveis
Por muitos anos (a primeira menção de algo semelhante que eu descobri foi no verão de 2014), os editores capturaram manualmente os fluxos de "mortes de Yakubovich", "risers de pedra", "assista ao vídeo, clique em assistir" e outros maus espíritos ( início , continuação ), esse processo quase nenhuma automação 1 e parecia quase impossível.

1 Existem (pelo menos uma vez) duas soluções, mas elas têm requisitos bastante sérios que nem todos podem pagar.
Estas mesmas soluções:

  1. Limpador do AdSense . É preciso muito extra. Software.
  2. AdsAutomation . O script para controlar o navegador Google Chrome (como eu o entendo, no ZennoPoster). É necessário um PC separado. E, no momento, o projeto foi excluído do GitHub.

Se você cria um software que substitui a pessoa que está bloqueando o anúncio, isso deve ser feito levando em consideração vários requisitos:

  • deve trabalhar no hardware e software que quase todos os proprietários de sites possuem;
  • Não exija software adicional e altere as configurações existentes;
  • Fácil de instalar e configurar para que o usuário médio possa entregar.
.

Em geral, php (com cURL) terá o que é preciso. Você pode fazer o upload diretamente para o seu site e trabalhar sem computadores adicionais e outras dificuldades.

E um refinamento para os requisitos.
Como a solução era para ser automatizada em php, portanto, iniciando via cron, o armazenamento das configurações do usuário e dos dados temporários deve estar em disco (não em um cookie). Somente a chave para acessar o painel de controle será armazenada em cookies. Para a elite que não tem a capacidade de configurar o cron, mas pode manter uma guia aberta em um PC / tablet / smartphone, será adicionada a capacidade de executar periodicamente um timer em Javascript.

O que o início ou a API do Google prenunciou


E para o AdSense, existe uma API, de alguma forma eu a vi pelo canto do olho e não fui fundo. Agora é a hora de mergulhar. Existem muitas possibilidades, mas aconteceu que nem aqui , bem, nada foi descrito sobre a API da CPU . Deseja assistir a anúncios que estão girando no site, por favor - manualmente.

Iniciar


A interface do Google AdSense é construída no AngularDart, tudo parece bonito e bastante complicado do ponto de vista do dispositivo.

Primeiro, observei as ferramentas de desenvolvedor do Google Chrome na guia "Rede" para "escutar" como essa interface sofisticada se comunica com o servidor. Havia muitos pedidos por lá, os mais interessantes para mim estavam na seção “XHR and Fetch”, e lá encontrei algo que parecia bastante provável, se você pensar com cuidado. Por exemplo, uma das solicitações de postagem:

A cadeia transmitida.
{"method":"searchArcApprovals","params":"{\"1\":\"ca-pub-8958890276790964\",\"2\":{\"1\":0,\"2\":1,\"3\":0,\"4\":{\"1\":{\"1\":\"AClZvXKL6S3HChRty5YBa81BLWDBQkb3FYDsifZ9V/mBTKbOGlj3gMWVpzTtXggA1880Le9NyVZIicNm/4pz724e/MO8fyLfjOReF205cyjLV9C8OCCeKe7VvZHyvyKpXh8x9smTQ0n8qIIqzuIXle5UK0hD4VBkZDvy//qoSPRCr94UtWYqqi//Rot22LJ2JFNjWEGb4n1YQbAw0cKWPR3LAugPBajInWXEFGWJRTnmY2TkI5VzUzIkcXpJ/bkajn3c8GnecCfFNvNhGLS10VXdRwiykngG3xfoMTRhQOR5GXbm4kwdIhzQUM/d6xP0Xda3FOIZGGk9bymneg+9oDY+rMFiRfDFCb66g50t9J9r++oHXjek09Ci1rqC7LOw2pvkqp3hjG6RyVmsiT/eWGq+OsfjE7CgRk43QIRMSa+jlZBQhARUPlpUXzyZyoTiIPTRZ5ND/4MnIMqaUWSRoDGffiE/XkHJPEkNZtLX2XR5gZ3x5/K+ejU/fqxfZIjI6A3kueJybNA46wSLbmflhDCGDJEE2aeYemLFGqNzFG43B80LzU3yuwgZhrLu/jaMvBJozi0nq+gXEz6r+8tic4fvsQ9lWDA+IXzXw6MKzamgfWV0ORGDW0+966KIY6IkjtIlNRKGyp3pSAd2Po+br4Dl4WNwSkMdmuV60wOrkb5BpnKZKIhDtpjWF7q6ly3FFhwo8Ktdq5ddVJ8ijJ9Y9tQhs2O0idA9N0yV86khV1IQ72OgbMv15qAswnbqF9WCo3qpfJNjJqMCHBRTohPCxhRp0cWz2thszZTmDDADPxU46sclnurd/JxHFO7lJZVdrsFB4vdLIx9kObV3bP1gOpU66kdcmom2tiedknugj7s0jLcgf1EfXnp+SUUAQyoqwS+kdhhQtGqSXgI2TopsuaLVzj+EtAuPwWeLvtI9CFPSe4o2x+gjCRPl8wVvWKV5FIrZavUVOAHZIL4nKyJjHxZi3jPfVnAia/hq1gW6XKoCg1eWGg/cAWZY4mZYQ6W4XnC0MY0uMC6fhPQdXnIS5iLZNhan80jbr/leBr4fO22+tXc6oZpZsDkXd0r3ilBJFPS2I/zAhotuzZgNA+nF2N86pyiSrdeEYFDhKWKadcKAVc3BMxxlrqZYcAXnlus9GW7R9F/ImXQ/fjRfSjVRUaJuQ0EnFejNAwdGcS6STYMa1G0wnNMAKcZ52xcHgil1SZ6N9BQ7A27z6eViOxw0LHBqNJIRZwQml2KjPd5b00D9XvohDr6jBqYXLGS/HMVvpGDJZLDI2LRlmkqBqx7YEgDZqvspeoMLHIJP22SkQDnaJtsOLGVBSi20ZD5nRyjAgS6MmcgFCvfJVWjCIL1RPHqmUU90eK4WXve0ayH9cJnpbtWrkXYCibhVPCMmYowMROw7rI4bPir0\"}}}}","xsrf":"ABOvogKvrE9fIqAKh0w02RIsB4OJ4hsB_g:1535467885347"} 

O identificador do editor é imediatamente visível na solicitação; no segundo parágrafo, há um conjunto de parâmetros, cuja essência pode ser determinada experimentalmente e o token XSRF.

E, em resposta, ele recebe informações detalhadas sobre o anúncio, mas nem todos sem o próprio anúncio (aqui e abaixo, as imagens estendidas na base64 foram cortadas).

Uma folha de várias páginas.
 {"result":{"1":[{"1":0,"3":0,"4":{"1":"AClZvXJ2t4wiEZ/VZ0i54m0Qtqpi2DTqkI1kaPMTRi4LnsQn0iR5K1xBlFpS1xmJV7ko4a6qx5RcTkp7CzVjwoy5UDSWZ5jOCPLGRcoQdDt+wOk46bdr0yA\u003d"},"5":{"1":82,"2":0,"3":0,"4":"\u003cdiv id\u003d\"ad-parent-id-6A2DE3D206234468F53C743C0EEACD67A59E6C5B62C0371F770419826258CB1AD9591F60\"\u003e\u003c/div\u003e","5":"\u003cdiv id\u003d\"ad-parent-id-6A2DE3D206234468F53C743C0EEACD67A59E6C5B62C0371F770419826258CB1AD9591F60\"\u003e\u003c/div\u003e","6":"\u003cdiv\u003e\u041c\u043d\u043e\u0433\u043e\u0444\u043e\u0440\u043c\u0430\u0442\u043d\u044b\u0435\u003cspan id\u003d'multi-format-tooltip'\u003e\u003c/span\u003e\u003c/div\u003e\u003ca class\u003d'arc-url-link-ellipsis' target\u003d'_blank' href\u003d'https://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/' title\u003d'https://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/'\u003ehttps://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/\u003c/a\u003e","7":"\u003cdiv class\u003d'arc-one-by-one-legend'\u003e\u0422\u0438\u043f \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f\u003c/div\u003e\u003cdiv class\u003d'arc-one-by-one-data'\u003e\u041c\u043d\u043e\u0433\u043e\u0444\u043e\u0440\u043c\u0430\u0442\u043d\u044b\u0435\u003cspan id\u003d'multi-format-tooltip'\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv class\u003d'arc-one-by-one-legend'\u003e\u0426\u0435\u043b\u0435\u0432\u043e\u0439 URL\u003c/div\u003e\u003cdiv class\u003d'arc-one-by-one-data'\u003e\u003ca class\u003d'arc-url-link-ellipsis' target\u003d'_blank' href\u003d'https://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/' title\u003d'https://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/'\u003ehttps://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/\u003c/a\u003e\u003c/div\u003e\u003cdiv class\u003d'arc-one-by-one-legend'\u003e\u0414\u043e\u043c\u0435\u043d\u044b \u0438\u0437\u0434\u0430\u0442\u0435\u043b\u0435\u0439\u003c/div\u003e\u003cdiv class\u003d'arc-one-by-one-data'\u003e4aynikam.ru\u003c/div\u003e\u003cdiv class\u003d'arc-one-by-one-data'\u003eandroidphone.su\u003c/div\u003e\u003cdiv class\u003d'arc-one-by-one-data'\u003eandroidphones.ru\u003c/div\u003e\u003cdiv class\u003d'arc-one-by-one-data'\u003efull-repair.com\u003c/div\u003e\u003cdiv class\u003d'arc-one-by-one-data'\u003ehowgadget.com\u003c/div\u003e\u003cdiv class\u003d'arc-one-by-one-legend'\u003e\u041e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0439 \u0440\u0435\u043a\u043b\u0430\u043c\u043e\u0434\u0430\u0442\u0435\u043b\u044c\u003cspan id\u003d'adx-advertiser-tooltip'\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv class\u003d'arc-one-by-one-data'\u003eDNS Shop\u003c/div\u003e","8":"\u003cdiv\u003e\u003cspan class\u003d'arc-impression-score high'\u003e\u0412\u042b\u0421\u041e\u041a\u041e\u0415\u003c/span\u003e \u0447\u0438\u0441\u043b\u043e \u043f\u043e\u043a\u0430\u0437\u043e\u0432\u003c/div\u003e","9":{"1":"\u003ca href\u003d\"https://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/\" target\u003d\"_blank\"\u003e\u003cimg onerror\u003d\"this.src\u003d'data:image/gif;base64,RA7'\" src\u003d\"https://www.google.com/webpagethumbnail?c\u003d58\u0026s\u003d400:400\u0026r\u003d4\u0026d\u003dhttps://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/\u0026a\u003dAIYkKU9ZGGjFTOWtm771MQwgDYxqtlBLCw\" border\u003d0 alt\u003d\"\"\u003e\u003c/a\u003e","2":"\u003ca href\u003d\"https://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/\" target\u003d\"_blank\"\u003e\u003cimg onerror\u003d\"this.src\u003d'data:image/gif;base64,R0AA7'\" src\u003d\"https://www.google.com/webpagethumbnail?c\u003d58\u0026s\u003d400:400\u0026r\u003d3\u0026d\u003dhttps://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/\u0026a\u003dAIYkKU_CQ2K6v5f11Nk1RXtc87FtmG2B1w\" border\u003d0 alt\u003d\"\"\u003e\u003c/a\u003e","3":"\u003ca href\u003d\"https://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/\" target\u003d\"_blank\"\u003e\u003cimg onerror\u003d\"this.src\u003d'data:image/gif;base64,R0lAA7'\" src\u003d\"https://www.google.com/webpagethumbnail?c\u003d58\u0026s\u003d400:400\u0026r\u003d6\u0026d\u003dhttps://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/\u0026a\u003dAIYkKU_My0a48LAsW-ZKpQX-ATXkMoPEVg\" border\u003d0 alt\u003d\"\"\u003e\u003c/a\u003e"},"10":"https://adwords-displayads.googleusercontent.com/da/b/preview.js?client\u003dasfe-arc-external-preview\u0026obfuscatedCustomerId\u003d5240877441\u0026creativeId\u003d288930210411\u0026htmlParentId\u003dad-parent-id-6A2DE3D206234468F53C743C0EEACD67A59E6C5B62C0371F770419826258CB1AD9591F60\u0026sig\u003dACiVB_yMUjLwDjRO2T-0VAaVuRPt8uLHGQ","13":"https://adwords-displayads.googleusercontent.com/da/b/preview.js?client\u003dasfe-arc-external-preview\u0026obfuscatedCustomerId\u003d5240877441\u0026creativeId\u003d288930210411\u0026htmlParentId\u003dad-parent-id-6A2DE3D206234468F53C743C0EEACD67A59E6C5B62C0371F770419826258CB1AD9591F60\u0026showVariations\u003dtrue\u0026sig\u003dACiVB_yMUjLwDjRO2T-0VAaVuRPt8uLHGQ","14":"https://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/","15":"","17":"","18":"DNS Shop","20":"adv-5594449542310820","21":["site1.ru","site2.com","site3.com","site4.ru"]},"6":{"5":"-6668648012302470727","7":["DNS"],"9":0},"7":1,"9":{"3":[{"1":{"1":"AClZvXLE9HJbFYq9TrAsXFgV4YkXsQt9lXp1xWjSB5aT5bFBpe4VNgo\u003d"},"2":"\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0438 \u0442\u0435\u043b\u0435\u043a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u0438","3":"\u0422\u043e\u0432\u0430\u0440\u044b \u0438 \u0443\u0441\u043b\u0443\u0433\u0438, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u0442\u0435\u043b\u0435\u043a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u044f\u043c\u0438, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u043a\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0435 \u0438 \u0441\u043f\u0443\u0442\u043d\u0438\u043a\u043e\u0432\u043e\u0435 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0435 \u0438 \u0434\u043e\u0441\u0442\u0443\u043f \u0432 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442."},{"1":{"1":"AClZvXKrUJJ3kKBen2scP56BynOtGhf160i1F1LLmtBj3b/oh2dUFg8\u003d"},"2":"\u041c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u044b","3":"\u041c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0435 \u0438 \u0441\u043e\u0442\u043e\u0432\u044b\u0435 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u043f\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0441\u0442\u0438\u043a\u0438 \u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0430\u043d\u0430\u043b\u0438\u0437 \u0442\u043e\u0432\u0430\u0440\u043e\u0432. \u0412 \u044d\u0442\u0443 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044e \u043d\u0435 \u0432\u0445\u043e\u0434\u044f\u0442 \u0430\u043a\u0441\u0435\u0441\u0441\u0443\u0430\u0440\u044b \u0434\u043b\u044f \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u043e\u0432."},{"1":{"1":"AClZvXL4W+khZ4O9SJiu97cTbTs2+0Wecf1IVNju8ffd4ysIT9PJ7XY\u003d"},"2":"\u041c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u044b \u0438 \u0430\u043a\u0441\u0435\u0441\u0441\u0443\u0430\u0440\u044b \u0434\u043b\u044f \u043d\u0438\u0445","3":"\u041c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u043f\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0430\u043a\u0441\u0435\u0441\u0441\u0443\u0430\u0440\u044b \u0438 \u0430\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0447\u0435\u0445\u043b\u044b, \u043c\u043e\u043d\u043e\u043f\u043e\u0434\u044b \u0434\u043b\u044f \u0441\u0435\u043b\u0444\u0438, \u0437\u0430\u0449\u0438\u0442\u043d\u044b\u0435 \u044d\u043a\u0440\u0430\u043d\u044b \u0438 \u0437\u0430\u0440\u044f\u0434\u043d\u044b\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430."},{"1":{"1":"AClZvXLQ3gPoVwjQbokDpB3+nni4xURwH5+YlnwkqjYtUowjhiKvk8Q\u003d"},"2":"\u041f\u041a \u0438 \u0431\u044b\u0442\u043e\u0432\u0430\u044f \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u0438\u043a\u0430","3":"\u0422\u043e\u0432\u0430\u0440\u044b, \u0443\u0441\u043b\u0443\u0433\u0438 \u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0430\u043c\u0438 \u0438 \u0431\u044b\u0442\u043e\u0432\u043e\u0439 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u0438\u043a\u043e\u0439."},{"1":{"1":"AClZvXLKYOGgOROaa32IUxU15jP89AtTM4dV24WKS+daMhqJMTNmeSY\u003d"},"2":"\u0422\u0435\u043b\u0435\u0444\u043e\u043d\u0438\u044f","3":"\u0422\u043e\u0432\u0430\u0440\u044b, \u0443\u0441\u043b\u0443\u0433\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0438\u0435\u0439 \u0438 \u0433\u043e\u043b\u043e\u0441\u043e\u0432\u043e\u0439 \u0441\u0432\u044f\u0437\u044c\u044e."}]},"10":{"1":"AClZvXLdGOShgJo+BM3apOUAFzQkE41z1/hiZhIY8eUlC7p7xXPm82P3dq7yXhbEI+tN/YHgdH4P"}}],"2":0.0,"3":"60609","4":1,"5":"","6":"ClD3Z2nP2P/////1/ff99fXV98nMyMrJz8rH9fHV883Hx8bMz83Oz8vOzv8A/v/+9f33/fX11ffJzMjKyc/Kx/Xx1fPNx8fGzM/Nzs/Lzs7//hABIWxUk293Pm+qOQAAAAAnMJaYSAFQAFoLCS8wxxaTatL1EAJgp7737gY\u003d","7":"3639","9":0},"xsrf":"ABOvogKaRsVZECZZJU-gDWrOqoP0CSqf7Q:1535467886413"} 

Após json_decode, ele se parece com isso:

Um objeto de uma string json (cuidado, 175 linhas).
 objeto (stdClass) nº 19 (2) {
   ["resultado"] =>
   objeto (stdClass) nº 18 (8) {
     ["1"] =>
     matriz (1) {
       [0] =>
       objeto (stdClass) nº 1 (8) {
         ["1"] =>
         int (0)
         ["3"] =>
         int (0)
         ["4"] =>
         objeto (stdClass) nº 2 (1) {
           ["1"] =>
           string (120) "AClZvXJ2t4wiEZ / VZ0i54m0Qtqpi2DTqkI1kaPMTRi4LnsQn0iR5K1xBlFpS1xmJV7ko4a6qx5RcTkp7CzVjwQQ00400400404
         }
         ["5"] =>
         objeto (stdClass) nº 3 (17) {
           ["1"] =>
           int (82)
           ["2"] =>
           int (0)
           ["3"] =>
           int (0)
           ["4"] =>
           string (102) "<div id =" ad-parent-id-6A2DE3D206234468F53C743C0EEACD67A59E6C5B62C0371F770419826258CB1AD9591F60 "> </div>"
           ["5"] =>
           string (102) "<div id =" ad-parent-id-6A2DE3D206234468F53C743C0EEACD67A59E6C5B62C0371F770419826258CB1AD9591F60 "> </div>"
           ["6"] =>
           string (355) "<div> Multi-formato <span id = 'multi-format-tooltip'> </span> </div> <a class = 'elipse-link-de-url-arc' target = '_ blank' href = ' https://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/ 'title =' https: //www.dns-shop.ru/actions/c09a061b-a048-11e8-9547- 00155d03330d / '> https://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/ </a> "
           ["7"] =>
           string (1066) "<div class = 'arc-one-by-one-legend' '> Tipo de anúncio </div> <div class =' ​​arc-one-by-one-data '> Multi-formato <span id =' multi -format-tooltip '> </span> </div> <div class =' ​​arc-one-by-one-legend '> URL de destino </div> <div class =' ​​arc-one-by-one-data '> <a class =' ​​arc-url-link-elipsis 'target =' _ blank 'href =' https: //www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/ 'title = 'https://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/'>https://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d / </a> </div> <div class = 'arco-a-um-por-uma-legenda'> Domínios do editor </div> <div class = 'arco-um-por-um-dados'> 4aynikam.ru </div> <div class = 'arc-a-one-one-data'> androidphone.su </div> <div class = 'arc-one-by-one-data'> androidphones.ru </div> <div class = 'arco-a-um-por-um-dado'> full-repair.com </div> <div class = 'arco-a-um-por-um-dado'> howgadget.com </div> <div class = 'arc-one-by-one-legend'> Anunciante detectado <span id = 'adx-  advertiser-tooltip '> </span> </div> <div class =' ​​arc-one-by-one-data '> Loja DNS </div> "
           ["8"] =>
           string (98) "<div> <span class = 'arc-impression-score high'> ALTA </span> impressões </div>"
           ["9"] =>
           objeto (stdClass) nº 4 (3) {
             ["1"] =>
             string (4191) "<a href="https://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/" target="_blank"> <img onerror =" this.src = 'data: image / gif; base64, RCw "borda = 0 alt =" "> </a>"
             ["2"] =>
             string (4191) "<a href="https://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/" target="_blank"> <img onerror =" this.src = 'data: image / gif; base64, R1w "borda = 0 alt =" "> </a>"
             ["3"] =>
             string (4191) "<a href="https://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/" target="_blank"> <img onerror =" this.src = 'data: image / gif; base64, Rg "border = 0 alt =" "> </a>"
           }
           ["10"] =>
           string (291) "https://adwords-displayads.googleusercontent.com/da/b/preview.js?client=asfe-arc-external-preview&obfuscatedCustomerId=5240877441&creativeId=288930210411&htmlParentId=ad-parent-id-6A2DE3D206234468F53C743C0EEACD67A59E6C5B62C0371F770419826258CB1AD9591F60&sig=ACiVB_yMUjLwDjRO2T-0VAaVuRPt8uLHGQ "
           ["13"] =>
           string (311) "https://adwords-displayads.googleusercontent.com/da/b/preview.js?client=asfe-arc-external-preview&obfuscatedCustomerId=5240877441&creativeId=288930210411&htmlParentId=ad-parent-id-6A2DE3D206234468F53C743C0EEACD67A59E6C5B62C0371F770419826258CB1AD9591F60&showVariations=true&sig=ACiVB_yMUjLwDjRO2T -0VAaVuRPt8uLHGQ "
           ["14"] =>
           string (69) "https://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/"
           ["15"] =>
           string (0) ""
           ["17"] =>
           string (0) ""
           ["18"] =>
           string (8) "Loja DNS"
           ["20"] =>
           sequência (20) "adv-5594449542310820"
           ["21"] =>
           matriz (4) {
             [0] =>
             string (8) "site1.ru"
             [1] =>
             string (9) "site2.com"
             [2] =>
             string (9) "site3.com"
             [3] =>
             string (8) "site4.ru"
           }
         }
         ["6"] =>
         objeto (stdClass) nº 5 (3) {
           ["5"] =>
           sequência (20) "-6668648012302470727"
           ["7"] =>
           matriz (1) {
             [0] =>
             string (3) "DNS"
           }
           ["9"] =>
           int (0)
         }
         ["7"] =>
         int (1)
         ["9"] =>
         objeto (stdClass) nº 16 (1) {
           ["3"] =>
           matriz (5) {
             [0] =>
             objeto (stdClass) nº 7 (3) {
               ["1"] =>
               objeto (stdClass) nº 6 (1) {
                 ["1"] =>
                 string (56) "AClZvXLE9HJbFYq9TrAsXFgV4YkXsQt9lXp1xWjSB5aT5bFBpe4VNgo ="
               }
               ["2"] =>
               string (52) "Internet e telecomunicações"
               ["3"] =>
               string (217) "Produtos e serviços relacionados às telecomunicações, incluindo serviços de cabo e satélite e acesso à Internet."
             }
             [1] =>
             objeto (stdClass) nº 9 (3) {
               ["1"] =>
               objeto (stdClass) nº 8 (1) {
                 ["1"] =>
                 string (56) "AClZvXKrUJJ3kKBen2scP56BynOtGhf160i1F1LLmtBj3b / oh2dUFg8 ="
               }
               ["2"] =>
               string (35) "Telefones celulares"
               ["3"] =>
               string (359) "Telefones celulares e celulares, bem como informações relacionadas, como especificações técnicas e análise comparativa de produtos. Esta categoria não inclui acessórios para celulares."
             }
             [2] =>
             objeto (stdClass) nº 11 (3) {
               ["1"] =>
               objeto (stdClass) nº 10 (1) {
                 ["1"] =>
                 string (56) "AClZvXL4W + khZ4O9SJiu97cTbTs2 + 0Wecf1IVNju8ffd4ysIT9PJ7XY ="
               }
               ["2"] =>
               string (73) "Telefones celulares e acessórios para eles"
               ["3"] =>
               string (283) "Telefones celulares, bem como acessórios e hardware relacionados, como estojos, monopés para selfies, telas de segurança e carregadores."
             }
             [3] =>
             objeto (stdClass) nº 13 (3) {
               ["1"] =>
               objeto (stdClass) nº 12 (1) {
                 ["1"] =>
                 string (56) "AClZvXLQ3gPoVwjQbokDpB3 + nni4xURwH5 + YlnwkqjYtUowjhiKvk8Q ="
               }
               ["2"] =>
               string (45) "PC e eletrônicos"
               ["3"] =>
               string (142) "Produtos, serviços e informações relacionados a computadores e eletrônicos de consumo."
             }
             [4] =>
             objeto (stdClass) nº 15 (3) {
               ["1"] =>
               objeto (stdClass) nº 14 (1) {
                 ["1"] =>
                 string (56) "AClZvXLKYOGgOROaa32IUxU15jP89AtTM4dV24WKS + daMhqJMTNmeSY ="
               }
               ["2"] =>
               string (18) "Telefonia"
               ["3"] =>
               string (181) "Produtos, serviços, além de informações e outros recursos relacionados à telefonia e às comunicações de voz."
             }
           }
         }
         ["10"] =>
         objeto (stdClass) nº 17 (1) {
           ["1"] =>
           sequência (76) "AClZvXLdGOShgJo + BM3apOUAFzQkE41z1 / hiZhIY8eUlC7p7xXPm82P3dq7yXhbEI + tN / YHgdH4P"
         }
       }
     }
     ["2"] =>
     flutuador (0)
     ["3"] =>
     sequência (5) "60609"
     ["4"] =>
     int (1)
     ["5"] =>
     string (0) ""
     ["6"] =>
     de cadeia (168) "ClD3Z2nP2P ///// 1 / ff99fXV98nMyMrJz8rH9fHV883Hx8bMz83Oz8vOzv8A / v / + 9f33 / fX11ffJzMjKyc / KX / Xx1fPNx8fGzM / nzs / Lzs7 // hABIWxUk293Pm + qOQAAAAAnMJaYSAFQAFoLCS8wxxaTatL1EAJgp7737gY ="
     ["7"] =>
     sequência (4) "3639"
     ["9"] =>
     int (0)
   }
   ["xsrf"] =>
   string (48) "ABOvogKaRsVZECZZJU-gDWrOqoP0CSqf7Q: 1535467886413"
 }


Este foi um exemplo de resposta contendo apenas uma declaração. Entenda o que é possível.
E para outras consultas, os métodos são chamados humanamente. Alguns exemplos:

  • getWebPropertyMetricsToken
  • getAdDisplayLanguages
  • getArcSettings
  • getAdNetworkApprovals
  • getPubControlsCapabilities

Teoricamente possível. Para a batalha?


Tudo bem, é possível resolver a comunicação deles (teoricamente), mas tudo isso será inútil, e a teoria permanecerá se você não autorizar no Google.

Autorização Ou como entrar no Google em php + cURL


Novamente, as ferramentas do desenvolvedor, saem da conta e examinam a troca de dados. Não me lembro de detalhes, porque não conseguia entender nada. Uma quantidade enorme de JS, parece que algum tipo de cálculo é feito diretamente no cliente, os resultados são enviados ao servidor. Em geral, é quase impossível para uma pessoa entrar.

Pensamos mais. Um monte de JS. E se você desabilitar o JS? Mas o Google não privará os usuários sem o JS da capacidade de fazer login? Bem, tente sem JS. Externamente, a janela de autorização já parece muito mais fácil. Como antes, primeiro digite o logon e a senha na próxima página. Mais importante ainda, em termos de HTML, também é muito mais fácil! A tag "form" usual com os campos "input" usuais, embora não sem um monte de campos protegidos ou ocultos do sistema. Mas os campos ocultos não são um problema, porque o que eles receberam na entrada é passado para o próximo script. E assim, acabou por entrar no Google. E autorização em duas etapas? Mais sobre isso mais tarde. Primeiro, você precisa ter certeza de que pode retirar os anúncios para inspeção, caso contrário, tudo não faz sentido.

Teórico é possível na prática?


O Google entrou - é hora de testar a teoria de desvendar protocolos de comunicação na prática. Eu tive que mexer com experimentos e observações, observar cuidadosamente e registrar quais ações do usuário levam a quais consultas, identificar elementos de consulta comuns e variáveis, comparar valores incompreensíveis longos recebidos do servidor com os mesmos longos enviados de volta na próxima solicitação. Era uma floresta densa, que com o tempo se tornou mais clara e transparente.

O que tinha que ser feito para entender que a continuação faz sentido?

  1. Faça logon no CPO .
  2. Obtenha uma lista de anúncios.
  3. Obtenha um anúncio específico (primeiro o texto).

Entrar no CPO é o mais simples, grosso modo, basta seguir o link. Acabou.

Detalhes
Simplesmente seguimos o link, obtemos a resposta (que não usamos neste caso). Também precisamos solicitar e salvar um token digital para solicitações futuras.

No momento da redação deste artigo, o AdSense possui dois centros de serviço público. Vou nomeá-los condicionalmente antigos e novos.

Para o antigo CPO.

Nenhuma solicitação de postagem de carregamento:

https://www.google.com/adsense/gwt-properties?pid=pub-8958890276790964&authuser=0&tpid=pub-8958890276790964&ov=3&hl=en

A resposta é:

 <meta name="gwt:property" content="usePropertyService=true"> <meta name="gwt:property" content="applicationType=ASFE3"> <meta name="gwt:property" content="syn.token=ABOvogJ1yQyL9pgHcGYM-J3OLj_9VSh31w:1535115071772"> <meta name="gwt:property" content="syn.token.pb=ABOvogKJ6-xmsNWK4Mbe_H5bT1xXhyj8SQ:1535115071772"> <meta name="gwt:property" content="syn.login=XXXXXX@gmail.com"> <meta name="gwt:property" content="syn.csi.backendUrl="> <meta name="gwt:property" content="syn.helpCenterUrl=//support.google.com/adsense/"> <meta name="gwt:property" content="syn.helpHost=//support.google.com"> <meta name="gwt:property" content="syn.helpCenterUri=/adsense"> <meta name="gwt:property" content="syn.newHelpHost=https://clients6.google.com"> <meta name="gwt:property" content="syn.newHelpCenterUri=/adsense"> <meta name="gwt:property" content="syn.helpCenterGaiaAuthDisabled=false"> <meta name="gwt:property" content="syn.billing3BaseUri=https://bpui0.google.com"> <meta name="gwt:property" content="syn.contextPath=/adsense"> <meta name="gwt:property" content="syn.userLanguage=en-US"> <meta name="gwt:property" content="syn.bruschettaContextPath=/adsense/new"> <meta name="gwt:property" content="userProfileImageUrl=https://lh5.googleusercontent.com/-v7nuoAI4eEQ/AAAAAAAAAAI/AAAAAAAAAAA/AT3-yjmKyg8/s96/photo.jpg"> <meta name="gwt:property" content="userDisplayName=" "> <meta name="gwt:property" content="userSettingsUrl=https://www.google.com/settings"> <meta name="gwt:property" content="googlePlusProfileUrl=https://plus.google.com/me"> <meta name="gwt:property" content="googlePrivacyUrl=http://www.google.com/intl/en_US/policies/privacy/"> <meta name="gwt:property" content="syn.features=562,465,612,604,616,618"> <meta name="gwt:property" content="analyticsHomePageUrl=https://www.google.com/analytics/web/"> <meta name="gwt:property" content="disableDebugIds=true"> <meta name="gwt:property" content="syn.pubControlsCapabilitiesLoadTimeout=5000"> <meta name="gwt:property" content="pid=pub-8958890276790964"> <meta name="gwt:property" content="tpid=pub-8958890276790964"> <meta name="gwt:property" content="syn.asfeGtmCampaignId=GTM-K7WZ"> 

Precisamos da quarta linha, a saber "syn.token.pb". Mantemos esse valor para geração adicional de consultas.

Para o novo CPO.

Nenhuma solicitação de postagem de carregamento:

https://www.google.com/ads-publisher-controls/acx/5/darc/loader?onearcClient=adsense&pc=ca-pub-8958890276790964&tpid=pub-8958890276790964&hl=en

A resposta é:

 (function() {function loadAsyncOrDefer() {var scriptElement = document.createElement('script'); scriptElement.src = 'https:\/\/ssl.gstatic.com\/ads-publisher-controls\/onearc_20180822-12_RC00\/darc\/arc_app.dart.js';scriptElement.type = 'application\/javascript';scriptElement.defer = true;scriptElement.nonce = window['acxCspNonce'];scriptElement = document.head.appendChild(scriptElement); if ('_resourceTimingBuffer' in window) {_resourceTimingBuffer.add(scriptElement.src);}};loadAsyncOrDefer();})();window['__darc_app_params'] = {'onearcClient': 'ADSENSE','hl': 'ru','pc': 'ca-pub-8958890276790964','tpid': 'pub-8958890276790964',};window['__app_metadata'] = {'token': 'ABiMD8TT9vzK99SFB7iaI0ssBySxT9jjrQ:1535116725529','pre': '\/ads-publisher-controls\/acx','scs': 'https:\/\/ssl.gstatic.com\/ads-publisher-controls\/onearc_20180822-12_RC00','oacf': '\x7b\x221\x22:\x5b5,25,22,8,27,32,43,44,45,48,49,5,25,22,8,27,32,43,44,45,48,49,29,46\x5d\x7d','hats': 'ibhswcm2x2iztju5i6jbbzlkma',}; 

A sequência que precisamos está aqui:

'token': 'ABiMD8TT9vzK99SFB7iaI0ssBySxT9jjrQ:1535116725529'


Obter uma lista é uma tarefa interessante, porque você precisa passar por várias configurações - diga-nos o que queremos receber (tipo de anúncio, verificado / novo / bloqueado, número de anúncios etc.). Além disso, um token XSRF digital por solicitação. Acabou. Em resposta, chegou uma grande quantidade de dados, que ainda continha miniaturas de imagens dos sites em que os anúncios levavam. E, é claro, links para anúncios.

Detalhes
Rascunhos das minhas tentativas foram preservados para descobrir qual parâmetro é responsável por quê. Eu os enobreci um pouco, recortei todo o tapete e emoticons e os postei aqui. Primeiro, haverá uma sequência para o CPO antigo e depois para o novo.

Em seguida, chamarei os nomes dos métodos (apenas para a nova CPU, para o método antigo indicado no corpo da solicitação) e json string, pois são os "portadores" de informações, tudo mais (endereço, cabeçalhos, tokens digitais, outros parâmetros) - "wrapper ", Eles não são fundamentais, vou falar sobre isso mais tarde.

Para a CPU antiga (json request params variable):

 { "1":"ca-pub-8958890276790964", "2":{ "1":0, //  ,          "2":32, // -   "3":0, // 0 - , 1-  "4":{ "1":{"1":"-    "} //    }, "5":{ "1":"video" //   "2":1, //  ,     "3":1, //       "6":7, //      "16":[0], // 0 - ; 1 - ; 2 - .      . "17":0 //       } }, "3":"-3945261286198141534" //,    } 

Descriptografia, formamos uma solicitação e recebemos a resposta.

Para o CPO antigo, primeiro você precisa obter um token - faça outra solicitação antes de solicitar anúncios:

 {"method":"getWebPropertyMetricsToken","params":"{\"1\":\"ca-pub-8958890276790964\"}","xsrf":"ABOvogKJ6-xmsNWK4Mbe_H5bT1xXhyj8SQ:1535115071772"} 

A resposta é:

 {"result":{"1":{"1":{"1":"AClZvXKte+4mEwsFB7kw20LrbWQ6jOMxmK8j4At4Vxqc7w+5dDDYWIx2k1ldCvvGbAT59UClLSkQty6zyZZQSmgxKvpKhq22bKRfGy8ywt0B5L8WE53vo+YtI8ixM8Xe0RPixTjPtOLQA8sCZod+hvHxqU5Depi3I9XUV6JMn8uCOg67m+5oe5TT1L0OytnUBDIsjAaQ+kcldN23yGoppKKCs2Zf5XI6i7nk5QHehS8wvsDlugvkKSU3fUo3J+ZHJvoUXyCGLP3lP9Gh+6fOMir/SLrOJx8udRbtjTJhLsvXTXUN2QbjcEfFFAIaWfgMr5euHtYwYYWuMoI5ofZTc9L8sCY5pA0Q/CWyZ6QLH85XI70vxH6cBZtsnfrPLRh18cxSxFgzXuAwPHW8+CueCznqiHcY7gOhxQc2YWmSgwMIP9Cpgr089dWoB58wulcK0g+EqnTJiQdI9MMUj4zzLpu5DYja5ftP7lF3jeCSuKT9q70B9OqMDvlGlruZd2hhHe3k5S+LoyWo/4WZDUTvWpCMmnPzCP3R4OIQnrhS0s5ffOVxjyNHrXJXtrNhppap3BY4iByIn1cowMfVFfx3hNep0JW59db9fVuXKaSy/mqHZKC1ToRM/UyCoSZ9ZjY/Ot091ptURLRYoTFal5TBbMKISgxn5UCz4vSoxVe1fC64dwXHatSzCCg9AjJOpKR4p/9smxOaKg73pmMHsEY98I6TJhvaeJ9o6lcHsG8PZnB6xNS4ZJHBtN1baHkrCHOfqaepMVyRCF2kPNhr9SgujjTTbiKGMUO3UVamOQQ5/EckTgFMr0PIda7PPw7op8qFEhxZmkoo9KgERcYLGHxzGePjfo0IiNbf7k50lgDipwk5ag3CI0tw3CtDicQn6isHwKOmlfSctrEGv/Fjlmcgjhl1sTAL/rTWxDCABKN7/OhdysBAOq0j6viFgzjM8WI0ZuYPIVIm19CQ+YGcOx77oiyxev+3sAj7uSJoYFslmgiZV4jrF5P+b+U/5fknRf2Ho8plAUh4AHweXMeaPFYZAYooe6jC79EzgizqXvx1H/HrKKQcaXdDZ1ivoOM/7DtzJbawzO7ALUnHkqR1ZYmw3+3E/pmsDXedYgzERWYWvJltS+P46iWYOS43SUVw+whDWZnjJOwVOFFLDWcg4ykfzNmbq4B/vUibrV1dCiRpTIXSP92xk1I8MCfQGiptqo5MiKttqJ9Orj7nrGXEDz5pJBTTem919nz5rNIjI/sus3GZ+G4rBE+9i1sJN0jxszvpRD2AKsl1KSOrPCuOBhpNbD2HnFgQd+EUw8CpH2MLZlrZ8l3cqzDVc5aeCQ1eiUKlONlZpIxZi5wE5HyKZRxC8ljtX5xe+Fpg8R8/yDarvAkjeb0yKzN/e893nEVz3CmF68pphNp71kjJtvwBS2JtSWhFc81Ys51GEw\u003d\u003d"}}},"xsrf":"ABOvogJLbcTkcBxU_TCJddIrW4L-mVwPcw:1535115072920"} 

Esse enorme token ("1": "AClZ ...") precisará solicitar anúncios.

Solicitar anúncios:

 {"method":"searchArcApprovals","params":"{"1":"ca-pub-8958890276790964","2":{"1":0,"2":24,"3":0,"4":{"1":{"1":"AClZvXKte+4mEwsFB7kw20LrbWQ6jOMxmK8j4At4Vxqc7w+5dDDYWIx2k1ldCvvGbAT59UClLSkQty6zyZZQSmgxKvpKhq22bKRfGy8ywt0B5L8WE53vo+YtI8ixM8Xe0RPixTjPtOLQA8sCZod+hvHxqU5Depi3I9XUV6JMn8uCOg67m+5oe5TT1L0OytnUBDIsjAaQ+kcldN23yGoppKKCs2Zf5XI6i7nk5QHehS8wvsDlugvkKSU3fUo3J+ZHJvoUXyCGLP3lP9Gh+6fOMir/SLrOJx8udRbtjTJhLsvXTXUN2QbjcEfFFAIaWfgMr5euHtYwYYWuMoI5ofZTc9L8sCY5pA0Q/CWyZ6QLH85XI70vxH6cBZtsnfrPLRh18cxSxFgzXuAwPHW8+CueCznqiHcY7gOhxQc2YWmSgwMIP9Cpgr089dWoB58wulcK0g+EqnTJiQdI9MMUj4zzLpu5DYja5ftP7lF3jeCSuKT9q70B9OqMDvlGlruZd2hhHe3k5S+LoyWo/4WZDUTvWpCMmnPzCP3R4OIQnrhS0s5ffOVxjyNHrXJXtrNhppap3BY4iByIn1cowMfVFfx3hNep0JW59db9fVuXKaSy/mqHZKC1ToRM/UyCoSZ9ZjY/Ot091ptURLRYoTFal5TBbMKISgxn5UCz4vSoxVe1fC64dwXHatSzCCg9AjJOpKR4p/9smxOaKg73pmMHsEY98I6TJhvaeJ9o6lcHsG8PZnB6xNS4ZJHBtN1baHkrCHOfqaepMVyRCF2kPNhr9SgujjTTbiKGMUO3UVamOQQ5/EckTgFMr0PIda7PPw7op8qFEhxZmkoo9KgERcYLGHxzGePjfo0IiNbf7k50lgDipwk5ag3CI0tw3CtDicQn6isHwKOmlfSctrEGv/Fjlmcgjhl1sTAL/rTWxDCABKN7/OhdysBAOq0j6viFgzjM8WI0ZuYPIVIm19CQ+YGcOx77oiyxev+3sAj7uSJoYFslmgiZV4jrF5P+b+U/5fknRf2Ho8plAUh4AHweXMeaPFYZAYooe6jC79EzgizqXvx1H/HrKKQcaXdDZ1ivoOM/7DtzJbawzO7ALUnHkqR1ZYmw3+3E/pmsDXedYgzERWYWvJltS+P46iWYOS43SUVw+whDWZnjJOwVOFFLDWcg4ykfzNmbq4B/vUibrV1dCiRpTIXSP92xk1I8MCfQGiptqo5MiKttqJ9Orj7nrGXEDz5pJBTTem919nz5rNIjI/sus3GZ+G4rBE+9i1sJN0jxszvpRD2AKsl1KSOrPCuOBhpNbD2HnFgQd+EUw8CpH2MLZlrZ8l3cqzDVc5aeCQ1eiUKlONlZpIxZi5wE5HyKZRxC8ljtX5xe+Fpg8R8/yDarvAkjeb0yKzN/e893nEVz3CmF68pphNp71kjJtvwBS2JtSWhFc81Ys51GEw\u003d\u003d"}}},"3":""}","xsrf":"ABOvogI3FCm29t4pdIded8L-Q98R0Voy-Q:1535121289188"} 

Estou traduzindo a seção 2 da variável params:
Google, , :
("1":0),
24 ("2":24),
("3":0),
: AClZvX....


Vários parâmetros podem ser omitidos, eles assumem valores padrão:

  • tipo de anúncios: todos;
  • período: todos disponíveis;
  • bloqueio previsto: não;
  • mostrar apenas não verificado: não.

Dezenas ou centenas de kilobytes vêm em resposta, dependendo do número de anúncios solicitados. O mais difícil são os gráficos "estendidos" no texto (dados: image / gif; base64 ....). E se não houver respostas não verificadas, a resposta é simples:

 {"result":{"4":1,"5":"","8":"0","9":0},"xsrf":"ABOvogLWqmyC7KH1zfvmPxk-Y69-Jzj5XQ:1535115074392"} 

Se houvesse anúncios, eles seriam contidos aqui: resultado -> {5}.

Para o novo CPO:

 { "1":"ca-pub-8958890276790964", "2":{ "1":10, //  ,          "2":7, // -   "3":11, //  - 10;  - 1;  - 11; "5":{ "6":3 //      "7":3534 //    "14":"en" //  "16":[0] // 0 - ; 1 - ; 2 - . "18":"dfd.com" //   "24":"video" //   }, "7":""}, //          "3":"-2876348936240321457", //          "5":true //    . . } 

Solicitações preliminares não precisam ser feitas, você pode solicitar anúncios imediatamente.
Aprovações de pesquisa (este é um método)

 {"1":"ca-pub-8958890276790964","2":{"2":100,"3":11,"5":{"16":[0]},"7":""},"5":true} 

Google, , :
100 ("2":100),
("3":11),
("5":{"16":[0]},
("7":"")


Parâmetros e padrões opcionais:

  • número de série do primeiro anúncio solicitado: 0;
  • período: todos disponíveis;

Em resposta, temos quase o mesmo que no caso do antigo CPO. Difere em apenas uma palavra - o nome do contêiner de dados. No antigo, é "resultado", no novo, é "padrão".


Obter um anúncio específico é simples, pegue o link da resposta anterior e faça o download do anúncio. Não há proteção aqui, o acesso é gratuito para todos.

Detalhes
Link para o anúncio. Vamos procurá-lo na resposta anterior, onde recebemos muitos e muitos kilobytes de texto em resposta a uma solicitação de anúncios.

Para que não haja muito código incompreensível, respondo à solicitação de um anúncio (e mesmo assim foi cortado sem piedade, eram 10 vezes mais, apenas o mais importante ficou no momento):

 {"result":{"1":[{"1":0,"3":0,"4":{"1":"AClZvXJ2t4wiEZ/VZ0i54m0Qtqpi2DTqkI1kaPMTRi4LnsQn0iR5K1xBlFpS1xmJV7ko4a6qx5RcTkp7CzVjwoy5UDSWZ5jOCPLGRcoQdDt+wOk46bdr0yA\u003d"},"5":{"1":82,"2":0,"3":0,"4":"\u00GQ","13":"https://adwords-displayads.googleusercontent.com/da/b/preview.js?client\u003dasfe-arc-external-preview\u0026obfuscatedCustomerId\u003d5240877441\u0026creativeId\u003d288930210411\u0026htmlParentId\u003dad-parent-id-6A2DE3D206234468F53C743C0EEACD67A59E6C5B62C0371F770419826258CB1AD9591F60\u0026showVariations\u003dtrue\u0026sig\u003dACiVB_yMUjLwDjRO2T-0VAaVuRPt8uLHGQ","14":"https://www.dns-shop.ru/actions/c09a061b-a048-11e8-9547-00155d03330d/","15":"","17":"","18":"","20":"adv-5594449542310820","21":["domain1.com","domain2.com"]},"6":{"5":"-6668648012302470727","9":0},"7":1,"9":{"3":[{"1":{"1":"AClZvXLE9HJbFYq9TrAsXFgV4YkXsQt9lXp1xWjSB5aT5bFBpe4VNgo\u003d"},"2":"\u041/YHgdH4P"}}],"2":0.0,"3":"59917","4":1,"5":"","6":"ClD3Z2nP2P/////1/ff9oPjm7gU\u003d","7":"5751","9":0},"xsrf":"ABOvogJJJuNM1d0i22yN48ibBAY8vpvC_A:1535125743731"} 

No parâmetro {13}, você pode obter o link para o anúncio:

https://adwords-displayads.googleusercontent.com/da/b/preview.js?client=asfe-arc-external-preview&obfuscatedCustomerId=5240877441&creativeId=288930210411&htmlParentId=ad-parent-id-6A2DE3D206234468F53C743C0EEACD67A59E6C5B62C0371F770419826258CB1AD9591F60&showVariations=true&sig=ACiVB_yMUjLwDjRO2T-0VAaVuRPt8uLHGQ .

Por algum tempo (dias, talvez semanas), o link permanecerá ativo e qualquer pessoa poderá obter um anúncio por meio dele. Existem entre 100 e 150 kilobytes e, na parte inferior (e não apenas), você encontra trechos do texto do anúncio.

Além disso, esse é um parâmetro importante - esse é o identificador interno do anúncio, que usaremos para gerenciá-lo ainda mais (bloquear / desbloquear o anúncio, bloquear / desbloquear a conta do Google AdWords que desaparafusa esse anúncio, solicitando estatísticas de impressão, definindo a sinalização como "marcada", enviando uma mensagem sobre violação das regras) . Está armazenado aqui:
resultado -> {1} -> {4} -> {1}.

É assim:

AClZvXJ2t4wiEZ/VZ0i54m0Qtqpi2DTqkI1kaPMTRi4LnsQn0iR5K1xBlFpS1xmJV7ko4a6qx5RcTkp7CzVjwoy5UDSWZ5jOCPLGRcoQdDt+wOk46bdr0yA=

Seu comprimento é de 120 caracteres (com raras exceções).

Há muitas informações nesse fluxo de dados:

  • Tipo de anúncio.
  • URL de destino
  • Domínios nos quais foi desaparafusado.
  • Informações sobre o anunciante (nome, se houver, e identificador).
  • Característica qualitativa do número de impressões, por exemplo, "alto".
  • Três miniaturas da página de destino na forma de dados: imagem.
  • A categoria à qual o anúncio pertence, por exemplo, Telefonia.

O resultado é obtido - ele se presta à automação. Em seguida, a ordem nas funções foi implementada, porque o protótipo em funcionamento era terrível, eu só queria entender rapidamente se o processo seria automatizado. A primeira versão foi oferecida às pessoas e a conclusão e a correção dos erros começaram. O primeiro problema é que o "dois estágios" não pôde efetuar login.

Autorização em duas etapas


Se você verificar a aparência quando o JS estiver desativado, poderá ver muitas opções de autorização: senha do SMS, senhas únicas de um pedaço de papel, através do aplicativo ...
Automatize cada opção para que todos fiquem à vontade - você pode ficar louco.

Rescue do desenvolvedor


Quando, sem o JS no Chrome, observei o mecanismo de autorização em dois estágios, vi uma referência à escolha de outro método, fiquei viciado nisso. Qualquer que seja o método selecionado por padrão, sempre há uma opção para ir para a seleção e selecionar SMS. Essa foi uma verdadeira salvação. Obviamente, eu tive que verificar o método selecionado por padrão e, no caso de um método "incorreto", "pressione" o botão alterar e selecione "senha descartável por SMS".

Para a autorização em si, salvei os dados intermediários do formulário no arquivo (o mesmo grupo de todos os campos ocultos) e no formulário de entrada de senha descartável. Isso é tudo, "duas etapas" também puderam entrar.

Conclusão do processo de criação


A principal tarefa foi concluída - qualquer pessoa poderia instalar e usar uma solução automatizada para filtrar periodicamente os anúncios em seus sites.

Em seguida vieram melhorias, melhorias, correção de deficiências ...
... identificado pelos usuários e independentemente, o refinamento do design externo (intuitivo para o autor era incompreensível para quase todos os outros).
Várias funções e filtros também foram concluídos e adicionados à pesquisa de anúncios censuráveis. Por exemplo, para detectar automaticamente um hash de letras cirílicas e latinas. Anunciantes normais não fazem anúncios como esse, mas às vezes há erros na forma de misturar um caractere russo em palavras russas (erros populares no filtro também são levados em consideração).

Complementos adicionados por conveniência:

  • Lista de anunciantes bloqueados.
  • Lista de domínios bloqueados.
  • Rótulo de renda.
  • Links do AdSense.

A lista de anunciantes bloqueados é uma oportunidade de assistir e editar, e é mais conveniente (mas não é mais bonito na aparência) do que na interface normal! Além disso, existe a capacidade de desbloquear "em massa", o que não é comum no AdSense.

A lista de domínios bloqueados é semelhante à lista anterior.

Capacidade de trabalhar com o AdX (por meio do AdManager, para onde o AdX foi movido recentemente).

Existem muitas melhorias, as mais interessantes na minha opinião estão listadas acima.


Funções de envio de uma solicitação e recebimento de um resultado


Anteriormente, escrevi sobre solicitações na forma de json strings e prometi abri-las com mais detalhes posteriormente.

Quando tudo isso foi feito pelo novo CPO, ainda não havia, portanto, tudo foi feito para o antigo, vamos começar com ele.

Comunicação com o antigo CPO


Com a ajuda das observações, foi possível descobrir que a principal troca de solicitações vai para um endereço:

  https://www.google.com/adsense/gp/creativeReview?ov=3&pid=pub-8958890276790964&authuser=0&tpid=pub-8958890276790964(&hl=pt_BR) 


O que nem sempre está entre parênteses é apenas um parâmetro que indica o idioma da resposta, que pode ser aplicado a quase todos os produtos do Google. Isso é importante, pois eu uso o inglês em qualquer lugar e o software reconhece alguns parâmetros, aguardando uma resposta em inglês.

Além do endereço, existe uma forma padrão de pós-dados transmitidos (nas ferramentas do desenvolvedor, eles são visíveis na seção "Solicitar carga") - esta é uma string json com o método, parâmetros e variáveis ​​xsrf:

 {"method":"getArcSettings","params":"{\"1\":[\"ca-pub-8958890276790964\"]}","xsrf":"ABOvogJlvXKkBQUbPYEsM04recgCsukFMg:1535467881599"} 

método - tudo parece estar claro aqui.
params - dependendo do método, seu próprio formato padrão para a string json transmitida.
xsrf - o recebimento inicial do token digital que usamos para a solicitação está descrito acima e, na resposta, recebemos um novo token XSRF para a próxima solicitação.

A resposta também vem na forma de uma string json das partes do resultado (informações solicitadas) e xsrf:

 {"result":{"1":[{"1":"ca-pub-8958890276790964","2":{"1":"ca-pub-8958890276790964","2":0},"3":{"1":"ca-pub-8958890276790964","2":0}}]},"xsrf":"ABOvogIH7wJjD8t1xmuu8WbGplQowqjjJA:1535467883406"} 

código de função php
 function creative_review($method, $params) { $xsrftoken = file_get_contents($GLOBALS['xsrftoken_file']); $creativeReview = new stdClass(); //to make json request string $creativeReview->method = $method; $creativeReview->params = $params; $creativeReview->xsrf = $xsrftoken; $creativeReview_post_request = json_encode($creativeReview); unset($creativeReview); $result = curl_post($GLOBALS['creative_review_req_string'], $creativeReview_post_request, $GLOBALS['arc_tab_req_string'], $GLOBALS['myheaders']); $result = json_decode($result); // decode result string if ($result->xsrf) file_put_contents($GLOBALS['xsrftoken_file'], $result->xsrf); // Renew standard XSRF token return $result; } 

post- — curl_post($url, $postfields, $referer, $myheaders).

.
$myheaders :

 accept-language:en-US;q=1,en;q=0.4
content-type:application/javascript; charset=UTF-8 


$GLOBALS['creative_review_req_string']:

 https://www.google.com/adsense/gp/creativeReview?ov=3&pid=pub-8958890276790964&authuser=0&tpid=pub-8958890276790964&hl=en 


, .

$GLOBALS['arc_tab_req_string']:

 https://www.google.com/adsense/new/u/0/pub-8958890276790964/main/allowAndBlockAds?webPropertyCode=ca-pub-8958890276790964&tab=arcTab 

referer , .

Comunicação com o novo CPO


Aqui com o endereço para a solicitação é mais complicado - ele muda. Existe apenas a parte comum inicial. O esquema é o seguinte:

Parte geral + método + '?' + Parâmetros GET + rpcTrackingId = <repetição de parâmetros GET anteriores na codificação de URL> + ':' + <número de sequência da solicitação usando o mesmo método em ... em geral, até que o usuário atualize a página>.

https://www.google.com/ads-publisher-controls/acx/5/proto/creativereview/GetArcSettings?hl=ru&pc=ca-pub-8958890276790964&onearcClient=adsense&rpcTrackingId=%2Fads-publisher-controls%2Facx%2F5%2Fproto%2Fcreativereview%2FGetArcSettings%3Fhl%3Dru%26pc%3Dca-pub-8958890276790964%26onearcClient%3Dadsense%3A1

O token XSRF aqui é passado no cabeçalho 'x-framework-xsrf-token' e é reutilizável, portanto, não vem nas respostas e não é necessário atualizá-lo constantemente.

código de função php
 function creative_review_new($method, $params) { if (!isset($GLOBALS['xsrftoken_new'])) $GLOBALS['xsrftoken_new'] = file_get_contents($GLOBALS['temp_folder'] . 'xsrftoken_new.txt'); $myheaders = $GLOBALS['myheaders_new']; $myheaders[] = 'x-framework-xsrf-token:' . $GLOBALS['xsrftoken_new']; $query['pc'] = 'ca-' . $GLOBALS['pub_id']; $query['onearcClient'] = 'adsense'; $query['hl'] = 'en_US'; foreach ($query as $index => $value) $rpc[] = $index . '=' . $value; if(!isset($GLOBALS[$method_count])) { $GLOBALS[$method_count]=1; } else { $GLOBALS[$method_count]++; } $append = ':'.$GLOBALS[$method_count]; $query['rpcTrackingId'] = $GLOBALS['creative_review_new_string'] . $method . '?' . implode('&', $rpc) . $append; $query = http_build_query($query); $url = 'https://www.google.com' . $GLOBALS['creative_review_new_string'] . $method . '?' . $query; $result = curl_post($url, $params, $GLOBALS['new_arc_tab_req_string'], $myheaders); if (mb_strpos($result, 'Error 400 (Not Found)', 0, 'UTF-8') !== false) { return '-32000 XSRF token validation'; } $list = explode("\n", $result, 2); $result = $list[1]; $result = json_decode($result); // decode result string if (@$result->default->{5}) file_put_contents($GLOBALS['temp_folder'] . 'some_digi_token.txt', $result->default->{5}); // Renew token if (@$result->default->{6}) file_put_contents($GLOBALS['temp_folder'] . 'some_long_token.txt', $result->default->{6}); // Renew token 

post- — curl_post($url, $postfields, $referer, $myheaders).

$myheaders (javascript → json):

 accept-language:en-US;q=1,en;q=0.4
content-type:application/json; charset=UTF-8 


$GLOBALS['creative_review_new_string']:

 /ads-publisher-controls/acx/5/proto/creativereview/ 
.

$GLOBALS['new_arc_tab_req_string']:

 https://www.google.com/adsense/new/u/0/pub-8958890276790964/arc/ca-pub-8958890276790964 
referer , .

. «» . (« 10 , 30-»). , .


Consulta da Lista de Domínios e Função de Gerenciamento


É quase o mesmo que a função de comunicação com o antigo CPO, difere apenas no endereço do recurso.

código de função php
 function blocking_controls($method, $params) { $xsrftoken = file_get_contents($GLOBALS['xsrftoken_file']); $creativeReview = new stdClass(); //to make json request string $creativeReview->method = $method; $creativeReview->params = $params; $creativeReview->xsrf = $xsrftoken; $creativeReview_post_request = json_encode($creativeReview); unset($creativeReview); $result = curl_post($GLOBALS['blocking_controls_req_string'], $creativeReview_post_request, $GLOBALS['arc_tab_req_string'], $GLOBALS['myheaders']); $result = json_decode($result); // decode result string if ($result->xsrf) file_put_contents($GLOBALS['xsrftoken_file'], $result->xsrf); // Renew standard XSRF token return $result; } 

$GLOBALS['blocking_controls_req_string']:
 https://www.google.com/adsense/gp/blockingControls?ov=3&pid=pub-8958890276790964&authuser=0&tpid=pub-8958890276790964 
.

Os tokens XSRF são salvos no disco em um arquivo. É necessário que as solicitações bloqueiem / desbloqueiem anúncios, contas do AdWords e outras ações para trabalhar diretamente no painel de controle, sem a necessidade de solicitar uma nova.

Processando respostas recebidas


Os dados são fornecidos na forma de strings json (as respostas recebidas pelas três funções acima) e na forma de um código JS (declarações solicitadas), onde uma série de caracteres é "criptografada" com codificação hexadecimal (\ x <código de caractere de dois caracteres>).

Trecho do anúncio mencionado acima:
target \ x3d_blank title \ x3d \ x22 \ x22 \ x3e \ x3cspan \ x3e Compre o Xiaomi Redmi S2 e obtenha o Redmi 5 \ x3cbr \ x3e como presente. De 24 a 26 de agosto. \ x3cbr \ x3eSaiba mais no site.

Para json, existe uma função no php que produzirá pelo menos um objeto, pelo menos um array.
Para os "Kosoiks" em algum lugar da rede, encontrei uma pequena função que traz os dados para a forma humana.

código de função php
 function hex_repl($html) { $i = 256; while ($i >= 0) { $hex = dechex($i); $html = str_ireplace("\x$hex", chr($i), $html); $i--; } return $html; } 

Resultado da descriptografia:
target = _blank title = ""> <span> Compre o Xiaomi Redmi S2 e ganhe o Redmi 5 <br> como presente. De 24 a 26 de agosto. <br> Mais informações no site.

Reconhecimento de anúncios


Texto . Eu comecei com eles. Eles eram mais importantes e, como se viu, tudo era muito mais fácil com eles. Existem apenas dois tipos: antigo, com um título (que está quase acabando) e novo, com dois títulos.

O anúncio já vem na forma de código HTML, mas, além do anúncio, a resposta que recebemos contém muitos dados de que não precisamos - o código Javascript (que nem chegou à essência desse código).

O reconhecimento acabou por seguir as seguintes etapas:

  • aparar o “grande começo”, deixando apenas a “cauda”, que contém o texto do anúncio;
  • Criando um objeto usando a classe DOMDocument
  • pesquise no loop os valores desejados: títulos, texto do anúncio, texto do link.

Os títulos, o texto e um link contêm determinadas classes e o reconhecedor "se apega" a elas.

O que é onde e a função do processamento de anúncios de texto
rhtitleline1 — 1;
rhtitleline2 — 2;
rhtitle — ( );
rhbody — ;
rhurl — URL.

 function text_ad($html) { $list = explode('</head>', $html); $ad_html = array_pop($list); unset($list, $html); $dom = new DOMDocument('1.0', 'UTF-8'); @$dom->loadHTML($ad_html); unset($ad_html); foreach ($dom->getElementsByTagName('a') as $a_node) { if (stripos($a_node->getAttribute('class'), 'rhtitleline1') !== false) { $ad['header1'] = $a_node->textContent; continue; } if (stripos($a_node->getAttribute('class'), 'rhtitleline2') !== false) { $ad['header2'] = $a_node->textContent; continue; } if (stripos($a_node->getAttribute('class'), 'rhbody') !== false) { $ad['body'] = $a_node->textContent; continue; } //Old ads (with just 1 header) support if (stripos($a_node->getAttribute('class'), 'rhtitle ') !== false || stripos($a_node->getAttribute('class'), 'rhtitle"') !== false) { $ad['header1'] = $a_node->textContent; continue; } if (stripos($a_node->getAttribute('class'), 'rhurl ') !== false || stripos($a_node->getAttribute('class'), 'rhurl"') !== false) { $ad['displayUrl'] = $a_node->textContent; continue; } } $fulltext = implode(' ', $ad); $ad['fulltext'] = $fulltext; if (!isset($GLOBALS['set_gl']['utf8_off'])) foreach ($ad as $index => $value) $ad[$index] = utf8_decode($value); return $ad; } 

— . .

$fulltext — .

utf8_decode . DOMDocument . .


Gráfico . Eles apenas verificam o URL de destino. Não há reconhecimento de fotos, também é possível salvar fotos para inspeção (porque as fotos, se desejado, também podem ser visualizadas no CPO). Não vejo razão para reinventar a roda (provavelmente uma curva e ninguém precisa dela).

Multimídia . Sob esse nome comum, oculta vários anúncios diferentes:

  • Multi-formato.
  • Mídia (Rich Media).
  • Modelo personalizado (HTML5).

Para multi-formato, 3 funções de reconhecimento foram criadas, dependendo do tipo de anúncio.
Para mídia, foram criadas 2 funções.

Para HTML5, três funções foram criadas.

Filtragem


Após o reconhecimento dos anúncios, o processo de determinação de objetáveis ​​por diferentes critérios começa (todos os filtros estão incluídos, alguns são personalizáveis):

  • A presença no domínio "blogspot.com".
  • A presença em palavras de uma mistura de letras cirílicas e latinas.
  • A presença de palavras "ruins" (uma lista de palavras "ruins" é personalizável pelo usuário).
  • Ter um usuário redirecionado para um domínio que não seja o original.

Relatório de trabalho


Com base nos resultados da filtragem, um relatório de progresso é compilado.
Ele é criado na forma de uma lista de anúncios para cada filtro em sua coluna, além de uma coluna para anúncios "bons", as seguintes informações são incluídas no relatório:

  • O identificador e o nome textual do anunciante, se houver.
  • Motivo do bloqueio (apenas para bloqueado).
  • Cabeçalhos e texto do anúncio.
  • Destino e URL de visualização.
  • Data e hora da verificação.
  • O número total de visualizações que conseguiram obter um anúncio (apenas para bloqueados).
  • Links para bloquear / desbloquear anúncios e contas de anunciantes.
  • Links para bloquear o URL ou domínio de destino.
  • Link para registrar uma reclamação sobre o anúncio (disponível no novo CPO).
  • Links para adicionar partes diferentes do anúncio à lista de permissões.
  • Link para excluir um anúncio do relatório.

A aparência é baseada no CPO antigo (e o único no momento do design).


Clicável


Quando visualizada em um celular, cada coluna ocupa toda a largura da tela e os botões aparecem para selecionar a coluna que você está visualizando.

Um pouco sobre segurança


Você pode fazer acesso limitado ao painel de controle (para se controlar de um lugar) ou "em todo o mundo" para poder controlar de qualquer lugar.

O primeiro caso é seguro - ninguém vai caber se ele não estiver sentado em um PC em funcionamento. No segundo caso, o endereço em que o software está localizado deve ser mantido em segredo, além da senha para inserir o painel de controle. Para impedir que seu endereço secreto "vaze" ao clicar em links para sites de terceiros (de anúncios), foi feito o seguinte:

  • Cada link externo possui esse atributo
     rel = "noreferrer" 
  • Para referenciador passado apenas dentro do mesmo domínio na cabeça, há uma tag:
     <meta name = "referrer" content = "mesma origem"> 
  • Todos os links externos passam pelo limpador de referência:
     http: //nullrefer.com/? http: //free.da ... 

Resultado de automação


24 horas, 7 dias por semana, todos os anúncios que aparecem nos anúncios de CPO são examinados em intervalos de alguns minutos. Como resultado, objetáveis ​​(de acordo com os critérios especificados pelo usuário) são enviados para a seção "bloqueada". Eu nunca contei isso com certeza, mas de cerca de 100 peças bloqueadas, 90 - 95 foram bloqueadas por um bom motivo. De uma centena de softwares "limpos", em média, menos de um "ruim".

O que eu chamo de "anúncios ruins"? Tudo o que leva a assinaturas móveis, tudo o que oferece "download", basta baixar ou "baixar um arquivo" sem detalhes específicos, tudo o que oferece "assistir a um vídeo", novamente sem detalhes, tudo o que não leva a nada , conforme indicado no título e no texto do anúncio, qualquer menção de cassinos em países onde isso é proibido por lei.

Como resultado, eu praticamente não gasto meu tempo pesquisando e bloqueando anúncios, e os anúncios de cassino e várias mercearias distribuídas pelos meus sites se tornaram dez vezes menos (infelizmente, o problema não foi completamente resolvido - não paro de pensar nisso).

O roubo na forma de assinaturas inconscientes se tornou ainda menos sem um cartão MegaFon!

E de onde vem o cartão MegaFon?
« » « » « »:
«» , . , .

Mas nem todos os usuários de nossos sites têm MegaFoncards e análogos de outros PPSOS.
Portanto, senhores, protejam seus visitantes de cobranças indesejadas por si mesmos!

O projeto de código aberto está no GitHub .

Source: https://habr.com/ru/post/pt422379/


All Articles