Что нового

Извлечение текста по трудоустройству с сайта

Сообщения
34
Репутация
0
Добрый вечер. Помогите решить проблему.

Есть скрипт вытаскивающий с сайта по трудоустройству chastnik.ru - адреса вакансий.
Код:
#include <Inet.au3>
#include <FileConstants.au3>
Global $g_sFile = @ScriptDir & "\JobList.txt", $g_sPath = "/aob/22"
_DumpJobList($g_sFile, $g_sPath)

Func _DumpJobList($sFile, $sPath)
    Local $sURL = "https://chastnik.ru", $sHTML, $aRegExp, $sOut, $hFile
    While 1
;~         $sHTML = _INetGetSource($sURL & $sPath)  ; было
;~         If @error Then ExitLoop                  ;
        ;
        $sHTML = INetRead($sURL & $sPath, $INET_FORCERELOAD)
        If @error Then ExitLoop                               ;
        $sHTML = BinaryToString($sHTML, $SB_UTF8)             ; не забываем кодировку страницы UTF8
        ;
        $aRegExp = StringRegExp($sHTML, '<div class="large-12 columns aob__text"><a href="(.+?)">(.*?)</a></div>', $STR_REGEXPARRAYGLOBALMATCH)
        If Not @error Then
            For $i = 0 To UBound($aRegExp) - 1 Step 2
                $sOut &= "URL=" & $sURL & $aRegExp[$i] & @CRLF & "Desc=" & $aRegExp[$i + 1] & @CRLF & @CRLF
            Next
        EndIf
        $aRegExp = StringRegExp($sHTML, '<a class="block_white navigation__arrow navigation__next" href="(.+?)" title="Следующая страница">След.</a>', $STR_REGEXPARRAYMATCH)
        If @error Then ExitLoop
        $sPath = $aRegExp[0]
    WEnd
;~     $hFile = FileOpen($sFile, $FO_OVERWRITE)                 ; было
    $hFile = FileOpen($sFile, BitOr($FO_OVERWRITE, $FO_ANSI))   ; стало: кодировку можно заменить на $FO_UTF8
    FileWrite($hFile, $sOut)
    FileClose($hFile)
EndFunc   ;==>_DumpJobList
Как аналогичным образом вытащить текст из списков с сайта irr.ru ?
Адрес первой страницы https://ivanovo.irr.ru/jobs-education/
Адрес второй страницы https://ivanovo.irr.ru/jobs-education/page2/ и т.д.

(Если изменить по аналогии название сайта в скрипте - то скрипт выдаст пустой незаполненный файл JobList.txt )
Код:
#include <Inet.au3>
#include <FileConstants.au3>
Global $g_sFile = @ScriptDir & "\JobList.txt", $g_sPath = "/jobs-education"
_DumpJobList($g_sFile, $g_sPath)

Func _DumpJobList($sFile, $sPath)
    Local $sURL = "https://irr.ru", $sHTML, $aRegExp, $sOut, $hFile
    While 1
;~         $sHTML = _INetGetSource($sURL & $sPath)  ; было
;~         If @error Then ExitLoop                  ;
        ;
        $sHTML = INetRead($sURL & $sPath, $INET_FORCERELOAD)
        If @error Then ExitLoop                               ;
        $sHTML = BinaryToString($sHTML, $SB_UTF8)             ; не забываем кодировку страницы UTF8
        ;
        $aRegExp = StringRegExp($sHTML, '<div class="large-12 columns aob__text"><a href="(.+?)">(.*?)</a></div>', $STR_REGEXPARRAYGLOBALMATCH)
        If Not @error Then
            For $i = 0 To UBound($aRegExp) - 1 Step 2
                $sOut &= "URL=" & $sURL & $aRegExp[$i] & @CRLF & "Desc=" & $aRegExp[$i + 1] & @CRLF & @CRLF
            Next
        EndIf
        $aRegExp = StringRegExp($sHTML, '<a class="block_white navigation__arrow navigation__next" href="(.+?)" title="Следующая страница">След.</a>', $STR_REGEXPARRAYMATCH)
        If @error Then ExitLoop
        $sPath = $aRegExp[0]
    WEnd
