Страницы

Поиск по вопросам

Показаны сообщения с ярлыком парсер. Показать все сообщения
Показаны сообщения с ярлыком парсер. Показать все сообщения

среда, 15 апреля 2020 г.

Синтаксический анализатор (построение грамматики) ?

#синтаксический_анализ #парсер

                    
Нужно построить синтаксический анализатор. В частности для языка создать  контекстно-зависимую
грамматику( LL) Везде встречаются примеры только для чисел и знаков, у меня присутствуют
только 4 буквы(A, B, C, D)  и для них надо построить грамматику .
Есть ли примеры построения грамматики ?    


Ответы

Ответ 1



Тут не плохой пример. Грамматика это просто набор правил. Таблица синтаксического анализа лишь отражает порядок применения этих правил.

четверг, 9 апреля 2020 г.

Как получить содержимое страницы, которая грузится через AJAX?

#php #ajax #angularjs #http #парсер

                    
Получить содержимое страницы на PHP.
Раньше я делал это достаточно легко через file_get_contents( $url ). Но на одном
сайте список товаров грузится ajax-om, точнее ангуляром.
    То есть если открыть такую страницу в браузере, у вас будет крутиться лоадер
и через некоторе время появятся товары.

Функция file_get_contents( $url ) получает сырой код, то есть типа

{{tovari.name}}
Как получить обработанное( загруженное ) содержимое страницы?


Ответы

Ответ 1



