How can I scrape faster
asyncio is also a solution if you don't want to use multi threading
import time
import pymongo
import json
import asyncio
from aiohttp import ClientSession
async def get_url(url, session):
async with session.get(url) as response:
if response.status == 200:
return await response.text()
async def create_task(sem, url, session):
async with sem:
response = await get_url(url, session)
if response:
parsed = json.loads(response)
n = url.rsplit('/', 1)[1]
inserted = com.insert_one(parsed)
write_log.write(str(n) + "\t" + str(inserted) + "\n")
print(str(n) + "\t" + str(inserted) + "\n")
async def run(minimum, maximum):
url = 'https:/xx.xxx.xxx/{}.json'
tasks = []
sem = asyncio.Semaphore(1000) # Maximize the concurrent sessions to 1000, stay below the max open sockets allowed
async with ClientSession() as session:
for n in range(minimum, maximum):
task = asyncio.ensure_future(create_task(sem, url.format(n), session))
tasks.append(task)
responses = asyncio.gather(*tasks)
await responses
client = pymongo.MongoClient("mongodb://127.0.0.1:27017")
db = client["thread1"]
com = db["threadcol"]
start_time = time.time()
write_log = open("logging.log", "a")
min_item = 1
max_item = 100
loop = asyncio.get_event_loop()
future = asyncio.ensure_future(run(min_item, max_item))
loop.run_until_complete(future)
write_log.close()
There are several things that you could do:
- Reuse connection. According to the benchmark below it is about 3 times faster
- You can scrape in multiple processes in parallel
Parallel code from here
from threading import Thread
from Queue import Queue
q = Queue(concurrent * 2)
for i in range(concurrent):
t = Thread(target=doWork)
t.daemon = True
t.start()
try:
for url in open('urllist.txt'):
q.put(url.strip())
q.join()
except KeyboardInterrupt:
sys.exit(1)
Timings from this question for reusable connection
>>> timeit.timeit('_ = requests.get("https://www.wikipedia.org")', 'import requests', number=100)
Starting new HTTPS connection (1): www.wikipedia.org
Starting new HTTPS connection (1): www.wikipedia.org
Starting new HTTPS connection (1): www.wikipedia.org
...
Starting new HTTPS connection (1): www.wikipedia.org
Starting new HTTPS connection (1): www.wikipedia.org
Starting new HTTPS connection (1): www.wikipedia.org
52.74904417991638
>>> timeit.timeit('_ = session.get("https://www.wikipedia.org")', 'import requests; session = requests.Session()', number=100)
Starting new HTTPS connection (1): www.wikipedia.org
15.770191192626953
You can improve your code on two aspects:
Using a
Session
, so that a connection is not re-arranged at every request and is kept open;Using parallelism in your code with
asyncio
;
Give a look here https://pawelmhm.github.io/asyncio/python/aiohttp/2016/04/22/asyncio-aiohttp.html