;~     $hFile = FileOpen($sFile, $FO_OVERWRITE)                 ; было
    $hFile = FileOpen($sFile, BitOr($FO_OVERWRITE, $FO_ANSI))   ; стало: кодировку можно заменить на $FO_UTF8
    FileWrite($hFile, $sOut)
    FileClose($hFile)
EndFunc   ;==>_DumpJobList
 

Alecsis

Осваивающий
Сообщения
98
Репутация
41
Привет ещё раз!
Просто так
изменить по аналогии название сайта в скрипте
не прокатит, структура страниц на ivanovo.irr.ru/jobs-education/ совершенно другая. Соотв-но и прежние regexp'ы по боку.

В общем, немного развил тему из заготовки для похожего случая. Ну и причесал код в привычном для себя стиле по принципу «разделяй и властвуй», добавив побольше комментов.
В общих чертах концепция такая: основная программа передаёт в функцию JobList_Build URL начальной страницы, имя и кодировку выходного файла. Эта ф-ция открывает файл результата, и в цикле для каждой из страниц №№ 1, 2, … N передаёт в функцию JobList_ParsePage основной URL, путь к нужной странице и хендл выходного JobList-а. Та в свою очередь выполняет всю черновую работу по выдёргиванию нужных сведений с каждой страницы, не заморачиваясь ненужными подробностями и пишет в выходной файл некое подобие отчёта.

Плюс доза извращений «украшательств», к-рые на логику работы не влияют, но с ними как-то понятнее и нет ощущения, что прога повисла или вообще свалилась.
Получилось нечто «на лицо ужасное, но доброе внутри» © на вид монстроподобное, зато кмк пригодное к относительно безболезненной модернизации. Как-то так:

Код:
#pragma compile(Console, True)
#cs
  https://ivanovo.irr.ru/jobs-education/
    на каждой странице по-видимому надо найти нечто подобное:
    ....
    <a href="https://ivanovo.irr.ru/jobs-education/vacancies/assistance/pomoschnik-rukovoditelya-advert700776372.html" class="listing__itemTitle">
    …
    <div class="js-productListingProductName">Помощник руководителя</div>
    …
    <div class="listing__itemParameter listing__itemParameter_text js-listingText">Репетитор по математике от дошкольника до выпускника.  Текущие темы . Повторение.  Опережение...</div>
    ....

  Аналогично для
  https://ivanovo.irr.ru/jobs-education/page2/
  https://ivanovo.irr.ru/jobs-education/page3/ итд
  ...
#ce

Opt('MustDeclareVars', True)
;
; #include <AutoItConstants.au3>
#include <FileConstants.au3>
#include <StringConstants.au3>
#include <Inet.au3>

Local Const _
  $csURL_Main = 'https://ivanovo.irr.ru/jobs-education/', _
  $csFile_Out = 'JobList.txt'

JobList_Build($csURL_Main, $csFile_Out, $FO_ANSI)

Exit