Попробуйте подключиться через curl к нужной странице, должно сработать, например: $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HEADER, false); curl_setopt($curl, CURLOPT_FAILONERROR, 1); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false); curl_setopt($curl, CURLOPT_POST, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($curl) curl_close($curl);

Ответ 2



Вам может помочь phantomjs. Через метод evaluate вы получите контекст загруженной страницы, а дальше можете либо качать всю страницу, либо весь арсенал JS селекторов у вас в руках. Пример взят с офф. сайта: var webPage = require('webpage'); var page = webPage.create(); page.open('http://m.bing.com', function(status) { var title = page.evaluate(function() { return document.title; }); console.log(title); phantom.exit(); });

Ответ 3



С помощью библиотеки CURL это возможно. Недавно сайт парсил где все на ajax и с библиотекой jQuery. Так если парсишь с помощью curl и потом выводим в браузер, то будет все криво, потому-что клиент в данный момент CURL(сервер), а не Вы. Кроссдоменный запрос не прокатит поэтому нужно взять к примеру библиотеку Simple HTMLDOM $curl = curl_init(); curl_setopt($curl, CURLOPT_FAILONERROR, 1); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // allow redirects curl_setopt($curl, CURLOPT_TIMEOUT, 10); // times out after 4s curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // return into a variable curl_setopt($curl, CURLOPT_URL, "https://ya.ru/"); curl_setopt($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 GTB6"); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($curl); Выводить $data не нужно. Всё, ваш клиент (сервер) получил страницу. Теперь скачиваем http://simplehtmldom.sourceforge.net/ И есть инструкция например здесь http://zubuntu.ru/php-simple-html-dom-parser/ То есть нам нужно продолжить так: $html=str_get_html($data); $result=$html->find(div.spisok span); //получаем массив Дальше его перебираем. foreach ($result as $one){ echo $one; //можем уже выводить то, что нашли } По такому принципу ищем данные, перебираем их. Важно точно определить "координаты" данных.

Ответ 4



Ну тут же все тоже самое загружаете инструмент разработчика , в любом браузере . В хроме и ему подобных (опера , яндекс , рамблер итд) он встроеный в мозиле firebug смотрите что грузится у вас после загрузки страницы , берете этот url подставляете свои параметры и тем же file_get_contents качаете контент

Ответ 5



В хроме я использую расширение https://chrome.google.com/webstore/detail/quick-source-viewer/cfmcghennfbpmhemnnfjhkdmnbidpanb?utm_source=chrome-app-launcher-info-dialog После загрузки страницы и отработки скриптов можно посмотреть результат со всеми изменениями.

вторник, 31 марта 2020 г.

Парсинг безымянных блоков в AngleSharp

#c_sharp #парсер #anglesharp


Подскажите пожалуйста как из этого блока выбрать только вот это : 8.85 р / шт

дисконт 8.60
8.85 р / шт
Сейчас пробую так: var price = document.Result.QuerySelectorAll(@".price"); Но в результате выводится все, что находится в блоке


Ответы

Ответ 1



Я дал вам ссылку на вопрос на enSO, там есть красивый вариант (через чтение AngleSharp'ом безымянных блоков CSS) и мой варварский в вопросе (вырезанием всех "лишних" нод). В вашем случае начните с чего-то типа: var parser = new HtmlParser(); var document = parser.Parse(@"
дисконт 8.60
8.85 р / шт
"); var priceBlocks = document.QuerySelectorAll("div.price"); foreach (var block in priceBlocks) { var element = block.ChildNodes.First(o => o.NodeType == AngleSharp.Dom.NodeType.Text && o.TextContent.Trim() != ""); element.Text().Trim().Dump(); } Linqpad говорит, что вам вполне сойдёт для начала: Писал наспех, поэтому подразумеваю, что вы понимаете, что такое linq.

понедельник, 30 марта 2020 г.

BeautifulSoup: построчная обработка таблицы

#python #python_3x #парсер #beautiful_soup #bs4


Помогите пожалуйста разобраться, пытаюсь обработать выгрузку информации о Сisco телефоне
в формате HTML. Необходимые данные лежат в table[2]



    Cisco
Systems, Inc.


Device information

Cisco IP Phone

Device information
Streaming statistics
   Stream 1
...
Service modeEnterprise
Service domain
App load IDrootfs8845_65.12-1-1-12
При попытке вытащить параметры аппарата из таблицы, не отображаются строки param = soup.findChildren("table"[2]) print(param) В выводе получается список без какой либо привязки к строкам, все параметры подряд: .... Service mode, Enterprise, Service domain, , Service state, Idle, .... Однако если сделать поиск по тегу "DIV" param = soup.findChildren("div") print(param) На выводе будет строка необходимых данных, но ее нельзя прогнать через цикл что бы создать словарь, где параметры из одной строки будут ключом - значением (пример "Service mode" : "Enterprise") Подскажите, как правильно обработать таблицу, чтобы создать словарь из параметров в table[2]


Ответы

Ответ 1



Попробуйте так: from bs4 import BeautifulSoup # ... table = root.select_one('table:nth-of-type(3)') # Или так: table = soup.select('table')[2] name_by_value = dict() for tr in table.select('tr'): tds = tr.select('td') name, value = tds[0].text.strip(), tds[2].text.strip() name_by_value[name] = value print(name_by_value) # {'Service mode': 'Enterprise', 'Service domain': '', 'App load ID': 'rootfs8845_65.12-1-1-12'} PS. Заметил, что нужные значения ячеек находятся исключительно в , а значит можно немного конкретизировать поиск: ... for tr in table.select('tr'): tds = [x.text.strip() for x in tr.select('td > b')] name, value = tds[0], tds[1] name_by_value[name] = value ... А если элементов всегда ожидается два, то воспользоваться распаковкой: ... for tr in table.select('tr'): name, value = [x.text.strip() for x in tr.select('td > b')] name_by_value[name] = value ...

воскресенье, 29 марта 2020 г.

Извлечение домена из ссылки и поиск ссылок по имени домена

#python #парсер #url #urllib


Задача стоит такая:


Сверка ссылок по домену(*) из TXT №2 с TXT №1
Сохранение уникальны ссылок в отдельный TXT №3
Добавление уникальных ссылок в TXT №1


При сверке по  доменам - идет сверка только доменов сайта без: http:// и без https://
, так же при сверке по домену не учитывается все что после доменной зоны (.com , .ru
, и т.п.)

Я разделил программу на подзадачи и написал код на python 3.8:
Подзадачи: 

Исходные данные:

1.txt

http://site.com/
https://sit1e.com/vwdsvdfw/vwdefei/userpanel?cid=2
https://site.com/index.php?id=1
http://sit2e.com/
http://site.com/vwifow/fwviiwf?

2.txt

http://site.com/
https://sit1e213.com/vwdsvdfw/vwdefei/userpanel?cid=2
https://site.com/index.php?id=1
http://sit222e.com/
http://site.com/vwifow/fwviiwf?


1) Достать домены:

import re

f1 = open('1.txt')
f2 = open('2.txt')

filevar1 = f1.read()
filevar2 = f2.read()

domains1 = re.findall(r'\/\/([\w\-]+)', filevar1) 
domains2 = re.findall(r'\/\/([\w\-]+)', filevar2)

#Вывод доменов с новой строки 

with open('domains1.txt','w') as out:
    for domen in domains1:
        print(domen,file=out)
with open('domains2.txt','w') as out:
    for domen in domains2:
        print(domen,file=out)

f1.close()
f2.close()

input('Нажмите Enter, чтобы выйти из программы')


Результат работы участка кода:

domains1.txt

site
sit1e
site
sit2e
site

domains2.txt

site
sit1e213
site
sit222e
site


2) Сравнить домены:

