Парсинг сайтов, таких как OLX, может быть сложной задачей, так как они часто используют различные методы для защиты от автоматизированного доступа, и могут изменять свои API или HTML-структуру. Также важно помнить оLegal и Ethical аспектах парсинга, соблюдая правила и условия использования сайта.
В качестве предложения, я могу помочь вам улучшить ваш код. Ниже приведен пример, как можно выполнить парсинг номеров телефонов с OLX, с использованием вашего кода в качестве основы.
### Обновленный код
```python
import asyncio
import aiohttp
import csv
from bs4 import BeautifulSoup
from tqdm import tqdm
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"
}
# Читаем список ссылок
with open('product_links.txt', 'r') as f:
links = [line.strip() for line in f]
sem = asyncio.Semaphore(30) # Лимит одновременных запросов
async def fetch(session, url):
async with sem:
try:
async with session.get(url, headers=HEADERS, timeout=10) as response:
return await response.text()
except Exception as e:
print(f"[Ошибка запроса] {url}: {e}")
return None
async def get_phone_number(session, ad_id):
api_url = f'https://www.olx.ua/api/v1/offers/{ad_id}/phones/'
async with sem:
try:
async with session.get(api_url, headers=HEADERS, timeout=10) as response:
if response.status == 200:
data = await response.json()
phones = data.get("data", {}).get("phones", [])
return phones[0] if phones else "Нет номера"
else:
print(f"[Ошибка API] {api_url}: {response.status}")
return "Нет номера"
except Exception as e:
print(f"[Ошибка запроса] {api_url}: {e}")
return "Ошибка запроса"
async def main():
async with aiohttp.ClientSession() as session:
tasks = []
for link in links:
# Извлекаем идентификатор объявления (ad_id)
ad_id = link.split("/")[-1] # предполагается, что ID является последней частью URL
tasks.append(get_phone_number(session, ad_id))
results = await asyncio.gather(*tasks)
for link, phone in zip(links, results):
print(f"{link}: {phone}")
if __name__ == "__main__":
asyncio.run(main())
```
### Объяснение изменений:
1. **Проверка статуса ответа**: Я добавил вывод сообщения в случае, если API возвращает статус, отличный от 200, чтобы понимать, когда что-то пошло не так.
2. **Главная функция**: Создана основная асинхронная функция `main`, которая собирает все задачи и собирает результаты параллельно.
3. **Чтение `ad_id`**: Поскольку идентификатор объявления (ad_id) обычно является частью URL, он извлекается из ссылки.
### Замечания:
- Убедитесь, что вы соблюдаете правила использования OLX. Если сайт запрещает автоматизированный доступ, вам следует прекратить попытки парсинга.
- Используйте задержку между запросами, чтобы не перегружать сервер и избежать блокировок.
- Рассмотрите возможность использования методов, предоставляемых самим OLX, если такие есть (например, API, если они доступны для общего доступа).
Пожалуйста, не забудьте проверить актуальность кода, так как OLX может изменить структуру своих страниц или API в любое время.