Func JobList_Build(   _ ; формирование списка пунктов (= вакансий/предложений)
    $psURL_Main,      _ ; [in] стартовая страница, откуда выбивать инфу
    $psOutFile,       _ ; [in] имя файла-отчёта
    $pnOutCP          _ ; [in] кодировка файла-отчёта
  )                     ; --> возвращает кол-во найденных пунктов
  Local _
    $hFile,           _ ; хендл файла-отчёта
    $nPage = 0,       _ ; № обрабатываемой страницы
    $sPage_Ref,       _ ; путь к этой странице относительно стартовой
    $nJob_Items,      _ ; кол-во найденных на странице пунктов
    $bFinish = False, _ ; флажок выхода из осн. цикла
    $nResPages = 0,   _ ; кол-во успешно обработанных страниц
    $nResItems = 0      ; кол-во найденных пунктов
  ;
  ConsoleWrite('Start with URL = ' & $psURL_Main & @CRLF)       ; лог обработки
  ;
  $hFile = FileOpen($psOutFile, BitOR($FO_OVERWRITE, $pnOutCP)) ; новый отчёт в нужной кодировке
  FileWriteLine($hFile, 'Обработка ' & $psURL_Main)
  FileWriteLine($hFile, Null)
  ;
  While(True)
    $nPage += 1           ; № очередной страницы
    If ($nPage > 1) Then  ; начиная с №2 URL дополняется канонiчнымЪ довеском «pageN/»
        $sPage_Ref = StringFormat('page%d/', $nPage)
        ;
      Else                ; а вот с начальной страницей имеем извращение:
        $sPage_Ref = ''   ; вместо логичного «page1/» довесок почему-то отсутствует
        ;                 ; оставим сие на совести сайтоклепателей и примем как должное…
    EndIf
    #cs
    а теперь, собсс-но, для чего всё это затеяли:
    сказать что-то во избежание гадкого чувства, что прога ушла в астрал
    и собсс-но распатронить страницу
    #ce
    ConsoleWrite('Parsing ' & $psURL_Main & $sPage_Ref & '  ... ')
    $nJob_Items = JobList_ParsePage($psURL_Main, $sPage_Ref, $hFile, $nResItems)
    ;
    Select
      Case ($nJob_Items > 0)  ; Ok, что-то нашли
        $nResPages += 1       ; сч-к успешных страниц += 1 не сильно нужен, но пусть живёт
        ConsoleWrite('Ok! # items found = ' & $nJob_Items)
        ;
      Case ($nJob_Items = 0)                  ; а на этой странице мимо кассы
        ConsoleWrite('Error: no items found') ; мб не совсем корректно сразу сливаться в закат,
        $bFinish = True                       ; но вряд ли где-нибудь на page123/ найдётся сабж
        ;
      Case Else                               ; тут всё по рабоче-крестьянски:
        ConsoleWrite('Error: page not found') ; страницы нет, и аналогично предыдущему
        $bFinish = True                       ; случаю ($nJob_Items=0) и не предвидится
    EndSelect
    ConsoleWrite(@CRLF)
    If $bFinish Then ExitLoop ; good bye
  Wend
  ;
  FileWriteLine($hFile, 'Задание завершено')  ; наконец всё завершаем по классике жанра
  FileWriteLine($hFile, Null)
  FileClose($hFile)
  ;
  ConsoleWrite('Total ' & $nResItems & ' job(s) in ' & $nResPages & ' page(s) found' & @CRLF)
  ConsoleWrite('Finish' & @CRLF)
  Return $nResItems
EndFunc     ; ==> JobList_Build