import re

def diff():
    with open('result1.txt') as text_one, \
            open('result2.txt') as text_two:
        return set(text_one) ^ set(text_two)
if __name__ == '__main__':
    with open('output.txt', 'w') as result:
        for i in diff():
            result.write(i)

input('Нажмите Enter, чтобы выйти')


Выходные данные:

output.txt

sit1e
sit2e
sit1e213
sit222e


3) Найти исходные строки по выделенным доменам в исходных файлах и записать их в
отдельный файл.
с этим возникают проблемы. Не знаю какую регулярную функцию использовать.

PS: пока искал ответ на свой вопрос, то заметил, что моя программа не учитывает субдомены,
вроде для этого уже существует специальная функция в python: urlparse, но я не могу
понять как ее использовать.

Можно ли как-то сократить код программы, чтобы не писать 3-й блок программы?
Можно-ли реализовать эту задачу проще?
    


Ответы

Ответ 1



Для чтения доменов из файлов со ссылками можно использовать следующую функцию: from urllib.parse import urlparse def get_domains(filename): with open(filename) as f: return ['.'.join(urlparse(line.strip()).netloc.split('.')[:-1]) for line in f] Проверка: dom1 = get_domains(r'C:\temp\1.txt') dom2 = get_domains(r'C:\temp\2.txt') print(dom1) # ['site', 'sit1e', 'site', 'sit2e', 'site'] print(dom2) # ['site', 'sit1e213', 'site', 'sit222e', 'site'] Работа со списками доменов как со множествами - объединение, пересечение, симметрическая разность: In [31]: set(dom1) | set(dom2) Out[31]: {'sit1e', 'sit1e213', 'sit222e', 'sit2e', 'site'} In [32]: set(dom1) & set(dom2) Out[32]: {'site'} In [33]: set(dom1) ^ set(dom2) Out[33]: {'sit1e', 'sit1e213', 'sit222e', 'sit2e'} Поиск ссылок по списку доменов: import re def search_domains(filename, doms): with open(filename) as f: text = f.read() pat = r'(https?://[^./\r\n]*?\b(?:{})\b[^\r\n]*)'.format('|'.join(doms)) return re.findall(pat, text) Проверка: In [47]: doms = set(dom1) ^ set(dom2) In [48]: doms Out[48]: {'sit1e', 'sit1e213', 'sit222e', 'sit2e'} In [49]: search_domains(r'C:\temp\1.txt', doms) Out[49]: ['https://sit1e.com/vwdsvdfw/vwdefei/userpanel?cid=2', 'http://sit2e.com/'] In [50]: search_domains(r'C:\temp\2.txt', doms) Out[50]: ['https://sit1e213.com/vwdsvdfw/vwdefei/userpanel?cid=2', 'http://sit222e.com/'] PS с записью результатов в файл я думаю вы справитесь сами.

