diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a79632d..bffa656 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
+ python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
steps:
- name: Checkout repository
diff --git a/HISTORY.md b/HISTORY.md
index a34d285..88404b3 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,12 +1,33 @@
Release History
===============
-dev
----
+0.1.5 (2023-11-01)
+------------------
-* Initial release
+- Python 3.12 support.
-1.0.0 (planned)
----------------
+0.1.4 (2023-10-11)
+------------------
-- First planned release
\ No newline at end of file
+- Add README documentation for various engines.
+
+0.1.3 (2023-10-06)
+------------------
+
+- Replace deprecated serpapi_pagination.next_link with 'next'.
+- Improve documentation: how to use the client directly for pagination searches.
+
+0.1.2 (2023-10-03)
+------------------
+
+- Update project status to Production/Stable.
+
+0.1.1 (2023-10-03)
+------------------
+
+- Update documentation link to point to Read the Docs.
+
+0.1.0 (2023-10-03)
+------------------
+
+- First release on PyPI.
diff --git a/Pipfile b/Pipfile
index a9520dd..a5c014f 100644
--- a/Pipfile
+++ b/Pipfile
@@ -5,6 +5,7 @@ name = "pypi"
[packages]
serpapi = {editable = true, path = "."}
+pytest = "*"
[dev-packages]
alabaster = "*"
diff --git a/Pipfile.lock b/Pipfile.lock
index e0db2c3..b648257 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "af8f25e5f407e8511d4991ef1bea16153306344c1b3f417c2b005dce48c36352"
+ "sha256": "89b1875c3363b3d6f5d499c666e43404b5260933fb44f45d06e40277eceb34cb"
},
"pipfile-spec": 6,
"requires": {},
@@ -16,92 +16,107 @@
"default": {
"certifi": {
"hashes": [
- "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082",
- "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"
+ "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1",
+ "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"
],
"markers": "python_version >= '3.6'",
- "version": "==2023.7.22"
+ "version": "==2023.11.17"
},
"charset-normalizer": {
"hashes": [
- "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96",
- "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c",
- "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710",
- "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706",
- "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020",
- "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252",
- "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad",
- "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329",
- "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a",
- "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f",
- "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6",
- "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4",
- "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a",
- "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46",
- "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2",
- "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23",
- "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace",
- "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd",
- "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982",
- "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10",
- "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2",
- "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea",
- "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09",
- "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5",
- "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149",
- "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489",
- "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9",
- "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80",
- "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592",
- "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3",
- "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6",
- "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed",
- "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c",
- "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200",
- "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a",
- "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e",
- "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d",
- "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6",
- "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623",
- "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669",
- "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3",
- "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa",
- "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9",
- "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2",
- "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f",
- "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1",
- "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4",
- "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a",
- "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8",
- "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3",
- "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029",
- "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f",
- "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959",
- "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22",
- "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7",
- "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952",
- "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346",
- "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e",
- "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d",
- "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299",
- "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd",
- "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a",
- "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3",
- "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037",
- "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94",
- "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c",
- "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858",
- "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a",
- "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449",
- "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c",
- "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918",
- "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1",
- "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c",
- "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac",
- "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"
+ "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027",
+ "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087",
+ "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786",
+ "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8",
+ "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09",
+ "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185",
+ "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574",
+ "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e",
+ "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519",
+ "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898",
+ "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269",
+ "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3",
+ "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f",
+ "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6",
+ "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8",
+ "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a",
+ "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73",
+ "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc",
+ "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714",
+ "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2",
+ "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc",
+ "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce",
+ "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d",
+ "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e",
+ "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6",
+ "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269",
+ "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96",
+ "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d",
+ "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a",
+ "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4",
+ "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77",
+ "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d",
+ "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0",
+ "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed",
+ "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068",
+ "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac",
+ "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25",
+ "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8",
+ "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab",
+ "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26",
+ "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2",
+ "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db",
+ "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f",
+ "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5",
+ "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99",
+ "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c",
+ "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d",
+ "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811",
+ "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa",
+ "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a",
+ "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03",
+ "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b",
+ "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04",
+ "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c",
+ "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001",
+ "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458",
+ "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389",
+ "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99",
+ "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985",
+ "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537",
+ "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238",
+ "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f",
+ "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d",
+ "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796",
+ "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a",
+ "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143",
+ "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8",
+ "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c",
+ "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5",
+ "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5",
+ "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711",
+ "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4",
+ "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6",
+ "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c",
+ "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7",
+ "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4",
+ "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b",
+ "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae",
+ "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12",
+ "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c",
+ "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae",
+ "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8",
+ "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887",
+ "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b",
+ "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4",
+ "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f",
+ "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5",
+ "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33",
+ "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519",
+ "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"
],
"markers": "python_full_version >= '3.7.0'",
- "version": "==3.2.0"
+ "version": "==3.3.2"
},
"idna": {
"hashes": [
@@ -111,13 +126,38 @@
"markers": "python_version >= '3.5'",
"version": "==3.4"
},
- "pygments": {
+ "iniconfig": {
"hashes": [
- "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c",
- "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"
+ "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3",
+ "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"
],
"markers": "python_version >= '3.7'",
- "version": "==2.15.1"
+ "version": "==2.0.0"
+ },
+ "packaging": {
+ "hashes": [
+ "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5",
+ "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==23.2"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12",
+ "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==1.3.0"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac",
+ "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"
+ ],
+ "index": "pypi",
+ "markers": "python_version >= '3.7'",
+ "version": "==7.4.3"
},
"requests": {
"hashes": [
@@ -129,15 +169,16 @@
},
"serpapi": {
"editable": true,
+ "markers": "python_full_version >= '3.6.0'",
"path": "."
},
"urllib3": {
"hashes": [
- "sha256:8d22f86aae8ef5e410d4f539fde9ce6b2113a001bb4d189e0aed70642d602b11",
- "sha256:de7df1803967d2c2a98e4b11bb7d6bd9210474c46e8a0401514e3a42a75ebde4"
+ "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3",
+ "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"
],
- "markers": "python_version >= '3.7'",
- "version": "==2.0.4"
+ "markers": "python_version >= '3.8'",
+ "version": "==2.1.0"
}
},
"develop": {
@@ -147,140 +188,153 @@
"sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"
],
"index": "pypi",
+ "markers": "python_version >= '3.6'",
"version": "==0.7.13"
},
"babel": {
"hashes": [
- "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610",
- "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"
+ "sha256:33e0952d7dd6374af8dbf6768cc4ddf3ccfefc244f9986d4074704f2fbd18900",
+ "sha256:7077a4984b02b6727ac10f1f7294484f737443d7e2e66c5e4380e41a3ae0b4ed"
],
"markers": "python_version >= '3.7'",
- "version": "==2.12.1"
+ "version": "==2.13.1"
},
"black": {
"hashes": [
- "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3",
- "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb",
- "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087",
- "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320",
- "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6",
- "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3",
- "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc",
- "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f",
- "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587",
- "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91",
- "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a",
- "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad",
- "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926",
- "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9",
- "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be",
- "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd",
- "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96",
- "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491",
- "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2",
- "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a",
- "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f",
- "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"
+ "sha256:250d7e60f323fcfc8ea6c800d5eba12f7967400eb6c2d21ae85ad31c204fb1f4",
+ "sha256:2a9acad1451632021ee0d146c8765782a0c3846e0e0ea46659d7c4f89d9b212b",
+ "sha256:412f56bab20ac85927f3a959230331de5614aecda1ede14b373083f62ec24e6f",
+ "sha256:421f3e44aa67138ab1b9bfbc22ee3780b22fa5b291e4db8ab7eee95200726b07",
+ "sha256:45aa1d4675964946e53ab81aeec7a37613c1cb71647b5394779e6efb79d6d187",
+ "sha256:4c44b7211a3a0570cc097e81135faa5f261264f4dfaa22bd5ee2875a4e773bd6",
+ "sha256:4c68855825ff432d197229846f971bc4d6666ce90492e5b02013bcaca4d9ab05",
+ "sha256:5133f5507007ba08d8b7b263c7aa0f931af5ba88a29beacc4b2dc23fcefe9c06",
+ "sha256:54caaa703227c6e0c87b76326d0862184729a69b73d3b7305b6288e1d830067e",
+ "sha256:58e5f4d08a205b11800332920e285bd25e1a75c54953e05502052738fe16b3b5",
+ "sha256:698c1e0d5c43354ec5d6f4d914d0d553a9ada56c85415700b81dc90125aac244",
+ "sha256:6c1cac07e64433f646a9a838cdc00c9768b3c362805afc3fce341af0e6a9ae9f",
+ "sha256:760415ccc20f9e8747084169110ef75d545f3b0932ee21368f63ac0fee86b221",
+ "sha256:7f622b6822f02bfaf2a5cd31fdb7cd86fcf33dab6ced5185c35f5db98260b055",
+ "sha256:cf57719e581cfd48c4efe28543fea3d139c6b6f1238b3f0102a9c73992cbb479",
+ "sha256:d136ef5b418c81660ad847efe0e55c58c8208b77a57a28a503a5f345ccf01394",
+ "sha256:dbea0bb8575c6b6303cc65017b46351dc5953eea5c0a59d7b7e3a2d2f433a911",
+ "sha256:fc7f6a44d52747e65a02558e1d807c82df1d66ffa80a601862040a43ec2e3142"
],
"index": "pypi",
- "version": "==23.7.0"
+ "markers": "python_version >= '3.8'",
+ "version": "==23.11.0"
},
"certifi": {
"hashes": [
- "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082",
- "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"
+ "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1",
+ "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"
],
"markers": "python_version >= '3.6'",
- "version": "==2023.7.22"
+ "version": "==2023.11.17"
},
"charset-normalizer": {
"hashes": [
- "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96",
- "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c",
- "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710",
- "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706",
- "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020",
- "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252",
- "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad",
- "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329",
- "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a",
- "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f",
- "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6",
- "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4",
- "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a",
- "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46",
- "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2",
- "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23",
- "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace",
- "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd",
- "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982",
- "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10",
- "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2",
- "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea",
- "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09",
- "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5",
- "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149",
- "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489",
- "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9",
- "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80",
- "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592",
- "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3",
- "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6",
- "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed",
- "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c",
- "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200",
- "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a",
- "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e",
- "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d",
- "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6",
- "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623",
- "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669",
- "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3",
- "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa",
- "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9",
- "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2",
- "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f",
- "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1",
- "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4",
- "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a",
- "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8",
- "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3",
- "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029",
- "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f",
- "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959",
- "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22",
- "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7",
- "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952",
- "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346",
- "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e",
- "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d",
- "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299",
- "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd",
- "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a",
- "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3",
- "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037",
- "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94",
- "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c",
- "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858",
- "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a",
- "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449",
- "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c",
- "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918",
- "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1",
- "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c",
- "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac",
- "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"
+ "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027",
+ "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087",
+ "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786",
+ "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8",
+ "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09",
+ "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185",
+ "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574",
+ "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e",
+ "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519",
+ "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898",
+ "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269",
+ "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3",
+ "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f",
+ "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6",
+ "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8",
+ "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a",
+ "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73",
+ "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc",
+ "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714",
+ "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2",
+ "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc",
+ "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce",
+ "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d",
+ "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e",
+ "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6",
+ "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269",
+ "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96",
+ "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d",
+ "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a",
+ "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4",
+ "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77",
+ "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d",
+ "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0",
+ "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed",
+ "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068",
+ "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac",
+ "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25",
+ "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8",
+ "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab",
+ "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26",
+ "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2",
+ "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db",
+ "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f",
+ "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5",
+ "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99",
+ "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c",
+ "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d",
+ "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811",
+ "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa",
+ "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a",
+ "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03",
+ "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b",
+ "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04",
+ "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c",
+ "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001",
+ "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458",
+ "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389",
+ "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99",
+ "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985",
+ "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537",
+ "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238",
+ "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f",
+ "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d",
+ "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796",
+ "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a",
+ "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143",
+ "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8",
+ "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c",
+ "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5",
+ "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5",
+ "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711",
+ "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4",
+ "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6",
+ "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c",
+ "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7",
+ "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4",
+ "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b",
+ "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae",
+ "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12",
+ "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c",
+ "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae",
+ "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8",
+ "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887",
+ "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b",
+ "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4",
+ "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f",
+ "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5",
+ "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33",
+ "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519",
+ "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"
],
"markers": "python_full_version >= '3.7.0'",
- "version": "==3.2.0"
+ "version": "==3.3.2"
},
"click": {
"hashes": [
- "sha256:48ee849951919527a045bfe3bf7baa8a959c423134e1a5b98c05c20ba75a1cbd",
- "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5"
+ "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28",
+ "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"
],
"markers": "python_version >= '3.7'",
- "version": "==8.1.6"
+ "version": "==8.1.7"
},
"docutils": {
"hashes": [
@@ -328,8 +382,11 @@
"sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e",
"sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431",
"sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686",
+ "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c",
"sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559",
"sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc",
+ "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb",
+ "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939",
"sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c",
"sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0",
"sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4",
@@ -337,6 +394,7 @@
"sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575",
"sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba",
"sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d",
+ "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd",
"sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3",
"sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00",
"sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155",
@@ -345,6 +403,7 @@
"sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f",
"sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8",
"sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b",
+ "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007",
"sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24",
"sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea",
"sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198",
@@ -352,9 +411,12 @@
"sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee",
"sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be",
"sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2",
+ "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1",
"sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707",
"sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6",
+ "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c",
"sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58",
+ "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823",
"sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779",
"sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636",
"sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c",
@@ -373,7 +435,9 @@
"sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9",
"sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57",
"sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc",
- "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"
+ "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc",
+ "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2",
+ "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"
],
"markers": "python_version >= '3.7'",
"version": "==2.1.3"
@@ -388,51 +452,52 @@
},
"packaging": {
"hashes": [
- "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61",
- "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"
+ "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5",
+ "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"
],
"markers": "python_version >= '3.7'",
- "version": "==23.1"
+ "version": "==23.2"
},
"pathspec": {
"hashes": [
- "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687",
- "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"
+ "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20",
+ "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"
],
"markers": "python_version >= '3.7'",
- "version": "==0.11.1"
+ "version": "==0.11.2"
},
"platformdirs": {
"hashes": [
- "sha256:1b42b450ad933e981d56e59f1b97495428c9bd60698baab9f3eb3d00d5822421",
- "sha256:ad8291ae0ae5072f66c16945166cb11c63394c7a3ad1b1bc9828ca3162da8c2f"
+ "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b",
+ "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731"
],
"markers": "python_version >= '3.7'",
- "version": "==3.9.1"
+ "version": "==4.0.0"
},
"pluggy": {
"hashes": [
- "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849",
- "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"
+ "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12",
+ "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"
],
- "markers": "python_version >= '3.7'",
- "version": "==1.2.0"
+ "markers": "python_version >= '3.8'",
+ "version": "==1.3.0"
},
"pygments": {
"hashes": [
- "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c",
- "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"
+ "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c",
+ "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"
],
"markers": "python_version >= '3.7'",
- "version": "==2.15.1"
+ "version": "==2.17.2"
},
"pytest": {
"hashes": [
- "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32",
- "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a"
+ "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac",
+ "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"
],
"index": "pypi",
- "version": "==7.4.0"
+ "markers": "python_version >= '3.7'",
+ "version": "==7.4.3"
},
"requests": {
"hashes": [
@@ -442,6 +507,14 @@
"markers": "python_version >= '3.7'",
"version": "==2.31.0"
},
+ "setuptools": {
+ "hashes": [
+ "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2",
+ "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6"
+ ],
+ "markers": "python_version >= '3.12'",
+ "version": "==69.0.2"
+ },
"snowballstemmer": {
"hashes": [
"sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1",
@@ -451,35 +524,36 @@
},
"sphinx": {
"hashes": [
- "sha256:8f336d0221c3beb23006b3164ed1d46db9cebcce9cb41cdb9c5ecd4bcc509be0",
- "sha256:9bdfb5a2b28351d4fdf40a63cd006dbad727f793b243e669fc950d7116c634af"
+ "sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560",
+ "sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5"
],
"index": "pypi",
- "version": "==7.1.0"
+ "markers": "python_version >= '3.9'",
+ "version": "==7.2.6"
},
"sphinxcontrib-applehelp": {
"hashes": [
- "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228",
- "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e"
+ "sha256:094c4d56209d1734e7d252f6e0b3ccc090bd52ee56807a5d9315b19c122ab15d",
+ "sha256:39fdc8d762d33b01a7d8f026a3b7d71563ea3b72787d5f00ad8465bd9d6dfbfa"
],
- "markers": "python_version >= '3.8'",
- "version": "==1.0.4"
+ "markers": "python_version >= '3.9'",
+ "version": "==1.0.7"
},
"sphinxcontrib-devhelp": {
"hashes": [
- "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e",
- "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"
+ "sha256:63b41e0d38207ca40ebbeabcf4d8e51f76c03e78cd61abe118cf4435c73d4212",
+ "sha256:fe8009aed765188f08fcaadbb3ea0d90ce8ae2d76710b7e29ea7d047177dae2f"
],
- "markers": "python_version >= '3.5'",
- "version": "==1.0.2"
+ "markers": "python_version >= '3.9'",
+ "version": "==1.0.5"
},
"sphinxcontrib-htmlhelp": {
"hashes": [
- "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff",
- "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"
+ "sha256:6c26a118a05b76000738429b724a0568dbde5b72391a688577da08f11891092a",
+ "sha256:8001661c077a73c29beaf4a79968d0726103c5605e27db92b9ebed8bab1359e9"
],
- "markers": "python_version >= '3.8'",
- "version": "==2.0.1"
+ "markers": "python_version >= '3.9'",
+ "version": "==2.0.4"
},
"sphinxcontrib-jsmath": {
"hashes": [
@@ -491,27 +565,27 @@
},
"sphinxcontrib-qthelp": {
"hashes": [
- "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72",
- "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"
+ "sha256:62b9d1a186ab7f5ee3356d906f648cacb7a6bdb94d201ee7adf26db55092982d",
+ "sha256:bf76886ee7470b934e363da7a954ea2825650013d367728588732c7350f49ea4"
],
- "markers": "python_version >= '3.5'",
- "version": "==1.0.3"
+ "markers": "python_version >= '3.9'",
+ "version": "==1.0.6"
},
"sphinxcontrib-serializinghtml": {
"hashes": [
- "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd",
- "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"
+ "sha256:0c64ff898339e1fac29abd2bf5f11078f3ec413cfe9c046d3120d7ca65530b54",
+ "sha256:9b36e503703ff04f20e9675771df105e58aa029cfcbc23b8ed716019b7416ae1"
],
- "markers": "python_version >= '3.5'",
- "version": "==1.1.5"
+ "markers": "python_version >= '3.9'",
+ "version": "==1.1.9"
},
"urllib3": {
"hashes": [
- "sha256:8d22f86aae8ef5e410d4f539fde9ce6b2113a001bb4d189e0aed70642d602b11",
- "sha256:de7df1803967d2c2a98e4b11bb7d6bd9210474c46e8a0401514e3a42a75ebde4"
+ "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3",
+ "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"
],
- "markers": "python_version >= '3.7'",
- "version": "==2.0.4"
+ "markers": "python_version >= '3.8'",
+ "version": "==2.1.0"
}
}
}
diff --git a/README.md b/README.md
index 5d5dde9..668055b 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,17 @@
+
SerpApi Python Library & Package

-
+

+
[](https://github.com/serpapi/serpapi-python/actions/workflows/ci.yml)
-This repository is the home of the *soon–to–be* official Python API wrapper for SerpApi (https://serpapi.com). This `serpapi` module allows you to access search data in your Python application.
-
-SerpApi supports Google, Google Maps, Google Shopping, Bing, Baidu, Yandex, Yahoo, eBay, App Stores, and more. Check out the [documentation](https://serpapi.com/search-api) for a full list.
+This repository is the home of the *soon–to–be* official Python API wrapper for [SerpApi](https://serpapi.com). This `serpapi` module allows you to access search data in your Python application.
-## Current Status
+[SerpApi](https://serpapi.com) supports Google, Google Maps, Google Shopping, Bing, Baidu, Yandex, Yahoo, eBay, App Stores, and more. Check out the [documentation](https://serpapi.com/search-api) for a full list.
-This project is under development, and will be released to the public on PyPi soon.
## Installation
@@ -23,11 +21,11 @@ To install the `serpapi` package, simply run the following command:
$ pip install serpapi
```
-Please note that this package is separate from the *soon–to–be* legacy `serpapi` module, which is currently available on PyPi as `google-search-results`.
+Please note that this package is separate from the legacy `serpapi` module, which is available on PyPi as `google-search-results`. This package is maintained by SerpApi, and is the recommended way to access the SerpApi service from Python.
## Usage
-Let’s start by searching for Coffee on Google:
+Let's start by searching for Coffee on Google:
```pycon
>>> import serpapi
@@ -36,14 +34,14 @@ Let’s start by searching for Coffee on Google:
The `s` variable now contains a `SerpResults` object, which acts just like a standard dictionary, with some convenient functions added on top.
-Let’s print the first result:
+Let's print the first result:
```pycon
>>> s["organic_results"][0]["link"]
'https://en.wikipedia.org/wiki/Coffee'
```
-Let’s print the title of the first result, but in a more Pythonic way:
+Let's print the title of the first result, but in a more Pythonic way:
```pycon
>>> s["organic_results"][0].get("title")
@@ -56,6 +54,292 @@ The [SerpApi.com API Documentation](https://serpapi.com/search-api) contains a l
Documentation is [available on Read the Docs](https://serpapi-python.readthedocs.io/en/latest/).
+## Basic Examples in Python
+
+### Search Bing
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'bing',
+ 'q': 'coffee'
+})
+```
+- API Documentation: [serpapi.com/bing-search-api](https://serpapi.com/bing-search-api)
+
+### Search Baidu
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'baidu',
+ 'q': 'coffee',
+})
+```
+- API Documentation: [serpapi.com/baidu-search-api](https://serpapi.com/baidu-search-api)
+
+### Search Yahoo
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'yahoo',
+ 'p': 'coffee',
+})
+```
+- API Documentation: [serpapi.com/yahoo-search-api](https://serpapi.com/yahoo-search-api)
+
+### Search YouTube
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'youtube',
+ 'search_query': 'coffee',
+})
+```
+- API Documentation: [serpapi.com/youtube-search-api](https://serpapi.com/youtube-search-api)
+
+### Search Walmart
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'walmart',
+ 'query': 'coffee',
+})
+```
+- API Documentation: [serpapi.com/walmart-search-api](https://serpapi.com/walmart-search-api)
+
+### Search eBay
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'ebay',
+ '_nkw': 'coffee',
+})
+```
+- API Documentation: [serpapi.com/ebay-search-api](https://serpapi.com/ebay-search-api)
+
+### Search Naver
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'naver',
+ 'query': 'coffee',
+})
+```
+- API Documentation: [serpapi.com/naver-search-api](https://serpapi.com/naver-search-api)
+
+### Search Home Depot
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'home_depot',
+ 'q': 'table',
+})
+```
+- API Documentation: [serpapi.com/home-depot-search-api](https://serpapi.com/home-depot-search-api)
+
+### Search Apple App Store
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'apple_app_store',
+ 'term': 'coffee',
+})
+```
+- API Documentation: [serpapi.com/apple-app-store](https://serpapi.com/apple-app-store)
+
+### Search DuckDuckGo
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'duckduckgo',
+ 'q': 'coffee',
+})
+```
+- API Documentation: [serpapi.com/duckduckgo-search-api](https://serpapi.com/duckduckgo-search-api)
+
+### Search Google
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'google',
+ 'q': 'coffee'
+})
+```
+- API Documentation: [serpapi.com/search-api](https://serpapi.com/search-api)
+
+### Search Google Scholar
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'google_scholar',
+ 'q': 'coffee',
+})
+```
+- API Documentation: [serpapi.com/google-scholar-api](https://serpapi.com/google-scholar-api)
+
+### Search Google Autocomplete
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'google_autocomplete',
+ 'q': 'coffee',
+})
+```
+- API Documentation: [serpapi.com/google-autocomplete-api](https://serpapi.com/google-autocomplete-api)
+
+### Search Google Product
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'google_product',
+ 'q': 'coffee',
+ 'product_id': '4887235756540435899',
+})
+```
+- API Documentation: [serpapi.com/google-product-api](https://serpapi.com/google-product-api)
+
+### Search Google Reverse Image
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'google_reverse_image',
+ 'image_url': 'https://i.imgur.com/5bGzZi7.jpg',
+ 'max_results': '1',
+})
+```
+- API Documentation: [serpapi.com/google-reverse-image](https://serpapi.com/google-reverse-image)
+
+### Search Google Events
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'google_events',
+ 'q': 'coffee',
+})
+```
+- API Documentation: [serpapi.com/google-events-api](https://serpapi.com/google-events-api)
+
+### Search Google Local Services
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'google_local_services',
+ 'q': 'electrician',
+ 'data_cid': '6745062158417646970',
+})
+```
+- API Documentation: [serpapi.com/google-local-services-api](https://serpapi.com/google-local-services-api)
+
+### Search Google Maps
+```python
+import os
+import serpapi
+
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'google_maps',
+ 'q': 'pizza',
+ 'll': '@40.7455096,-74.0083012,15.1z',
+ 'type': 'search',
+})
+```
+- API Documentation: [serpapi.com/google-maps-api](https://serpapi.com/google-maps-api)
+
+### Search Google Jobs
+```python
+import os
+import serpapi
+
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'google_jobs',
+ 'q': 'coffee',
+})
+```
+- API Documentation: [serpapi.com/google-jobs-api](https://serpapi.com/google-jobs-api)
+
+### Search Google Play
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'google_play',
+ 'q': 'kite',
+ 'store': 'apps',
+ 'max_results': '2',
+})
+```
+- API Documentation: [serpapi.com/google-play-api](https://serpapi.com/google-play-api)
+
+### Search Google Images
+```python
+import os
+import serpapi
+
+client = serpapi.Client(api_key=os.getenv("API_KEY"))
+results = client.search({
+ 'engine': 'google_images',
+ 'tbm': 'isch',
+ 'q': 'coffee',
+})
+```
+- API Documentation: [serpapi.com/images-results](https://serpapi.com/images-results)
+
+
## License
MIT License.
diff --git a/README.md.erb b/README.md.erb
new file mode 100644
index 0000000..0bed824
--- /dev/null
+++ b/README.md.erb
@@ -0,0 +1,165 @@
+<%-
+def snippet(format, path)
+ lines = File.new(path).readlines
+ stop = lines.size - 1
+ slice = lines[7..stop]
+ slice.reject! { |l| l.match?(/(^# |assert )/) }
+ buf = slice.map { |l| l.gsub(/(^\s{2})/, '').gsub(/^\s*$/, '') }.join
+ url = 'https://github.com/serpapi/serpapi-python/blob/master/' + path
+ %Q(```#{format}\nimport serpapi\nimport pprint\nimport os\n\n#{buf}```\ntest: [#{path}](#{url}))
+end
+-%>
+
+
+
SerpApi Python Library & Package
+

+
+
+ [](https://github.com/serpapi/serpapi-python/actions/workflows/ci.yml)
+
+
+This repository is the home of the *soon–to–be* official Python API wrapper for [SerpApi](https://serpapi.com). This `serpapi` module allows you to access search data in your Python application.
+
+[SerpApi](https://serpapi.com) supports Google, Google Maps, Google Shopping, Bing, Baidu, Yandex, Yahoo, eBay, App Stores, and more. Check out the [documentation](https://serpapi.com/search-api) for a full list.
+
+## Current Status
+
+This project is under development, and will be released to the public on PyPi soon.
+
+## Installation
+
+To install the `serpapi` package, simply run the following command:
+
+```bash
+$ pip install serpapi
+```
+
+Please note that this package is separate from the *soon–to–be* legacy `serpapi` module, which is currently available on PyPi as `google-search-results`.
+
+## Usage
+
+Let's start by searching for Coffee on Google:
+
+```pycon
+>>> import serpapi
+>>> s = serpapi.search(q="Coffee", engine="google", location="Austin, Texas", hl="en", gl="us")
+```
+
+The `s` variable now contains a `SerpResults` object, which acts just like a standard dictionary, with some convenient functions added on top.
+
+Let's print the first result:
+
+```pycon
+>>> s["organic_results"][0]["link"]
+'https://en.wikipedia.org/wiki/Coffee'
+```
+
+Let's print the title of the first result, but in a more Pythonic way:
+
+```pycon
+>>> s["organic_results"][0].get("title")
+'Coffee - Wikipedia'
+```
+
+The [SerpApi.com API Documentation](https://serpapi.com/search-api) contains a list of all the possible parameters that can be passed to the API.
+
+## Documentation
+
+Documentation is [available on Read the Docs](https://serpapi-python.readthedocs.io/en/latest/).
+
+## Examples in python
+Here is how to calls the APIs.
+
+### Search bing
+<%= snippet('python', 'tests/example_search_bing_test.py') %>
+see: [serpapi.com/bing-search-api](https://serpapi.com/bing-search-api)
+
+### Search baidu
+<%= snippet('python', 'tests/example_search_baidu_test.py') %>
+see: [serpapi.com/baidu-search-api](https://serpapi.com/baidu-search-api)
+
+### Search yahoo
+<%= snippet('python', 'tests/example_search_yahoo_test.py') %>
+see: [serpapi.com/yahoo-search-api](https://serpapi.com/yahoo-search-api)
+
+### Search youtube
+<%= snippet('python', 'tests/example_search_youtube_test.py') %>
+see: [serpapi.com/youtube-search-api](https://serpapi.com/youtube-search-api)
+
+### Search walmart
+<%= snippet('python', 'tests/example_search_walmart_test.py') %>
+see: [serpapi.com/walmart-search-api](https://serpapi.com/walmart-search-api)
+
+### Search ebay
+<%= snippet('python', 'tests/example_search_ebay_test.py') %>
+see: [serpapi.com/ebay-search-api](https://serpapi.com/ebay-search-api)
+
+### Search naver
+<%= snippet('python', 'tests/example_search_naver_test.py') %>
+see: [serpapi.com/naver-search-api](https://serpapi.com/naver-search-api)
+
+### Search home depot
+<%= snippet('python', 'tests/example_search_home_depot_test.py') %>
+see: [serpapi.com/home-depot-search-api](https://serpapi.com/home-depot-search-api)
+
+### Search apple app store
+<%= snippet('python', 'tests/example_search_apple_app_store_test.py') %>
+see: [serpapi.com/apple-app-store](https://serpapi.com/apple-app-store)
+
+### Search duckduckgo
+<%= snippet('python', 'tests/example_search_duckduckgo_test.py') %>
+see: [serpapi.com/duckduckgo-search-api](https://serpapi.com/duckduckgo-search-api)
+
+### Search google
+<%= snippet('python', 'tests/example_search_google_test.py') %>
+see: [serpapi.com/search-api](https://serpapi.com/search-api)
+
+### Search google scholar
+<%= snippet('python', 'tests/example_search_google_scholar_test.py') %>
+see: [serpapi.com/google-scholar-api](https://serpapi.com/google-scholar-api)
+
+### Search google autocomplete
+<%= snippet('python', 'tests/example_search_google_autocomplete_test.py') %>
+see: [serpapi.com/google-autocomplete-api](https://serpapi.com/google-autocomplete-api)
+
+### Search google product
+<%= snippet('python', 'tests/example_search_google_product_test.py') %>
+see: [serpapi.com/google-product-api](https://serpapi.com/google-product-api)
+
+### Search google reverse image
+<%= snippet('python', 'tests/example_search_google_reverse_image_test.py') %>
+see: [serpapi.com/google-reverse-image](https://serpapi.com/google-reverse-image)
+
+### Search google events
+<%= snippet('python', 'tests/example_search_google_events_test.py') %>
+see: [serpapi.com/google-events-api](https://serpapi.com/google-events-api)
+
+### Search google local services
+<%= snippet('python', 'tests/example_search_google_local_services_test.py') %>
+see: [serpapi.com/google-local-services-api](https://serpapi.com/google-local-services-api)
+
+### Search google maps
+<%= snippet('python', 'tests/example_search_google_maps_test.py') %>
+see: [serpapi.com/google-maps-api](https://serpapi.com/google-maps-api)
+
+### Search google jobs
+<%= snippet('python', 'tests/example_search_google_jobs_test.py') %>
+see: [serpapi.com/google-jobs-api](https://serpapi.com/google-jobs-api)
+
+### Search google play
+<%= snippet('python', 'tests/example_search_google_play_test.py') %>
+see: [serpapi.com/google-play-api](https://serpapi.com/google-play-api)
+
+### Search google images
+<%= snippet('python', 'tests/example_search_google_images_test.py') %>
+see: [serpapi.com/images-results](https://serpapi.com/images-results)
+
+
+## License
+
+MIT License.
+
+## Contributing
+
+Bug reports and pull requests are welcome on GitHub. Once dependencies are installed, you can run the tests with `pytest`.
diff --git a/docs/index.rst b/docs/index.rst
index b0a9a1a..717c69a 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,4 +1,4 @@
-.. serapi-python documentation master file, created by
+.. serpapi-python documentation master file, created by
sphinx-quickstart on Sun Apr 3 21:09:40 2022.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
@@ -37,6 +37,11 @@ For example, the API endpoint ``https://serpapi.com/search.json`` is represented
Any parameters that you pass to ``search()`` will be passed to the API. This includes the ``api_key`` parameter, which is required for all requests.
+.. _using-api-client-directly:
+
+Using the API Client directly
+^^^^^^^^^
+
To make this less repetitive, and gain the benefit of connection pooling, let's start using the API Client directly::
>>> client = serpapi.Client(api_key="secret_api_key")
@@ -78,8 +83,6 @@ This part of the documentation covers all the interfaces of :class:`serpapi` Pyt
.. module:: serpapi
:platform: Unix, Windows
:synopsis: SerpApi Python Library
- :members:
- :undoc-members:
.. autofunction:: serpapi.search
.. autofunction:: serpapi.search_archive
@@ -118,9 +121,11 @@ You can get the next page of results::
>>> type(s.next_page())
-Or iterate over all pages of results::
+To iterate over all pages of results, it's recommended to :ref:`use the API Client directly `::
- >>> for page in s.yield_pages():
+ >>> client = serpapi.Client(api_key="secret_api_key")
+ >>> search = client.search(q="Coffee", engine="google", location="Austin, Texas", hl="en", gl="us")
+ >>> for page in search.yield_pages():
... print(page["search_metadata"]["page_number"])
1
2
@@ -162,7 +167,7 @@ This class also alleviates the need to pass an ``api_key``` along with every se
Exceptions
----------
-.. autoexception:: serpapi.SerpAPIError
+.. autoexception:: serpapi.SerpApiError
:members:
.. autoexception:: serpapi.SearchIDNotProvided
diff --git a/pylint.rc b/pylint.rc
new file mode 100644
index 0000000..8cdc70e
--- /dev/null
+++ b/pylint.rc
@@ -0,0 +1,637 @@
+[MAIN]
+
+# Analyse import fallback blocks. This can be used to support both Python 2 and
+# 3 compatible code, which means that the block might have code that exists
+# only in one or another interpreter, leading to false positives when analysed.
+analyse-fallback-blocks=no
+
+# Clear in-memory caches upon conclusion of linting. Useful if running pylint
+# in a server-like mode.
+clear-cache-post-run=no
+
+# Load and enable all available extensions. Use --list-extensions to see a list
+# all available extensions.
+#enable-all-extensions=
+
+# In error mode, messages with a category besides ERROR or FATAL are
+# suppressed, and no reports are done by default. Error mode is compatible with
+# disabling specific errors.
+#errors-only=
+
+# Always return a 0 (non-error) status code, even if lint errors are found.
+# This is primarily useful in continuous integration scripts.
+#exit-zero=
+
+# A comma-separated list of package or module names from where C extensions may
+# be loaded. Extensions are loading into the active Python interpreter and may
+# run arbitrary code.
+extension-pkg-allow-list=
+
+# A comma-separated list of package or module names from where C extensions may
+# be loaded. Extensions are loading into the active Python interpreter and may
+# run arbitrary code. (This is an alternative name to extension-pkg-allow-list
+# for backward compatibility.)
+extension-pkg-whitelist=
+
+# Return non-zero exit code if any of these messages/categories are detected,
+# even if score is above --fail-under value. Syntax same as enable. Messages
+# specified are enabled, while categories only check already-enabled messages.
+fail-on=
+
+# Specify a score threshold under which the program will exit with error.
+fail-under=10
+
+# Interpret the stdin as a python script, whose filename needs to be passed as
+# the module_or_package argument.
+#from-stdin=
+
+# Files or directories to be skipped. They should be base names, not paths.
+ignore=CVS
+
+# Add files or directories matching the regular expressions patterns to the
+# ignore-list. The regex matches against paths and can be in Posix or Windows
+# format. Because '\\' represents the directory delimiter on Windows systems,
+# it can't be used as an escape character.
+ignore-paths=
+
+# Files or directories matching the regular expression patterns are skipped.
+# The regex matches against base names, not paths. The default value ignores
+# Emacs file locks
+ignore-patterns=^\.#
+
+# List of module names for which member attributes should not be checked
+# (useful for modules/projects where namespaces are manipulated during runtime
+# and thus existing member attributes cannot be deduced by static analysis). It
+# supports qualified module names, as well as Unix pattern matching.
+ignored-modules=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
+# number of processors available to use, and will cap the count on Windows to
+# avoid hangs.
+jobs=1
+
+# Control the amount of potential inferred values when inferring a single
+# object. This can help the performance when dealing with large functions or
+# complex, nested conditions.
+limit-inference-results=100
+
+# List of plugins (as comma separated values of python module names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# Minimum Python version to use for version dependent checks. Will default to
+# the version used to run pylint.
+py-version=3.11
+
+# Discover python modules and packages in the file system subtree.
+recursive=no
+
+# Add paths to the list of the source roots. Supports globbing patterns. The
+# source root is an absolute path or a path relative to the current working
+# directory used to determine a package namespace for modules located under the
+# source root.
+source-roots=
+
+# When enabled, pylint would attempt to guess common misconfiguration and emit
+# user-friendly hints instead of false-positive error messages.
+suggestion-mode=yes
+
+# Allow loading of arbitrary C extensions. Extensions are imported into the
+# active Python interpreter and may run arbitrary code.
+unsafe-load-any-extension=no
+
+# In verbose mode, extra non-checker-related info will be displayed.
+#verbose=
+
+
+[BASIC]
+
+# Naming style matching correct argument names.
+argument-naming-style=snake_case
+
+# Regular expression matching correct argument names. Overrides argument-
+# naming-style. If left empty, argument names will be checked with the set
+# naming style.
+#argument-rgx=
+
+# Naming style matching correct attribute names.
+attr-naming-style=snake_case
+
+# Regular expression matching correct attribute names. Overrides attr-naming-
+# style. If left empty, attribute names will be checked with the set naming
+# style.
+#attr-rgx=
+
+# Bad variable names which should always be refused, separated by a comma.
+bad-names=foo,
+ bar,
+ baz,
+ toto,
+ tutu,
+ tata
+ victor
+ kenneth
+ bart
+
+# Bad variable names regexes, separated by a comma. If names match any regex,
+# they will always be refused
+bad-names-rgxs=
+
+# Naming style matching correct class attribute names.
+class-attribute-naming-style=any
+
+# Regular expression matching correct class attribute names. Overrides class-
+# attribute-naming-style. If left empty, class attribute names will be checked
+# with the set naming style.
+#class-attribute-rgx=
+
+# Naming style matching correct class constant names.
+class-const-naming-style=UPPER_CASE
+
+# Regular expression matching correct class constant names. Overrides class-
+# const-naming-style. If left empty, class constant names will be checked with
+# the set naming style.
+#class-const-rgx=
+
+# Naming style matching correct class names.
+class-naming-style=PascalCase
+
+# Regular expression matching correct class names. Overrides class-naming-
+# style. If left empty, class names will be checked with the set naming style.
+#class-rgx=
+
+# Naming style matching correct constant names.
+const-naming-style=UPPER_CASE
+
+# Regular expression matching correct constant names. Overrides const-naming-
+# style. If left empty, constant names will be checked with the set naming
+# style.
+#const-rgx=
+
+# Minimum line length for functions/classes that require docstrings, shorter
+# ones are exempt.
+docstring-min-length=-1
+
+# Naming style matching correct function names.
+function-naming-style=snake_case
+
+# Regular expression matching correct function names. Overrides function-
+# naming-style. If left empty, function names will be checked with the set
+# naming style.
+#function-rgx=
+
+# Good variable names which should always be accepted, separated by a comma.
+good-names=i,
+ j,
+ k,
+ ex,
+ Run,
+ _
+
+# Good variable names regexes, separated by a comma. If names match any regex,
+# they will always be accepted
+good-names-rgxs=
+
+# Include a hint for the correct naming format with invalid-name.
+include-naming-hint=no
+
+# Naming style matching correct inline iteration names.
+inlinevar-naming-style=any
+
+# Regular expression matching correct inline iteration names. Overrides
+# inlinevar-naming-style. If left empty, inline iteration names will be checked
+# with the set naming style.
+#inlinevar-rgx=
+
+# Naming style matching correct method names.
+method-naming-style=snake_case
+
+# Regular expression matching correct method names. Overrides method-naming-
+# style. If left empty, method names will be checked with the set naming style.
+#method-rgx=
+
+# Naming style matching correct module names.
+module-naming-style=snake_case
+
+# Regular expression matching correct module names. Overrides module-naming-
+# style. If left empty, module names will be checked with the set naming style.
+#module-rgx=
+
+# Colon-delimited sets of names that determine each other's naming style when
+# the name regexes allow several styles.
+name-group=
+
+# Regular expression which should only match function or class names that do
+# not require a docstring.
+no-docstring-rgx=^_
+
+# List of decorators that produce properties, such as abc.abstractproperty. Add
+# to this list to register other decorators that produce valid properties.
+# These decorators are taken in consideration only for invalid-name.
+property-classes=abc.abstractproperty
+
+# Regular expression matching correct type alias names. If left empty, type
+# alias names will be checked with the set naming style.
+#typealias-rgx=
+
+# Regular expression matching correct type variable names. If left empty, type
+# variable names will be checked with the set naming style.
+#typevar-rgx=
+
+# Naming style matching correct variable names.
+variable-naming-style=snake_case
+
+# Regular expression matching correct variable names. Overrides variable-
+# naming-style. If left empty, variable names will be checked with the set
+# naming style.
+#variable-rgx=
+
+
+[CLASSES]
+
+# Warn about protected attribute access inside special methods
+check-protected-access-in-special-methods=no
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,
+ __new__,
+ setUp,
+ asyncSetUp,
+ __post_init__
+
+# List of member names, which should be excluded from the protected access
+# warning.
+exclude-protected=_asdict,_fields,_replace,_source,_make,os._exit
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=mcs
+
+
+[DESIGN]
+
+# List of regular expressions of class ancestor names to ignore when counting
+# public methods (see R0903)
+exclude-too-few-public-methods=
+
+# List of qualified class names to ignore when counting class parents (see
+# R0901)
+ignored-parents=
+
+# Maximum number of arguments for function / method.
+max-args=5
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Maximum number of boolean expressions in an if statement (see R0916).
+max-bool-expr=5
+
+# Maximum number of branch for function / method body.
+max-branches=12
+
+# Maximum number of locals for function / method body.
+max-locals=15
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+# Maximum number of return / yield for function / method body.
+max-returns=6
+
+# Maximum number of statements in function / method body.
+max-statements=50
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when caught.
+overgeneral-exceptions=builtins.BaseException,builtins.Exception
+
+
+[FORMAT]
+
+# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
+expected-line-ending-format=
+
+# Regexp for a line that is allowed to be longer than the limit.
+ignore-long-lines=^\s*(# )??$
+
+# Number of spaces of indent required inside a hanging or continued line.
+indent-after-paren=4
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string=' '
+
+# Maximum number of characters on a single line.
+max-line-length=100
+
+# Maximum number of lines in a module.
+max-module-lines=1000
+
+# Allow the body of a class to be on the same line as the declaration if body
+# contains single statement.
+single-line-class-stmt=no
+
+# Allow the body of an if to be on the same line as the test if there is no
+# else.
+single-line-if-stmt=no
+
+
+[IMPORTS]
+
+# List of modules that can be imported at any level, not just the top level
+# one.
+allow-any-import-level=
+
+# Allow explicit reexports by alias from a package __init__.
+allow-reexport-from-package=no
+
+# Allow wildcard imports from modules that define __all__.
+allow-wildcard-with-all=no
+
+# Deprecated modules which should not be used, separated by a comma.
+deprecated-modules=
+
+# Output a graph (.gv or any supported image format) of external dependencies
+# to the given file (report RP0402 must not be disabled).
+ext-import-graph=
+
+# Output a graph (.gv or any supported image format) of all (i.e. internal and
+# external) dependencies to the given file (report RP0402 must not be
+# disabled).
+import-graph=
+
+# Output a graph (.gv or any supported image format) of internal dependencies
+# to the given file (report RP0402 must not be disabled).
+int-import-graph=
+
+# Force import order to recognize a module as part of the standard
+# compatibility libraries.
+known-standard-library=
+
+# Force import order to recognize a module as part of a third party library.
+known-third-party=enchant
+
+# Couples of modules and preferred modules, separated by a comma.
+preferred-modules=
+
+
+[LOGGING]
+
+# The type of string formatting that logging methods do. `old` means using %
+# formatting, `new` is for `{}` formatting.
+logging-format-style=old
+
+# Logging modules to check that the string format arguments are in logging
+# function parameter format.
+logging-modules=logging
+
+
+[MESSAGES CONTROL]
+
+# Only show warnings with the listed confidence levels. Leave empty to show
+# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE,
+# UNDEFINED.
+confidence=HIGH,
+ CONTROL_FLOW,
+ INFERENCE,
+ INFERENCE_FAILURE,
+ UNDEFINED
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once). You can also use "--disable=all" to
+# disable everything first and then re-enable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use "--disable=all --enable=classes
+# --disable=W".
+disable=raw-checker-failed,
+ bad-inline-option,
+ locally-disabled,
+ file-ignored,
+ suppressed-message,
+ useless-suppression,
+ deprecated-pragma,
+ use-symbolic-message-instead
+ unnecessary-pass
+ invalid-name
+
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once). See also the "--disable" option for examples.
+enable=c-extension-no-member
+
+
+[METHOD_ARGS]
+
+# List of qualified names (i.e., library.method) which require a timeout
+# parameter e.g. 'requests.api.get,requests.api.post'
+timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,
+ XXX,
+ TODO
+
+# Regular expression of note tags to take in consideration.
+notes-rgx=
+
+
+[REFACTORING]
+
+# Maximum number of nested blocks for function / method body
+max-nested-blocks=5
+
+# Complete name of functions that never returns. When checking for
+# inconsistent-return-statements if a never returning function is called then
+# it will be considered as an explicit return statement and no message will be
+# printed.
+never-returning-functions=sys.exit,argparse.parse_error
+
+
+[REPORTS]
+
+# Python expression which should return a score less than or equal to 10. You
+# have access to the variables 'fatal', 'error', 'warning', 'refactor',
+# 'convention', and 'info' which contain the number of messages in each
+# category, as well as 'statement' which is the total number of statements
+# analyzed. This score is used by the global evaluation report (RP0004).
+evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))
+
+# Template used to display messages. This is a python new-style format string
+# used to format the message information. See doc for all details.
+msg-template=
+
+# Set the output format. Available formats are text, parseable, colorized, json
+# and msvs (visual studio). You can also give a reporter class, e.g.
+# mypackage.mymodule.MyReporterClass.
+#output-format=
+
+# Tells whether to display a full report or only the messages.
+reports=no
+
+# Activate the evaluation score.
+score=yes
+
+
+[SIMILARITIES]
+
+# Comments are removed from the similarity computation
+ignore-comments=yes
+
+# Docstrings are removed from the similarity computation
+ignore-docstrings=yes
+
+# Imports are removed from the similarity computation
+ignore-imports=yes
+
+# Signatures are removed from the similarity computation
+ignore-signatures=yes
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+
+[SPELLING]
+
+# Limits count of emitted suggestions for spelling mistakes.
+max-spelling-suggestions=4
+
+# Spelling dictionary name. No available dictionaries : You need to install
+# both the python package and the system dependency for enchant to work..
+spelling-dict=
+
+# List of comma separated words that should be considered directives if they
+# appear at the beginning of a comment and should not be checked.
+spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:
+
+# List of comma separated words that should not be checked.
+spelling-ignore-words=
+
+# A path to a file that contains the private dictionary; one word per line.
+spelling-private-dict-file=
+
+# Tells whether to store unknown words to the private dictionary (see the
+# --spelling-private-dict-file option) instead of raising a message.
+spelling-store-unknown-words=no
+
+
+[STRING]
+
+# This flag controls whether inconsistent-quotes generates a warning when the
+# character used as a quote delimiter is used inconsistently within a module.
+check-quote-consistency=no
+
+# This flag controls whether the implicit-str-concat should generate a warning
+# on implicit string concatenation in sequences defined over several lines.
+check-str-concat-over-line-jumps=no
+
+
+[TYPECHECK]
+
+# List of decorators that produce context managers, such as
+# contextlib.contextmanager. Add to this list to register other decorators that
+# produce valid context managers.
+contextmanager-decorators=contextlib.contextmanager
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E1101 when accessed. Python regular
+# expressions are accepted.
+generated-members=
+
+# Tells whether to warn about missing members when the owner of the attribute
+# is inferred to be None.
+ignore-none=yes
+
+# This flag controls whether pylint should warn about no-member and similar
+# checks whenever an opaque object is returned when inferring. The inference
+# can return multiple potential results while evaluating a Python object, but
+# some branches might not be evaluated, which results in partial inference. In
+# that case, it might be useful to still emit no-member and other checks for
+# the rest of the inferred objects.
+ignore-on-opaque-inference=yes
+
+# List of symbolic message names to ignore for Mixin members.
+ignored-checks-for-mixins=no-member,
+ not-async-context-manager,
+ not-context-manager,
+ attribute-defined-outside-init
+
+# List of class names for which member attributes should not be checked (useful
+# for classes with dynamically set attributes). This supports the use of
+# qualified names.
+ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace
+
+# Show a hint with possible names when a member name was not found. The aspect
+# of finding the hint is based on edit distance.
+missing-member-hint=yes
+
+# The minimum edit distance a name should have in order to be considered a
+# similar match for a missing member name.
+missing-member-hint-distance=1
+
+# The total number of similar names that should be taken in consideration when
+# showing a hint for a missing member.
+missing-member-max-choices=1
+
+# Regex pattern to define which classes are considered mixins.
+mixin-class-rgx=.*[Mm]ixin
+
+# List of decorators that change the signature of a decorated function.
+signature-mutators=
+
+
+[VARIABLES]
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid defining new builtins when possible.
+additional-builtins=
+
+# Tells whether unused global variables should be treated as a violation.
+allow-global-unused-variables=yes
+
+# List of names allowed to shadow builtins
+allowed-redefined-builtins=
+
+# List of strings which can identify a callback function by name. A callback
+# name must start or end with one of those strings.
+callbacks=cb_,
+ _cb
+
+# A regular expression matching the name of dummy variables (i.e. expected to
+# not be used).
+dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
+
+# Argument names that match this expression will be ignored.
+ignored-argument-names=_.*|^ignored_|^unused_
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# List of qualified module names which can have objects that can redefine
+# builtins.
+redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
diff --git a/serpapi/__version__.py b/serpapi/__version__.py
index f102a9c..1276d02 100644
--- a/serpapi/__version__.py
+++ b/serpapi/__version__.py
@@ -1 +1 @@
-__version__ = "0.0.1"
+__version__ = "0.1.5"
diff --git a/serpapi/core.py b/serpapi/core.py
index b6b5beb..a627d21 100644
--- a/serpapi/core.py
+++ b/serpapi/core.py
@@ -28,10 +28,10 @@ class Client(HTTPClient):
def __repr__(self):
return ""
- def search(self, **params):
+ def search(self, params: dict = None, **kwargs):
"""Fetch a page of results from SerpApi. Returns a :class:`SerpResults ` object, or unicode text (*e.g.* if ``'output': 'html'`` was passed).
- The following two calls are equivalent:
+ The following three calls are equivalent:
.. code-block:: python
@@ -42,6 +42,11 @@ def search(self, **params):
>>> params = {"q": "Coffee", "location": "Austin, Texas, United States"}
>>> s = serpapi.search(**params)
+ .. code-block:: python
+
+ >>> params = {"q": "Coffee", "location": "Austin, Texas, United States"}
+ >>> s = serpapi.search(params)
+
:param q: typically, this is the parameter for the search engine query.
:param engine: the search engine to use. Defaults to ``google``.
@@ -52,12 +57,17 @@ def search(self, **params):
**Learn more**: https://serpapi.com/search-api
"""
+ if params is None:
+ params = {}
+
+ if kwargs:
+ params.update(kwargs)
r = self.request("GET", "/search", params=params)
return SerpResults.from_http_response(r, client=self)
- def search_archive(self, **params):
+ def search_archive(self, params: dict = None, **kwargs):
"""Get a result from the SerpApi Search Archive API.
:param search_id: the Search ID of the search to retrieve from the archive.
@@ -67,6 +77,11 @@ def search_archive(self, **params):
**Learn more**: https://serpapi.com/search-archive-api
"""
+ if params is None:
+ params = {}
+
+ if kwargs:
+ params.update(kwargs)
try:
search_id = params["search_id"]
@@ -78,7 +93,7 @@ def search_archive(self, **params):
r = self.request("GET", f"/searches/{ search_id }", params=params)
return SerpResults.from_http_response(r, client=self)
- def locations(self, **params):
+ def locations(self, params: dict = None, **kwargs):
"""Get a list of supported Google locations.
@@ -88,6 +103,11 @@ def locations(self, **params):
**Learn more**: https://serpapi.com/locations-api
"""
+ if params is None:
+ params = {}
+
+ if kwargs:
+ params.update(kwargs)
r = self.request(
"GET",
@@ -97,10 +117,7 @@ def locations(self, **params):
)
return r.json()
- def account(
- self,
- **params,
- ):
+ def account(self, params: dict = None, **kwargs):
"""Get SerpApi account information.
:param api_key: the API Key to use for SerpApi.com.
@@ -109,10 +126,17 @@ def account(
**Learn more**: https://serpapi.com/account-api
"""
+ if params is None:
+ params = {}
+
+ if kwargs:
+ params.update(kwargs)
+
r = self.request("GET", "/account.json", params=params, assert_200=True)
return r.json()
+# An un-authenticated client instance.
_client = Client()
search = _client.search
search_archive = _client.search_archive
diff --git a/serpapi/exceptions.py b/serpapi/exceptions.py
index f1e31be..f501189 100644
--- a/serpapi/exceptions.py
+++ b/serpapi/exceptions.py
@@ -1,31 +1,31 @@
import requests
-class SerpAPIError(Exception):
+class SerpApiError(Exception):
"""Base class for exceptions in this module."""
pass
-class APIKeyNotProvided(ValueError, SerpAPIError):
+class APIKeyNotProvided(ValueError, SerpApiError):
"""API key is not provided."""
pass
-class SearchIDNotProvided(ValueError, SerpAPIError):
+class SearchIDNotProvided(ValueError, SerpApiError):
"""Search ID is not provided."""
pass
-class HTTPError(requests.exceptions.HTTPError, SerpAPIError):
+class HTTPError(requests.exceptions.HTTPError, SerpApiError):
"""HTTP Error."""
pass
-class HTTPConnectionError(HTTPError, requests.exceptions.ConnectionError, SerpAPIError):
+class HTTPConnectionError(HTTPError, requests.exceptions.ConnectionError, SerpApiError):
"""Connection Error."""
pass
diff --git a/serpapi/models.py b/serpapi/models.py
index 07f280f..0aa7720 100644
--- a/serpapi/models.py
+++ b/serpapi/models.py
@@ -3,14 +3,12 @@
from pprint import pformat
from collections import UserDict
-import requests
-
from .textui import prettify_json
from .exceptions import HTTPError
class SerpResults(UserDict):
- """A dictionary-like object that represents the results of a SerpAPI request.
+ """A dictionary-like object that represents the results of a SerpApi request.
.. code-block:: python
@@ -53,7 +51,7 @@ def next_page_url(self):
serpapi_pagination = self.data.get("serpapi_pagination")
if serpapi_pagination:
- return serpapi_pagination.get("next_link")
+ return serpapi_pagination.get("next")
def next_page(self):
"""Return the next page of results, if any."""
@@ -72,12 +70,16 @@ def yield_pages(self, max_pages=1_000):
"""
current_page_count = 0
-
+
current_page = self
- while current_page.next_page_url and current_page_count < max_pages:
- current_page = current_page.next_page()
- current_page_count += 1
+ while current_page and current_page_count < max_pages:
yield current_page
+ current_page_count += 1
+ if current_page.next_page_url:
+ current_page = current_page.next_page()
+ else:
+ break
+
@classmethod
def from_http_response(cls, r, *, client=None):
diff --git a/setup.py b/setup.py
index 52236a6..085e79a 100644
--- a/setup.py
+++ b/setup.py
@@ -46,6 +46,27 @@
about["__version__"] = VERSION
+class TestCommand(Command):
+ """Support setup.py test."""
+
+ description = "Test the package."
+ user_options = []
+
+ @staticmethod
+ def status(s):
+ """Prints things in bold."""
+ print("\033[1m{0}\033[0m".format(s))
+
+ def initialize_options(self):
+ pass
+
+ def finalize_options(self):
+ pass
+
+ def run(self):
+ os.system("{0} -m pytest".format(sys.executable))
+ sys.exit()
+
class UploadCommand(Command):
"""Support setup.py upload."""
@@ -104,7 +125,7 @@ def run(self):
extras_require=EXTRAS,
include_package_data=True,
license="MIT",
- project_urls={"Documentation": "https://serpapi.com/search-api"},
+ project_urls={"Documentation": "https://serpapi-python.readthedocs.io/en/latest/"},
keywords="scrape,serp,api,serpapi,scraping,json,search,localized,rank,google,bing,baidu,yandex,yahoo,ebay,scale,datamining,training,machine,ml,youtube,naver,walmart,apple,store,app,serpapi",
classifiers=[
# Trove classifiers
@@ -119,6 +140,7 @@ def run(self):
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
"Natural Language :: English",
"Topic :: Utilities",
"Topic :: Internet :: WWW/HTTP",
@@ -129,5 +151,6 @@ def run(self):
# $ setup.py publish support.
cmdclass={
"upload": UploadCommand,
+ "test": TestCommand
},
)
diff --git a/tests/example_search_apple_app_store_test.py b/tests/example_search_apple_app_store_test.py
new file mode 100644
index 0000000..70bb30b
--- /dev/null
+++ b/tests/example_search_apple_app_store_test.py
@@ -0,0 +1,12 @@
+# Example: apple_app_store search engine
+import pytest
+import os
+import serpapi
+
+def test_search_apple_app_store(client):
+ data = client.search({
+ 'engine': 'apple_app_store',
+ 'term': 'coffee',
+ })
+ assert data.get('error') is None
+ assert data['organic_results']
diff --git a/tests/example_search_baidu_test.py b/tests/example_search_baidu_test.py
new file mode 100644
index 0000000..d5a0d52
--- /dev/null
+++ b/tests/example_search_baidu_test.py
@@ -0,0 +1,13 @@
+# Example: baidu search engine
+import pytest
+import os
+import serpapi
+
+
+def test_search_baidu(client):
+ data = client.search({
+ 'engine': 'baidu',
+ 'q': 'coffee',
+ })
+ assert data.get('error') is None
+ assert data['organic_results']
diff --git a/tests/example_search_bing_test.py b/tests/example_search_bing_test.py
new file mode 100644
index 0000000..36a1c79
--- /dev/null
+++ b/tests/example_search_bing_test.py
@@ -0,0 +1,12 @@
+# Example: bing search engine
+import pytest
+import os
+import serpapi
+
+def test_search_bing(client):
+ data = client.search({
+ 'engine': 'bing',
+ 'q': 'coffee',
+ })
+ assert data.get('error') is None
+ assert data['organic_results']
diff --git a/tests/example_search_duckduckgo_test.py b/tests/example_search_duckduckgo_test.py
new file mode 100644
index 0000000..4a198ab
--- /dev/null
+++ b/tests/example_search_duckduckgo_test.py
@@ -0,0 +1,12 @@
+# Example: duckduckgo search engine
+import pytest
+import os
+import serpapi
+
+def test_search_duckduckgo(client):
+ data = client.search({
+ 'engine': 'duckduckgo',
+ 'q': 'coffee',
+ })
+ assert data.get('error') is None
+ assert data['organic_results']
diff --git a/tests/example_search_ebay_test.py b/tests/example_search_ebay_test.py
new file mode 100644
index 0000000..fd41037
--- /dev/null
+++ b/tests/example_search_ebay_test.py
@@ -0,0 +1,12 @@
+# Example: ebay search engine
+import pytest
+import os
+import serpapi
+
+def test_search_ebay(client):
+ data = client.search({
+ 'engine': 'ebay',
+ '_nkw': 'coffee',
+ })
+ assert data.get('error') is None
+ assert data['organic_results']
diff --git a/tests/example_search_google_autocomplete_test.py b/tests/example_search_google_autocomplete_test.py
new file mode 100644
index 0000000..3de2012
--- /dev/null
+++ b/tests/example_search_google_autocomplete_test.py
@@ -0,0 +1,12 @@
+# Example: google_autocomplete search engine
+import pytest
+import os
+import serpapi
+
+def test_search_google_autocomplete(client):
+ data = client.search({
+ 'engine': 'google_autocomplete',
+ 'q': 'coffee',
+ })
+ assert data.get('error') is None
+ assert data['suggestions']
diff --git a/tests/example_search_google_events_test.py b/tests/example_search_google_events_test.py
new file mode 100644
index 0000000..a46f5bf
--- /dev/null
+++ b/tests/example_search_google_events_test.py
@@ -0,0 +1,12 @@
+# Example: google_events search engine
+import pytest
+import os
+import serpapi
+
+def test_search_google_events(client):
+ data = client.search({
+ 'engine': 'google_events',
+ 'q': 'coffee',
+ })
+ assert data.get('error') is None
+ assert data['events_results']
diff --git a/tests/example_search_google_images_test.py b/tests/example_search_google_images_test.py
new file mode 100644
index 0000000..338e69b
--- /dev/null
+++ b/tests/example_search_google_images_test.py
@@ -0,0 +1,14 @@
+# Example: google_images search engine
+import pytest
+import os
+import serpapi
+
+def test_search_google_images(client):
+ data = client.search({
+ 'engine': 'google_images',
+ 'engine': 'google_images',
+ 'tbm': 'isch',
+ 'q': 'coffee',
+ })
+ assert data.get('error') is None
+ assert data['images_results']
diff --git a/tests/example_search_google_jobs_test.py b/tests/example_search_google_jobs_test.py
new file mode 100644
index 0000000..c465589
--- /dev/null
+++ b/tests/example_search_google_jobs_test.py
@@ -0,0 +1,12 @@
+# Example: google_jobs search engine
+import pytest
+import os
+import serpapi
+
+def test_search_google_jobs(client):
+ data = client.search({
+ 'engine': 'google_jobs',
+ 'q': 'coffee',
+ })
+ assert data.get('error') is None
+ assert data['jobs_results']
diff --git a/tests/example_search_google_local_services_test.py b/tests/example_search_google_local_services_test.py
new file mode 100644
index 0000000..964b013
--- /dev/null
+++ b/tests/example_search_google_local_services_test.py
@@ -0,0 +1,14 @@
+# Example: google_local_services search engine
+import pytest
+import os
+import serpapi
+
+def test_search_google_local_services(client):
+
+ data = client.search({
+ 'engine': 'google_local_services',
+ 'q': 'electrician',
+ 'data_cid': '6745062158417646970',
+ })
+ assert data.get('error') is None
+ assert data['local_ads']
diff --git a/tests/example_search_google_maps_test.py b/tests/example_search_google_maps_test.py
new file mode 100644
index 0000000..453b5dc
--- /dev/null
+++ b/tests/example_search_google_maps_test.py
@@ -0,0 +1,14 @@
+# Example: google_maps search engine
+import pytest
+import os
+import serpapi
+
+def test_search_google_maps(client):
+ data = client.search({
+ 'engine': 'google_maps',
+ 'q': 'pizza',
+ 'll': '@40.7455096,-74.0083012,15.1z',
+ 'type': 'search',
+ })
+ assert data.get('error') is None
+ assert data['local_results']
diff --git a/tests/example_search_google_play_test.py b/tests/example_search_google_play_test.py
new file mode 100644
index 0000000..bd44bef
--- /dev/null
+++ b/tests/example_search_google_play_test.py
@@ -0,0 +1,14 @@
+# Example: google_play search engine
+import pytest
+import os
+import serpapi
+
+def test_search_google_play(client):
+ data = client.search({
+ 'engine': 'google_play',
+ 'q': 'kite',
+ 'store': 'apps',
+ 'max_results': '2',
+ })
+ assert data.get('error') is None
+ assert data['organic_results']
diff --git a/tests/example_search_google_product_test.py b/tests/example_search_google_product_test.py
new file mode 100644
index 0000000..9229a07
--- /dev/null
+++ b/tests/example_search_google_product_test.py
@@ -0,0 +1,13 @@
+# Example: google_product search engine
+import pytest
+import os
+import serpapi
+
+def test_search_google_product(client):
+ data = client.search({
+ 'engine': 'google_product',
+ 'q': 'coffee',
+ 'product_id': '4887235756540435899',
+ })
+ assert data.get('error') is None
+ assert data['product_results']
diff --git a/tests/example_search_google_reverse_image_test.py b/tests/example_search_google_reverse_image_test.py
new file mode 100644
index 0000000..cbe9bac
--- /dev/null
+++ b/tests/example_search_google_reverse_image_test.py
@@ -0,0 +1,13 @@
+# Example: google_reverse_image search engine
+import pytest
+import os
+import serpapi
+
+def test_search_google_reverse_image(client):
+ data = client.search({
+ 'engine': 'google_reverse_image',
+ 'image_url': 'https://i.imgur.com/5bGzZi7.jpg',
+ 'max_results': '1',
+ })
+ assert data.get('error') is None
+ assert data['image_sizes']
diff --git a/tests/example_search_google_scholar_test.py b/tests/example_search_google_scholar_test.py
new file mode 100644
index 0000000..61ff7e0
--- /dev/null
+++ b/tests/example_search_google_scholar_test.py
@@ -0,0 +1,13 @@
+# Example: google_scholar search engine
+import pytest
+import os
+import serpapi
+
+def test_search_google_scholar(client):
+
+ data = client.search({
+ 'engine': 'google_scholar',
+ 'q': 'coffee',
+ })
+ assert data.get('error') is None
+ assert data['organic_results']
diff --git a/tests/example_search_google_test.py b/tests/example_search_google_test.py
new file mode 100644
index 0000000..650bcff
--- /dev/null
+++ b/tests/example_search_google_test.py
@@ -0,0 +1,14 @@
+# Example: google search engine
+import pytest
+import os
+import serpapi
+
+def test_search_google(client):
+
+ data = client.search({
+ 'engine': 'google',
+ 'q': 'coffee',
+ 'engine': 'google',
+ })
+ assert data.get('error') is None
+ assert data['organic_results']
diff --git a/tests/example_search_home_depot_test.py b/tests/example_search_home_depot_test.py
new file mode 100644
index 0000000..a09f4fd
--- /dev/null
+++ b/tests/example_search_home_depot_test.py
@@ -0,0 +1,13 @@
+# Example: home_depot search engine
+import pytest
+import os
+import serpapi
+
+def test_search_home_depot(client):
+
+ data = client.search({
+ 'engine': 'home_depot',
+ 'q': 'table',
+ })
+ assert data.get('error') is None
+ assert data['products']
diff --git a/tests/example_search_naver_test.py b/tests/example_search_naver_test.py
new file mode 100644
index 0000000..fa2bb26
--- /dev/null
+++ b/tests/example_search_naver_test.py
@@ -0,0 +1,12 @@
+# Example: naver search engine
+import pytest
+import os
+import serpapi
+
+def test_search_naver(client):
+ data = client.search({
+ 'engine': 'naver',
+ 'query': 'coffee',
+ })
+ assert data.get('error') is None
+ assert data['ads_results']
diff --git a/tests/example_search_walmart_test.py b/tests/example_search_walmart_test.py
new file mode 100644
index 0000000..24248fa
--- /dev/null
+++ b/tests/example_search_walmart_test.py
@@ -0,0 +1,13 @@
+# Example: walmart search engine
+import pytest
+import os
+import serpapi
+
+def test_search_walmart(client):
+ data = client.search({
+ 'engine': 'walmart',
+ 'query': 'coffee',
+ })
+ assert data.get('error') is None
+ assert data['organic_results']
+
diff --git a/tests/example_search_yahoo_test.py b/tests/example_search_yahoo_test.py
new file mode 100644
index 0000000..0a5af69
--- /dev/null
+++ b/tests/example_search_yahoo_test.py
@@ -0,0 +1,12 @@
+# Example: yahoo search engine
+import pytest
+import os
+import serpapi
+
+def test_search_yahoo(client):
+ data = client.search({
+ 'engine': 'yahoo',
+ 'p': 'coffee',
+ })
+ assert data.get('error') is None
+ assert data['organic_results']
diff --git a/tests/example_search_youtube_test.py b/tests/example_search_youtube_test.py
new file mode 100644
index 0000000..00c3da6
--- /dev/null
+++ b/tests/example_search_youtube_test.py
@@ -0,0 +1,13 @@
+# Example: youtube search engine
+import pytest
+import os
+import serpapi
+
+def test_search_youtube(client):
+
+ data = client.search({
+ 'engine': 'youtube',
+ 'search_query': 'coffee',
+ })
+ assert data.get('error') is None
+ assert data['video_results']
diff --git a/tests/test_integration.py b/tests/test_integration.py
index 2902b23..644ef50 100644
--- a/tests/test_integration.py
+++ b/tests/test_integration.py
@@ -58,6 +58,9 @@ def test_coffee_search_n_pages(coffee_search):
max_pages = 3
for page in coffee_search.yield_pages(max_pages=max_pages):
+ if page_count == 0:
+ assert 'start' not in page['search_parameters'], "The 'start' parameter should not be in the first page"
+
page_count += 1
assert page_count == max_pages
@@ -68,3 +71,14 @@ def test_coffee_search_next_page(coffee_search):
assert isinstance(next_page, serpapi.SerpResults)
assert coffee_search["search_metadata"]["id"] != next_page["search_metadata"]["id"]
+
+
+def test_search_function_signature(coffee_params, client):
+ s = client.search(coffee_params)
+ assert s["search_metadata"]["id"]
+
+ s = client.search(**coffee_params)
+ assert s["search_metadata"]["id"]
+
+ s = client.search(q='coffee')
+ assert s["search_metadata"]["id"]