Я извлекаю спецификации VIN из API Национальной администрации безопасности дорожного движения для примерно 25 000 000 номеров VIN. Это большой объем данных, и, поскольку я никоим образом не преобразую данные, curl
кажется более эффективным и легким способом выполнения задачи, чем Python (учитывая, что GIL Python делает параллельную обработку немного трудной) ,
В приведенном ниже коде vins.csv
– это файл, содержащий большую выборку из 25 миллионов VIN, разбитых на куски по 100 VIN. Они передаются в GNU Parallel, который использует 4 ядра. В конце все сбрасывается в nhtsa_vin_data.csv
.
$ cat vins.csv | parallel -j10% curl -s --data "format=csv" \ --data "data={1}" https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVINValuesBatch/ \ >> /nas/BIGDATA/kemri/nhtsa_vin_data.csv
Вначале этот процесс записывал около 3000 VIN-ов в минуту и постепенно прогрессировал со временем (в настоящее время около 1200 в минуту).
nhtsa_vin_data.csv
? >>
операции? Первое решение для @slm – используйте параметры параллельного файла tmp, чтобы записать каждый вывод curl в свой собственный файл .par, объедините в конце:
$ cat vins.csv | parallel \ --tmpdir /home/kemri/vin_scraper/temp_files \ --files \ -j10% curl -s \ --data "format=csv" \ --data "data={1}" https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVINValuesBatch/ > /dev/null cat <(head -1 $(ls *.par|head -1)) all_data.csv
Второе решение для @oletange – использовать –line-buffer для буферизации вывода в память вместо диска:
$ cat test_new_mthd_vins.csv | parallel \ --line-buffer \ -j10% curl -s \ --data "format=csv" \ --data "data={1}" https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVINValuesBatch/ \ >> /home/kemri/vin_scraper/temp_files/nhtsa_vin_data.csv
Я нахожу оба решения, предложенные здесь, очень полезными и интересными и определенно буду использовать обе версии больше в будущем (как для сравнения производительности, так и для дополнительной работы API). Надеюсь, я смогу запустить несколько тестов, чтобы увидеть, какой из них лучше подходит для моего варианта использования.
Кроме того, было бы целесообразно запустить какой-нибудь тест производительности, такой как @oletange и @slm, так как вероятность того, что NHTSA станет узким местом, не является ничтожной.
Я подозреваю, что >>
вызывает у вас конфликт по файлу nhtsa_vin_data.csv
среди команд curl
которые parallel
распадается для сбора данных API.
Я бы настроил ваше приложение так:
$ cat p.bash #!/bin/bash cat vins.csv | parallel --will-cite -j10% --progress --tmpdir . --files \ curl -s --data "format=csv" \ --data "data={1}" https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVINValuesBatch/
Это даст вашим командам curl
собственный изолированный файл для записи своих данных.
Я взял эти 3 VIN, 1HGCR3F95FA017875;1HGCR3F83HA034135;3FA6P0T93GR335818;
, что вы предоставили мне и поместили их в файл с именем vins.csv
. Затем я скопировал их несколько раз, чтобы этот файл имел следующие характеристики:
VIN на строку
$ tail -1 vins.csv | grep -o ';' | wc -l 26
Количество строк
$ wc -l vins.csv 15 vins.csv
Затем я запустил свой скрипт, используя эти данные:
$ ./p.bash Computers / CPU cores / Max jobs to run 1:local / 1 / 1 Computer:jobs running/jobs completed/%of started jobs/Average seconds to complete local:1/0/100%/0.0s ./pard9QD3.par local:1/1/100%/10.0s ./paruwK9L.par local:1/2/100%/8.5s ./parT6rCS.par local:1/3/100%/7.3s ./pardzT2g.par local:1/4/100%/6.8s ./parDAsaO.par local:1/5/100%/6.8s ./par9X2Na.par local:1/6/100%/6.7s ./par6aRla.par local:1/7/100%/6.7s ./parNR_r4.par local:1/8/100%/6.4s ./parVoa9k.par local:1/9/100%/6.1s ./parXJQTc.par local:1/10/100%/6.0s ./parDZZrp.par local:1/11/100%/6.0s ./part0tlA.par local:1/12/100%/5.9s ./parydQlI.par local:1/13/100%/5.8s ./par4hkSL.par local:1/14/100%/5.8s ./parbGwA2.par local:0/15/100%/5.4s
Когда все вышеперечисленное выполнено, вы можете объединить все файлы вместе, чтобы получить один файл .csv
.
$ cat *.par > all_data.csv
Будьте внимательны при этом, поскольку каждый файл имеет собственную строку заголовка для данных CSV, которые содержатся внутри. Чтобы справиться с удалением заголовков из файлов результатов:
$ cat <(head -1 $(ls *.par|head -1)) <(tail -q -n +2 *.par) > all_data.csv
В моем тестировании похоже, что веб-сайт DOT регулирует запросы, поскольку они продолжают получать доступ к своему API. Вышеуказанное время, которое я видел в своих экспериментах, хотя и было небольшим, уменьшалось по мере того, как каждый запрос отправлялся на сайт API.
Моя производительность на ноутбуке была следующей:
$ seq 5 | parallel --will-cite --line-buffer 'yes {} | head -c 1G' | pv >> /dev/null 5GiB 0:00:51 [99.4MiB/s] [ <=> ]
ПРИМЕЧАНИЕ: вышеприведенное заимствовано из ответа Оле Танге и изменено. Он записывает 5 ГБ данных через parallel
и передает его в pv >> /dev/null
. Используется pv
поэтому мы можем отслеживать пропускную способность по каналу и получать измерения типа МБ / с.
Мой ноутбук смог набрать ~ 100 МБ / с пропускной способности.
API
Для «Декодировать VIN (плоский формат) в пакете» есть ли пример выполнения этого запроса по URL, аналогично другим действиям?
Для этого конкретного API вам просто нужно поместить в поле набор VIN, разделенных «;». Вы также можете указать модельный год до «;», разделенного «,». Существует верхний предел количества VIN-адресов, которые вы можете использовать с помощью этой услуги.
Пример в поле – образец: 5UXWX7C5 * BA, 2011; 5YJSA3DS * EF
Источник: https://vpic.nhtsa.dot.gov/MfrPortal/home/faq искал “рейтинг”
Выше упоминается, что есть верхний предел при использовании API:
Существует верхний предел количества VIN-адресов, которые вы можете использовать с помощью этой услуги.
Производительность обычно ограничена одним из них:
sudo iftop
чтобы увидеть, используется ли ваше сетевое соединение на 100%. iostat -dkx 1
чтобы проверить, используется ли ввод-вывод любого из ваших дисков на 100%. top
если ваши процессоры загружены на 100%. Нажмите 1
чтобы увидеть отдельные streamи процессора. Если один из них на 100%, то у вас есть однопоточная программа, которая ограничена этим. GNU Parallel хорош для параллельного выполнения заданий, чтобы использовать больше пропускной способности, дискового ввода-вывода и процессора.
Но это также имеет свои ограничения.
GNU Parallel обычно кеширует вывод в /tmp
. Это означает, что ваш дисковый ввод / вывод в /tmp
может быть узким местом.
К счастью, имея дело с CSV, вы редко заботитесь о порядке строк: хорошо, если строки смешиваются, если это целые строки.
Если вы используете --line-buffer
от версии> 20170822, то GNU Parallel не буферизует вывод на диск – он только буферизует одну полную строку в памяти. Требуется немного больше ресурсов процессора, поэтому проверьте, использует ли parallel
процессор на 100%. Если он использует меньше, то вы не достигли этого узкого места.
$ cat vins.csv | parallel --line-buffer curl -s --data "format=csv" \ --data "data={1}" https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVINValuesBatch/ \ >> /nas/BIGDATA/kemri/nhtsa_vin_data.csv
Вы можете увидеть, есть ли у вас местное узкое место:
$ seq 1000 | parallel --line-buffer 'yes {} | head -c 1G' | pv >> /nas/BIGDATA/test
На моем паршивом ноутбуке я получаю около 100 МБ / с. Так что мой паршивый ноутбук сможет работать с 1 Гбит / с с dot.gov.