суббота, 21 марта 2020 г.

Как извлечь “скрытую” информацию из тегов с помощью Python и BeautifulSoup?

#python #парсер


Хочу сделать парсинг страниц Яндекс.Дзена, чтобы вытащить оттуда теги каждой публикации
и колчество прочитываний. Делаю это на Python с помощью BeautifulSoup.
При извлечение HTML кода страницы кодом

import urllib.request

from bs4 import BeautifulSoup

url = 'https://zen.yandex.ru/media/filmmaking/esli-vam-nravitsia-liucifer-posmotrite-i-eti-13-serialov-5d0f25adb34feb00af5df506'
response = urllib.request.urlopen(url)
page = BeautifulSoup(response, features="lxml")
print(page)


блоки, где находятся теги 



"теги"
и счетчик просмотров 13 тыс. дочитываний оказываются пустыми. Позволяет ли яндекс.дзен вообще достать эту информацию? Теми ли средствами я пользуюсь? В парсинге новичок)


Ответы

Ответ 1



Проблема в том, что BeautifulSoup не исполняет JS код, будь то отрисовывающий страницу или получающий данные из БД. Поэтому теги не заполнены, и данных внутри вы не видите. Используйте для этих целей Selenium, там точно все должно быть хорошо, так как запускается инстанс браузера, который точно отрендерит вам страничку и вернет полностью готовый html.

воскресенье, 15 марта 2020 г.

Firefox Bookmarks Reference (JSON)

#json #парсер #firefox


Хочу отпарсить JSON с сохраненными закладками из Firefox, но там очень много параметров,
о назначении которых можно только догадываться (в частности, типы папок). А я хочу
сделать нормальный импорт закладок из FF в свой софт (не костыльный, а в соответствии
с документацией, которую я, к сожалению, на нашел).

Есть ли вообще такое? Или может кто разбирался в этом вопросе и написал свою инструкцию? :)

P.S. На https://developer.mozilla.org/ не нашел. Есть некоторые похожие вопросы,
но по сути не то: https://stackoverflow.com/questions/904522/output-firefox-json-data.
    


Ответы

Ответ 1



Firefox хранит закладки, историю загрузок и посещений в базе данных SQLite, в файле places.sqlite, который находится в папке %APPDATA%\Mozilla\Firefox\Profiles\[RANDOM.PROFILENAME]. В своей программе Вы можете открыть эту базу и прочесть любые интересующие данные (в том числе и перевести их в формат JSON). Есть небольшое разъяснение по структуре тут: http://kb.mozillazine.org/Places.sqlite и тут: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/Places/Database Схема для лучшего ознакомления: При создании профиля, создаётся папка с случайным набором символов, отделяющий себя точкой, в начале названия профиля: [RANDOM.PROFILENAME]. Чтобы узнать полный путь к профилю, Вам понадобиться ещё прочитать INI файл profiles.ini который находится в папке %APPDATA%\Mozilla\Firefox\Profiles. В файле profiles.ini несколько параметров: [Profile0] Name=default IsRelative=1 Path=Profiles/s0ddpsc9.default Default=1 Вас интересует именно ключ Path, который указывает на полный путь к конкретному профилю. В Firefox есть ещё возможность сделать резервную копию вручную, в окне закладок, пункт: Import and Backup > Restore... на выходе вы получите готовый JSON файл.

Ответ 2