Func JobList_ParsePage( _ ; разбор конкретной страницы со списком работ
    $psURL_Root,        _ ; [in]  «корневой» URL, напр. https://ivanovo.irr.ru/jobs-education/
    $psURL_Page,        _ ; [in]  путь от корневого URL к нужной странице, напр. page2/
    $hOut,              _ ; [in]  хендл файла-списка работ
    ByRef $pnTotalRefs  _ ; [i/o] общее кол-во интересующих ссылок;
  ) ; рез-т > 0 = кол-во найденных пунктов на странице; 0 = нет; < 0 = страница не найдена
  #cs
  регекспы описывают в порядке физического появления:
  – URL конкретной страницы с вакансией/предложением
  – краткое описание наподобие «Помощник руководителя»
  – подробности в стиле «Репетитор по математике от дошкольника до выпускника […]»
  всё это перемежается целой кучей всякого неактуального в данном случае HTML-кода
  #ce
  Local Const _
    $csRE_URL   = '<a href="(\Q' & $psURL_Root & '\E[[:graph:]]+?\.html)" class="listing__itemTitle">', _
    $csRE_Short = '<div class="js-productListingProductName">(.*?)</div>', _
    $csRE_Long  = '<div class="listing__itemParameter listing__itemParameter_text js-listingText">(.*?)</div>', _
    $csRE_Main  = '(?is)'     & _ ; весь текст одной строкой;  игнорить регистр не обязательно, но как-то надёжнее
                  $csRE_URL   & _ ; фрагмент кода с URL искомой страницы
                  '.*?'       & _ ; какой-то html-код
                  $csRE_Short & _ ; фрагмент с кратким описанием пункта
                  '.*?'       & _ ; какой-то html-код
                  $csRE_Long      ; фрагмент с подробным описанием пункта
  Local _
    $sHTML, _ ; содержимое обрабатываемой страницы
    $vREs,  _ ; результат разбора на осн. регекспа
    $N = 0, _ ; кол-во обнаруженных на странице пунктов
    $i        ; и так ясно :-)
  #cs
  тут уже всё прямолинейно: читаем весь «фарш;
  если что-то прочиталось — конвертим в текст (помним про кодировку оригинала UTF-8!)
  и ковыряем StringRegExp'ом на предмет поиска искомой инфы
  #ce
  $sHTML = INetRead($psURL_Root & $psURL_Page, $INET_FORCERELOAD)
  If (@error) Then Return -1
  $sHTML = BinaryToString($sHTML, $SB_UTF8)
  $vREs  = StringRegExp($sHTML, $csRE_Main, $STR_REGEXPARRAYGLOBALMATCH)
  ;
  If Not(@error) Then
    For $i = 0 To UBound($vREs) - 1  Step 3 ; по 3 строки на пункт
      $N += 1
      $pnTotalRefs += 1
      FileWriteLine($hOut, StringFormat('URL %-4d = %s', $pnTotalRefs, $vRes[$i  ]))
      FileWriteLine($hOut, 'Кратко   = ' & $vRes[$i+1])
      FileWriteLine($hOut, 'Подробно = ' & $vRes[$i+2])
      FileWriteLine($hOut, Null)
    Next
  EndIf
  Return $N
EndFunc     ; ==> JobList_ParsePage

Реальный пример выдачи в JobList.txt
Код:
Обработка https://ivanovo.irr.ru/jobs-education/

URL 1    = https://ivanovo.irr.ru/jobs-education/education/tutors/repetitor-po-istorii-i-obschestvoznaniyu-advert700921420.html
Кратко   = Репетитор по истории и обществознанию
Подробно = Подготовка к ЕГЭ и ОГЭ,  итоговым административным работам,  Всероссийским проверочным работам (ВПР...

URL 2    = https://ivanovo.irr.ru/jobs-education/education/languages/repetitorstvo-po-angliyskomu-yazyku-advert701251845.html
Кратко   = Репетиторство по Английскому Языку
Подробно = Всем привет!Меня зовут Денис. 
. . . . .
. . . . .
URL 104  = https://ivanovo.irr.ru/jobs-education/vacancies/logistics/pomoschnik-na-sklad-advert700000782.html
Кратко   = Помощник на склад
Подробно = Обязанности:  работа с клиентскими заказами,  согласование заказа с клиентом в соответствие с его...

Задание завершено

Пример консольного лога:
Код:
Start with URL = https://ivanovo.irr.ru/jobs-education/
Parsing https://ivanovo.irr.ru/jobs-education/  ... Ok! # items found = 30
Parsing https://ivanovo.irr.ru/jobs-education/page2/  ... Ok! # items found = 30
Parsing https://ivanovo.irr.ru/jobs-education/page3/  ... Ok! # items found = 30
Parsing https://ivanovo.irr.ru/jobs-education/page4/  ... Ok! # items found = 14
Parsing https://ivanovo.irr.ru/jobs-education/page5/  ... Error: no items found
Total 104 job(s) in 4 page(s) found
Finish
P.S. Если нет желания загромождать форум, пишите в личку или на e-mail — чем могу, помогу
 
Верх