Парсинг php в mysql

Saved searches

Use saved searches to filter your results more quickly

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.

Parse MySQL schemas in PHP, fast

License

iamcal/SQLParser

This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Sign In Required

Please sign in to use Codespaces.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching Xcode

If nothing happens, download Xcode and try again.

Launching Visual Studio Code

Your codespace will open once ready.

There was a problem preparing your codespace, please try again.

Latest commit

Git stats

Files

Failed to load latest commit information.

README.md

SQLParser — Parse MySQL schemas in PHP, fast

This library takes MySQL CREATE TABLE statements and returns a data structure representing the table that it defines. MySQL syntax version 5.7 is supported. This library does not try to validate input — the goal is to deconstruct valid CREATE TABLE statements.

You can install this package using composer. To add it to your composer.json :

composer require iamcal/sql-parser 

You can then load it using the composer autoloader:

require_once 'vendor/autoload.php'; use iamcal\SQLParser; $parser = new SQLParser(); 

If you don’t use composer, you can skip the autoloader and include src/SQLParser.php directly.

To extract the tables defined in SQL:

$parser = new SQLParser(); $parser->parse($sql); print_r($parser->tables); 

The tables property is an array of tables, each of which is a nested array structure defining the table’s structure:

CREATE TABLE `achievements_counts` ( `achievement_id` int(10) unsigned NOT NULL, `num_players` int(10) unsigned NOT NULL, `date_updated` int(10) unsigned NOT NULL, PRIMARY KEY (`achievement_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; [ 'achievements_counts' => [ 'name' => 'achievements_counts', 'fields' => [ [ 'name' => 'achievement_id', 'type' => 'INT', 'length' => '10', 'unsigned' => true, 'null' => false, ], [ 'name' => 'num_players', 'type' => 'INT', 'length' => '10', 'unsigned' => true, 'null' => false, ], [ 'name' => 'date_updated', 'type' => 'INT', 'length' => '10', 'unsigned' => true, 'null' => false, ], ], 'indexes' => [ [ 'type' => 'PRIMARY', 'cols' => [ [ 'name' => 'achievement_id', ], ], ], ], 'props' => [ 'ENGINE' => 'InnoDB', 'CHARSET' => 'utf8', ], ], ] 

You can also use the lexer directly to work with other piece of SQL:

$parser = new SQLParser(); $parser->lex($sql); print($parser->tokens); 

The tokens property contains an array of tokens. SQL keywords are returned as uppercase, with multi-word terms (e.g. DEFAULT CHARACTER SET ) as a single token. Strings and escaped identifiers are not further processed; they are returned exactly as expressed in the input SQL.

By default, the tokenizer will ignore unterminated comments and strings, and stop parsing at that point, producing no further tokens. You can set $parser->throw_on_bad_syntax = true; to throw an exception of type iamcal\SQLParserSyntaxException instead.

My test target is an 88K SQL file containing 114 tables from Glitch’s main database.

The first version, using php-sql-parser, took over 60 seconds just to lex the input. This was obviously not a great option.

The current implementation uses a hand-written lexer which takes around 140ms to lex the same input and imposes less odd restrictions. This seems to be the way to go.

This library was created to parse multiple CREATE TABLE schemas and compare them, so figure out what needs to be done to migrate one to the other.

This is based on the system used at b3ta, Flickr and then Tiny Speck to check the differences between production and development databases and between shard instances. The original system just showed a diff (see SchemaDiff), but that was a bit of a pain.

MySQL table definitions have a lot of options, so some things just aren’t supported. They include:

  • UNION table properties
  • TABLESPACE table properties
  • table partitions
  • FLOAT[(bits)] fields
  • Deprecated YEAR(2|4) fields
  • ASCII attribute as a shorthand for CHARACTER SET latin1
  • UNICODE attribute as a shorthand for CHARACTER SET ucs2
  • NATIONAL modified for CHAR and VARCHAR fields

If you need support for one of these features, open an issue or (better) send a pull request with tests.

The specs for each of the four field groupings can be found here:

If you’re using PHP, then Modyllic is a great SQL parser and set of schema management tools.

If you’re using Hack, then Hack SQL Fake allows you to parse SQL and create a fake MySQL server for testing, with many (but not all!) features of MySQL.

Источник

Парсер на PHP с записью контента в БД

Нескольким читателям моего блога было интересно узнать «как объединить крон, базу данных и php парсер». Я постарался написать максимально простой и лаконичный скрипт, чтобы любой новичок смог в нём разобраться. Он состоит всего из одного файла index.php и 50 строк кода.

Я использовал 2 библиотеки:

  • RedBean PHP, которая упрощает работу с БД и защищает от SQL инъекций ->читать подробнее
  • phpQuery — порт jQuery на PHP, который позволяет добираться до нужных блоков в дебрях документа

Парсить в учебных целях мы будем один сайт о моде и красоте. Остановимся мы только на парсинге 10 статей, чтобы понять суть.

А вот и сам скрипт — файл index.php

require 'db.php'; // подключаем библиотеку ReadbeenPHP и соединяемся с базой данных require('/phpQuery/phpQuery.php'); // подключаем phpQuery define('HOST','http://tbeauty.ru'); // сюда мы вписываем адрес сайта-донора, который необходимо спарсить R::wipe('post'); // удаляем все записи из таблицы post R::wipe('postprev'); // удаляем все записи из таблицы postprev $data_site = file_get_contents(HOST); // получаем страницу сайта-донора $document = phpQuery::newDocument($data_site); $content_prev = $document->find('.news .post'); // перебираем в цикле все посты foreach ($content_prev as $el) < // Парсим превьюшки статей $pq = pq($el); // pq это аналог $ в jQuery $h2 = $pq->find('.post-title h2 a')->attr('title'); // парсим заголовок статьи $link = $pq->find('.post-title h2 a')->attr('href'); // парсим ссылку на статью $text = $pq->find('.post-content p'); // парсим текст в превью статьи $img = $pq->find('.wp-post-image')->attr('src'); // парсим ссылку на изображение в превью статьи // Записываем информацию о превьюшках в базу данных $post_prev = R::dispense('postprev'); if(!empty($h2)) $post_prev->h2 = strip_tags($h2); // strip_tags удаляет HTML тэги из строки if(!empty($link)) $post_prev->link = HOST.$link; if(!empty($text)) $post_prev->text = strip_tags($text); if(!empty($img)) $post_prev->img = HOST.$img; R::store($post_prev); // пробегаемся по всем ссылкам на посты и парсим контент из открытых статей if(!empty($link)) $data_link = file_get_contents(HOST.$link); $document_с = phpQuery::newDocument($data_link); $content = $document_с->find('.broden-ajax-content'); foreach ($content as $element) < $pq2 = pq($element); $h1 = $pq2->find('.post-title h1'); // парсим главный заголовок статьи $text_all = $pq2->find('.article__content .txt'); // парсим контент часть статьи > // Записываем информацию о статьях в базу данных $post = R::dispense('post'); if(!empty($h1)) $post->h1 = strip_tags($h1); if(!empty($text_all)) $post->text = strip_tags($text_all); R::store($post); >

Соединение с БД — файл db.php

require ‘libs/rb.php’; R::setup( ‘mysql:host=127.0.0.1;dbname=parserlinio’,’root’, » ); if ( !R::testconnection() )

Если мы запустим парсер, то в базе данных автоматически появятся 2 таблички. В таблице postprev запишется информация о превью статей (картинка, заголовок, небольшой текст и ссылка на сам пост). В таблицу post запишется уже полная информация о статьях.

Вот такая красота в итоге получается.

Таблица postprev

Таблица postprev

Таблица post

Таблица post красная пунктирная линия

Как работает парсер?

  1. Подключаемся к нашей базе данных (файл db.php)
  2. Подключаем библиотеки
  3. Создаем константу, в которой хранится адрес сайта-донора
  4. Очищаем таблицы post и postprev в БД. Это нужно для того, чтобы при повторном запуске парсера, данные в таблицах не дублировались. Момент очень спорный. Возможно, можно было сделать проверку на совпадение с данными в БД и уже потом производить запись или назначать статусы (0 – не парсили, 1 — парсили). Если есть мысли, то пишите в комментариях
  5. Функцией file_get_contents получаем содержимое страницы
  6. Смотрим, как у сайта-донора устроена разметка постовhtml разметка
  7. Перебираем в цикле foreach все посты
  8. Проверяем разметку превью постов и смотрим, в каких тэгах находятся необходимые данные (заголовок, картинка и т.д.)
  9. Информацию о превью, которую мы спарсили записываем в БД. Делается это методом dispense библиотеки RedbeenPHP, который принимает всего 1 аргумент – название таблицы. Причем, если такой таблицы в БД нет, то он сам её корректно создаст
  10. В пункте 8 мы спарсили ссылки на посты. Теперь можно перебрать их в цикле, чтобы спарсить текст внутри статей и заголовоки
  11. По аналогии с пунктом 9 записываем информацию о статьях в БД
  12. Теперь вам остается лишь самостоятельно вывести информацию из БД на свой сайт
  13. Также можно настроить CRON на своем сервере, чтобы файл index.php автоматически запускался, например, раз в неделю. Делается это в разделе планировщик задач. Также можно попросить помощи у техподдержки хостинга.

красная пунктирная линия

P.S. Данный парсер очень простой и его функционал можно расширять до бесконечности. Тестировался парсер на OpenServer. Версия PHP 5.6. На момент написания статьи всё работало. Если у вас не работает, то возможно у сайта-донора поменялся дизайн и соответственно вёрстка.

Скачать php парсер + дамп базы

Купить/заказать парсер под свои нужны

Источник

Парсинг CSV файла в MySQL базу с помощью PHP (mysqli). Как задать кодировку и условие выборки элементов перед внесением в БД?

Вводные данные. Итак, в определённую папку на хостинге (обычный shared, не VDS) каждый день из 1С: Альфа-Авто (спец. редакция 1С: Предприятие 8.3 для СТО и прочих авто-организаций) выгружается файл в формате CSV следующего содержания:

"Параметр 1","Параметр 2","Параметр 3","Параметр 4","Параметр 5" "Параметр N","Параметр N","Параметр N","Параметр N","Параметр N" . 

Это база запчастей/деталей в наличии (кол-во > 0). Для парсинга файла и преобразования его значений в массив (для последующего использования), я использую вот такой код:

$file = file_get_contents('/home/user/site.ru/public_html/upload/catalog.csv'); $lines = explode(PHP_EOL, $file); $array = array(); foreach ($lines as $line)

Вот тут появляется первый затык. По старой доброй традиции, 1С всё фигачит в кодировке CP1251 (или KOI8-R), и, вместо кириллицы, одни крякозябры в массиве $array . Так же, при последующих попытках сделать INSERT этих значений в БД, их не понимает mysqli и выдаёт ошибки.

Можно ли как-то пересохранять этот CSV файл или преобразовывать его «на лету» в формат UTF-8 (без BOM, например) перед парсингом? Да, есть Notepad++, но делать это каждый день вручную — просто физически нет человекоресурсов, да и не по фей-шую это, всё же.

Для внесения значений в БД, пишу вот так:

// Init MySQLi. $mysqli = mysqli_init(); // Connect to DB. if (!$mysqli->real_connect('localhost', $login, $password, $table)) die('Ошибка подключения (' . mysqli_connect_errno() . ') ' . mysqli_connect_error()); // Loop INSERT. foreach ($array as $row) < if (!$mysqli->query("INSERT INTO catalog(id, name, brand, stock, price) VALUES ('$row[0]', '$row[1]', '$row[2]', '$row[3]', '$row[4]')")) echo "Ошибка (" . $mysqli->errno . ") " . $mysqli->error; > // Close MySQLi connection. $mysqli->close();

(Ячейка таблицы ID имеет значения UNIQUE и PRIMARY)

В удачные дни этот файл весит около 500 Кб (~4000 наименований номенклатуры). Это второй затык, ибо грузить каждый раз заново такое кол-во, пусть даже и глубокой ночью по Cron, в MySQL — не есть хорошо (ИМХО). Следовательно, вопрос: как лучше сравнивать каждую строчку (элемент массива) из CSV файла с существующими строками в БД и вносить только те значения, которые были изменены (главный, логично, файл CSV)?

При этом, нужно как-то указать опции:
1. Если такой ID есть в БД, но его нет в файле CSV, то делать DELETE элемента;
2. Если такого ID нет в БД, но есть в файле CSV, то делать INSERT, иначе — пропустить элемент;
3. Если такой ID есть и в БД и в файле CSV, то делать UPDATE, иначе — пропустить элемент.

Надеюсь на вашу помощь. Заранее, спасибо!

Источник

Читайте также:  Python get open windows
Оцените статью