bookmarks.json - это детали реализации, не стандартный формат. Поэтому у него нет описания, и он может и будет меняться с доработками Firefox. Есть более стабильный формат bookmarks.html, для которого есть куча реализаций и даже, вроде как, документация (https://msdn.microsoft.com/en-us/library/aa753582%28v=vs.85%29.aspx), но в котором не содержится все богатство информации из Firefox. Если хотите связываться с JSON - разберитесь в текущем формате и обязательно добавьте проверки, что формат соответствует тому, что вы ожидаете. Вот тут есть краткое описание общей структуры (которая, в общем, и из примера понятна). Истина в последней инстанции - это код, который этот файл пишет. Сейчас это PlacesUtils.promiseBookmarksTree().

пятница, 13 марта 2020 г.

Как сохранить веб-страницу в формат mht программно?

#парсер


Решил заранее подготовить все ссылки страниц, а после сохранять их в формате .mht
Например, в .txt файле находятся все ссылки (каждая с новой строчки). Программа должна
читать оттуда ссылки и сохранять в формате .mht на жесткий диск.

Можно ли это реализовать программно и какую технологию лучше использовать?

Зачем мне это нужно?


  Есть один интернет-магазин. С него мне нужно скачать все изображения
  товаров. Пытался использовать jQuery через расширения Google Chrome.
  Пытался писать приложение на C#. Но, почему-то, загружаются не все
  картинки каталога.
  
  Вот, например эта страница: 
  www.onlinetrade.ru/catalogue/smartfoni-c13 Здесь показано 50 товаров.
  Ищу все конструкции "img". Скачиваю. В итоге, загружаются только
  первые 7 картинок товаров. В итоге, решил загрузить таким способом,
  описанным выше.

    


Ответы

Ответ 1



Точно ли сохраняет первые 7, а не 10 фото? Там на странице фильтр 10, 20, 50. Возможно ваш парсер просто не умеет наверное нажимать на цифру 50, для фильтра. А если 7, то возможно просто получалось что берет первую картинку и идет на следующую страницу. Там берет тоже первую и т.д. Соответственно, возможно вы просто чего-то не учли. Почему я так думаю? Потому, что урл спокойно себе парсится. Картинки (и не только) достаются без проблем. Вот пример с использованием php и Simple HTML DOM Parser (для использования Simple HTML DOM Parser конечно же надо его скачать...ресурс) // Добавлять сообщения обо всех ошибках, кроме E_WARNING error_reporting(E_ALL & ~E_WARNING); include './domParser/simple_html_dom.php'; class DomParser { public $url = ''; public $imgHost = ''; public $returnVal = 0; public function __construct($urlParse, $imgHostUrl) { $this->url = $urlParse; $this->imgHost = $imgHostUrl; } public function getImages($_data) { $i = 1; $data = $_data ? $_data : file_get_html($this->url); if ($data->innertext != '') { foreach ($data->find('div.catalog__displayedItem') as $a) { foreach ($a->find('.catalog__displayedItem__columnFoto img') as $img) { echo ''; $imgExt = explode('.', $img->src); // Это для добавления картинки себе в папку // Закоментировал в фиддле if ($image = file_get_contents($this->imgHost . $img->src)) { //file_put_contents('./images/' . $i . '.' . end($imgExt), $image); } } $i++; } echo '

'; $this->getNextPage($data, 'getImages'); $data->clear(); unset($data); } } public function getNextPage($data, $repeatFunctionName) { // сделал пока чтобы много циклов не делал не нагружал if ($this->returnVal >= 2) return; if ($data->innertext != '') { $this->returnVal++; foreach ($data->find('.catalogItemList__paginator a') as $a) { $str = iconv("windows-1251", "UTF-8", $a->title); if (mb_strpos(strtolower($str), 'ледующие', 0, 'UTF-8') !== false) { $page = explode('?', $a->href); $data_inner_link = file_get_html($this->url . '?' . end($page)); $this->$repeatFunctionName($data_inner_link); break; } } } } } $url = 'http://www.onlinetrade.ru/catalogue/smartfoni-c13/'; $imgHost = 'http://www.onlinetrade.ru'; $parser = new DomParser($url, $imgHost); $parser->getImages(null); /* $url = 'http://www.onlinetrade.ru/catalogue/smartfoni-c13/'; $imgHost = 'http://www.onlinetrade.ru'; $data = file_get_html($url); $i = 1; function getImages($data) { global $imgHost; global $i; if ($data->innertext!='') { foreach($data->find('div.catalog__displayedItem') as $a) { foreach ($a->find('.catalog__displayedItem__columnFoto img') as $img) { echo ''; $imgExt = explode('.', $img->src); // Это для добавления картинки себе в папку // Закоментировал в фиддле if ($image = file_get_contents($imgHost . $img->src)) { file_put_contents('./images/' . $i . '.' . end($imgExt), $image); } } $i++; } echo '

'; getNextPage($data); $data->clear(); unset($data); } } $return = 0; function getNextPage($data) { global $url; global $return; // сделал пока чтобы много циклов не делал не нагружал if ($return >= 2) return; if($data->innertext != ''){ $return++; foreach($data->find('.catalogItemList__paginator a') as $a){ $str = iconv("windows-1251", "UTF-8", $a->title); if (mb_strpos(strtolower($str), 'ледующие', 0, 'UTF-8') !== false) { $page = explode('?', $a->href); $data_inner_link = file_get_html($url . '?' . end($page)); getImages($data_inner_link); break; } } } } //getImages($data); */ Вариант использования класса и вариант обычный через функции (закоментированы ниже) Потрогать можно Здесь На данный момент специально установлено ограничение на парсинг только первых 3-х страниц (по 10 товаров), чтобы не грузить фиддл и закоменчена строка с file_put_contents потому что фиддл не пропускает, что логично))) вот пруф сохранения: И там еще много внизу... Как вариант можно и наверное лучше использовать (касаемо php) cURL cURL - свободная служебная программа командной строки, позволяющая взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL. Этот код просто скорее в целях показать, что всё работает, можно скачать и что у вас, скорее всего, где-то в коде ошибка. Не является, скорее всего, мой ответ ответом, но, возможно, этот код будет чем-то полезен и захотите как-то переделать под нужды. Нежели сохранять mht. Хотя памяти он будет кушать много.

Ответ 2



Для программного создания mht: C# source code for generating MHT files from an URL CDO.Message COM-объект, реализующий IMessage interface Из JavaScript попробуйте вызвать print(document.body.innerHTML); или document.execCommand('SaveAs','true','http://...')

Как реализовать парсер Markdown?

#java #регулярные_выражения #парсер


Смысл задания:
Преобразовать строки, содержащие определенные символы. Использовать регулярные выражения.


Header - Строка, которая начинается с #, ##, ### и т.д. является заголовком. Данные
строки должны оборачиваться тегами 

,

,

и т.д. Простая строка должна оборачиваться тегом

; Если в строке встречается * ... * то тогда обернуть в тег и т.д. Пример: Header line Simple * line * with strong Line with link [Link to google](h ttps://www.google.com) in center... Результат преобразования: < html> < body>

Header line

Simple < strong>line< /strong> with strong

Line with link Link to google in center


Ответы

Ответ 1



Воспользуйтесь библиотеками - pegdown либо txtmark. Это не насколько тривиальная задача, что бы отказываться от готовых библиотек.

Jsoup. Парсинг элемента класс которого начинается на

#java #html #jsoup #парсер


Есть элементы подобные этому:




Бывает либо trRandom, либо trRandomChild, а в остальных значениях меняются только
лишь цифры. 
Как выбрать элемент класс которого начинается на trRandom средствами библиотеки Jsoup?
Можно конечно написать костыли, но не хотелось бы, если есть более деликатный способ
решения задачи.

Пробовал код ниже, не помогает.

select("[^trRandom]");
select("div[^trRandom]");


Остальные способы кидают исключения. Буду благодарен любой подсказке, спасибо!
    


Ответы

Ответ 1



Ваш код: select("[^trRandom]"); select("div[^trRandom]"); Производит поиск по названию атрибута, который начинается на trRandom, а вам нужно по значению атрибута class по такому принципу: [attr^=valPrefix]. Вот так: select("[class^=trRandom]"); select("div[class^=trRandom]"); Подробней: http://jsoup.org/apidocs/org/jsoup/select/Selector.html

воскресенье, 8 марта 2020 г.

JSOUP заменить тег

#java #android #html #jsoup #парсер


Всем привет. Есть необходимость с помощью jsoup заменить тег  на