предисловие
В последнее время давно не обновлялись новости об объявлении Управления по академическим вопросам Вечуаньского университета.Я думал, что IP мог быть заблокирован.Я проверил журнал и обнаружил, что это не так.Вместо этого полученные страницы были все заменены на обфусцированные js.две форматированные функции
function _$Es(_$Cu) {
_$Cu[14] = _$v9();
_$Cu[_$yf(_$ox(), 16)] = _$Dn();
var _$cR = _$CR();
_$cR = _$iT();
return _$DA();
}
function _$Dk(_$Cu) {
var _$x5 = _$Dv();
var _$x5 = _$EB();
if (_$Ex()) {
_$w9 = _$Dw();
}
_$Cu[_$yf(_$EJ(), 16)] = _$ED();
_$Cu[_$yf(_$Ep(), 16)] = _$EP();
_$w9 = _$EB();
return _$Cu[_$yf(_$v9(), 16)];
}
function _$rK() {
var _$aJ = _$c0(_$DN());
_$aJ = _$BC(_$aJ, 2);
var _$Ce = _$yr(_$qt());
for (var _$Cu = 0; _$Cu < _$aJ[_$gX()]; _$Cu++) {
_$aJ[_$Cu] = _$Ce + _$aJ[_$Cu];
}
return _$aJ;
}
Смотреть на эту кучу — большая голова, но в соответствии с принципом, что до тех пор, пока браузер может отображать, сканер страниц может сканировать, мы будем решать эту проблему шаг за шагом.
анализировать
- Сначала я использовал postman, чтобы отправить запрос, и обнаружил, что была возвращена куча искаженных символов.
- Скопируйте заголовок запроса обычной страницы рендеринга и повторно отправьте запрос, чтобы получить обычную страницу. Рассмотрим две возможности: одна — это специальная обработка заголовка, а другая — проблема с файлом cookie.
- Остальное содержимое заголовка остается без изменений, удалите куки и повторно отправьте запрос, и снова получите кучу искаженных символов. Проблема успешно обнаружена, это должна быть проблема с файлами cookie
- Очистить кеш хрома, перезагрузить страницу, проверить запись запроса, видно, что страница загружается дважды всегоКуки не возвращаются при первой загрузкеВторая загрузка вернула
JSESSIONID
, это должен быть последний необходимый файл cookie - Наблюдая за серединой двух запросов, мы можем обнаружить, что есть еще два запроса.Эти два запроса должны быть причиной возврата куки во второй раз.Первый запрос - это js файл внешней ссылки на странице, а второй запрос должен быть Запрос, отправленный запутанным js, ушел.
- Из-за ограниченной силы я не анализировал, как загружается эта логика после нескольких часов анализа. Но я подумал о том, чтобы скопировать файл cookie прямо из браузера и использовать его для сканера? Но с этим тоже есть проблема, то есть невозможно каждый раз получать куку вручную, что не даст нужного эффекта. Затем посмотрите, что Python использует
Selenium
Чтобы полностью имитировать рендеринг в браузере, а затем проанализировать случай с поисковым роботом, я узнал, есть ли подобное решение для рендеринга в браузере в golang, и нашел его на всемогущем гейхабе.chromedp
. Следующее использует chromedp для решения этой проблемы.
chromedp
Package chromedp is a faster, simpler way to drive browsers (Chrome, Edge, Safari, Android, etc) without external dependencies (ie, Selenium, PhantomJS, etc) using the Chrome Debugging Protocol.
1.установить (рекомендуется использовать лестницу)
go get -u github.com/chromedp/chromedp
2.code
Запустив следующий код, вы увидите, что хром откроет всплывающее окно и запустит веб-страницу и, наконец, выведет ожидаемый HTML-код в консоль, но нам нужно только получить правильный файл cookie, который позже используется для сканирования веб-страницы. . Если всем страницам нужно ждать, пока хром просканирует после рендеринга, то эффективность слишком низкая.
package main
import (
"context"
"fmt"
"io/ioutil"
"log"
"time"
"github.com/chromedp/cdproto/cdp"
"github.com/chromedp/chromedp"
)
func main() {
var err error
// create context
ctxt, cancel := context.WithCancel(context.Background())
defer cancel()
// create chrome instance
c, err := chromedp.New(ctxt, chromedp.WithLog(log.Printf))
if err != nil {
log.Fatal(err)
}
// run task list
var res string
err = c.Run(ctxt, chromedp.Tasks{
// 访问教务处页面
chromedp.Navigate(`http://jwc.scu.edu.cn/jwc/moreNotice.action`),
// 等待table渲染成功,成功则说明已经获取到了正确的页面
chromedp.WaitVisible(`table`, chromedp.ByQuery),
// 获取body标签的html字符
chromedp.OuterHTML("body", &res),
})
if err != nil {
log.Fatal(err)
}
// 关闭chrome实例
err = c.Shutdown(ctxt)
if err != nil {
log.Fatal(err)
}
// 等待chrome实例关闭
err = c.Wait()
if err != nil {
log.Fatal(err)
}
// 输出html字符串
log.Printf(res)
}
3. Получить куки
Измените код списка задач на шаге 2, чтобы получить файл cookie.После модификации вы можете увидеть, что в консоли выводится строка файла cookie.Используя этот файл cookie для проверки в почтальоне, вы можете обнаружить, что вы можете получить правильную страницу . На этом этапе он должен быть в основном завершен, но все еще есть недостаток: окно Chrome будет всплывать каждый раз, когда он запускается, сканер работает на сервере без страницы графического интерфейса и затраты времени на открытие экземпляра Chrome каждый раз. также больше.
// 将chromedp.OuterHTML("body", &res) 替换为下面的代码
chromedp.ActionFunc(func(ctx context.Context, h cdp.Executor) error {
// 获取cookie
cookies, err := network.GetAllCookies().Do(ctx, h)
// 将cookie拼接成header请求中cookie字段的模式
var c string
for _, v := range cookies {
c = c + v.Name + "=" + v.Value + ";"
}
log.Println(c)
if err != nil {
return err
}
return nil
}),
5. Используйте безголовый режим Chrome
а. Используйте докер для запуска безголового режима Chrome
docker run -d -p 9222:9222 --rm --name chrome-headless knqz/chrome-headless
б. Изменить код
Вы можете видеть, что основное отличие состоит в том, что при создании экземпляра хрома вы не запускаете хром, и, конечно, вам не нужно его закрывать в конце.
package main
import (
"context"
"log"
"github.com/chromedp/chromedp/client"
"github.com/chromedp/cdproto/network"
"github.com/chromedp/cdproto/cdp"
"github.com/chromedp/chromedp"
)
func main() {
var err error
// create context
ctxt, cancel := context.WithCancel(context.Background())
defer cancel()
// create chrome instance
c, err := chromedp.New(ctxt, chromedp.WithTargets(client.New().WatchPageTargets(ctxt)), chromedp.WithLog(log.Printf))
if err != nil {
log.Fatal(err)
}
// run task list
err = c.Run(ctxt, chromedp.Tasks{
// 访问教务处页面
chromedp.Navigate(`http://jwc.scu.edu.cn/jwc/moreNotice.action`),
// 等待table渲染成功,成功则说明已经获取到了正确的页面
chromedp.WaitVisible(`table`, chromedp.ByQuery),
// 获取body标签的html字符
chromedp.ActionFunc(func(ctx context.Context, h cdp.Executor) error {
// 获取cookie
cookies, err := network.GetAllCookies().Do(ctx, h)
// 将cookie拼接成header请求中cookie字段的模式
var c string
for _, v := range cookies {
c = c + v.Name + "=" + v.Value + ";"
}
log.Println(c)
if err != nil {
return err
}
return nil
}),
})
if err != nil {
log.Fatal(err)
}
}
Вы можете в основном использовать его здесь.После получения файла cookie вы можете использовать метод, который вам нравится, чтобы получить страницу.