Почему мой веб-скребок работает только половину времени? - PullRequest
1 голос
/ 17 января 2020

Моя цель состоит в том, чтобы получить название продукта и цену всех страниц Amazon, обнаруженных на любом веб-сайте, который я передаю в свою программу.

Мой ввод - это текстовый файл, содержащий пять веб-сайтов. На каждом из этих веб-сайтов можно найти от пяти до пятнадцати ссылок amazon.

Мой код такой:

from simplified_scrapy.request import req
from simplified_scrapy.simplified_doc import SimplifiedDoc
import requests
import re
from bs4 import BeautifulSoup
from collections import OrderedDict
from time import sleep
import time
from lxml import html
import json
from urllib2 import Request, urlopen, HTTPError, URLError

def isdead(url):
    user_agent = 'Mozilla/20.0.1 (compatible; MSIE 5.5; Windows NT)'
    headers = { 'User-Agent':user_agent }
    req = Request(url, headers = headers)
    sleep(10)
    try:
        page_open = urlopen(req)
    except HTTPError, e:
        return e.code #404 if link is broken
    except URLError, e:
        return e.reason
    else:
        return False

def check(url):
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}
    page = requests.get(url, headers = headers)

    doc = html.fromstring(page.content)
    XPATH_AVAILABILITY = '//div[@id ="availability"]//text()'
    RAw_AVAILABILITY = doc.xpath(XPATH_AVAILABILITY)
    AVAILABILITY = ''.join(RAw_AVAILABILITY).strip()
    #re.... is a list. if empty, available. if not, unavailable.
    #return re.findall(r'Available from',AVAILABILITY[:30], re.IGNORECASE)

    if len(re.findall(r'unavailable',AVAILABILITY[:30],re.IGNORECASE)) == 1:
        return "unavailable"
    else:
        return "available"


file_name = raw_input("Enter file name: ")
filepath = "%s"%(file_name)

with open(filepath) as f:
    listoflinks = [line.rstrip('\n') for line in f]

all_links = []
for i in listoflinks:
    htmls = req.get(i)
    doc = SimplifiedDoc(htmls)
    amazon_links = doc.getElements('a')
    amazon_links = amazon_links.containsOr(['https://www.amazon.com/','https://amzn.to/'],attr='href')
    for a in amazon_links:
        if a.href not in all_links:
            all_links.append(a.href)

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}

all_links = [x for x in all_links if "amazon.com/gp/prime" not in x]
all_links = [y for y in all_links if "amazon.com/product-reviews" not in y]
for i in all_links:
    print "LINK:"
    print i
    response = requests.get(i, headers=headers)
    soup = BeautifulSoup(response.content, features="lxml")

    if isdead(i) == 404:
        print "DOES NOT EXIST"
        print "/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/"
        pass
    else:
        title = soup.select("#productTitle")[0].get_text().strip()
        if check(i) == "unavailable":
            price = "UNAVAILABLE"
        else:
            if (len(soup.select("#priceblock_ourprice")) == 0) and (len(soup.select("#priceblock_saleprice")) == 0):
                price = soup.select("#a-offscreen")
            elif len(soup.select("#priceblock_ourprice")) == 0:
                price = soup.select("#priceblock_saleprice")
            else:
                price = soup.select("#priceblock_ourprice")

        print "TITLE:%s"%(title)
        print "PRICE:%s"%(price)
        print "/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/"

print "..............................................."
print "FINALLY..."
print "# OF LINKS RETRIEVED:"
print len(all_links)

Всякий раз, когда все работает нормально, вывод выглядит примерно так (пожалуйста, не судите о выводе PRICE, я потратил так много времени, пытаясь это исправить, но ничего не работает, потому что я не могу превратить его в строку, а get_text () не работает. Этот проект предназначен только для личного использования. это не так важно, но если у вас есть предложения, я очень восприимчив к ним.):

LINK:
https://www.amazon.com/dp/B007Y6LLTM/ref=as_li_ss_tl?ie=UTF8&linkCode=ll1&tag=lunagtkf1-20&linkId=ee8c5299508af57c815ea6577ede4244
TITLE:Moen 7594ESRS Arbor Motionsense Two-Sensor Touchless One-Handle Pulldown Kitchen Faucet Featuring Power Clean, Spot Resist Stainless
PRICE:[<span class="a-size-medium a-color-price priceBlockBuyingPriceString" id="priceblock_ourprice">$359.99</span>]
/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/

... и так далее. Ошибка выглядит следующим образом:

Traceback (most recent call last):
File "name.py", line 75, in <module>
title = soup.select("#productTitle")[0].get_text().strip()
IndexError: list index out of range

Это так странно, потому что есть текстовый файл, который подается так много раз, а иногда все сайты хорошо очищаются, но иногда ошибка появляется в 10-м продукте Amazon, иногда , ошибка появляется в 1-м продукте ...

Я подозреваю, что это проблема обнаружения бота, но у меня есть заголовок. В чем проблема?

Ответы [ 2 ]

0 голосов
/ 18 января 2020

Вы должны узнать больше :) и привести пример использования фреймворка. Вот еще несколько примеров упрощенной_скрипции здесь

Если вам нужна помощь, пожалуйста, дайте мне знать.

from simplified_scrapy.spider import Spider, SimplifiedDoc
class MySpider(Spider):
  name = 'amazon-product'
  # allowed_domains = ['example.com']
  start_urls = []
  refresh_urls = True # For debug. If efresh_urls = True, start_urls will be crawled again.

  filepath='' # Your file path
  if filepath:
    with open(filepath) as f:
      start_urls = [line.rstrip('\n') for line in f]

  def extract(self, url, html, models, modelNames):
    doc = SimplifiedDoc(html)
    amazon_links=None
    data = None
    if url['url'].find('https://www.amazon.com')>=0 or url['url'].find('https://amzn.to')>=0:
      title = doc.getElementByID("productTitle").text
      if doc.getElementByID('availability') and doc.getElementByID('availability').text.find('unavailable')>0:
        price = "UNAVAILABLE"
      else:
        if doc.getElementByID("priceblock_ourprice"):
          price = doc.getElementByID("priceblock_ourprice").text
        elif doc.getElementByID("priceblock_saleprice"):
          price = doc.getElementByID("priceblock_saleprice").text
        else:
          price = doc.getElementByID("a-offscreen").text

      data = [{"title":title,'price':price}] # Get target data
      print "TITLE:%s"%(title)
      print "PRICE:%s"%(price)
      print "/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/"
    else:
      amazon_links = doc.getElements('a')
      amazon_links = amazon_links.containsOr(['https://www.amazon.com/','https://amzn.to/'],attr='href')
      amazon_links = amazon_links.notContains(['amazon.com/gp/prime','amazon.com/product-reviews'],attr='href')
    return {"Urls": amazon_links, "Data": data} # Return data to framework

from simplified_scrapy.simplified_main import SimplifiedMain
SimplifiedMain.startThread(MySpider()) # Start crawling
0 голосов
/ 18 января 2020

Ваш код слишком грязный. Я организовал это для вас, пожалуйста, проверьте, работает ли он.

from simplified_scrapy.request import req
from simplified_scrapy.simplified_doc import SimplifiedDoc
import requests

file_name = raw_input("Enter file name: ")
filepath = "%s"%(file_name)

with open(filepath) as f:
    listoflinks = [line.rstrip('\n') for line in f]

all_links = []
for i in listoflinks:
    htmls = req.get(i)
    doc = SimplifiedDoc(htmls)
    amazon_links = doc.getElements('a')
    amazon_links = amazon_links.containsOr(['https://www.amazon.com/','https://amzn.to/'],attr='href')
    amazon_links = amazon_links.notContains(['amazon.com/gp/prime','amazon.com/product-reviews'],attr='href')
    for a in amazon_links:
        if a.href not in all_links:
            all_links.append(a.href)

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}

for i in all_links:
    print "LINK:"
    print i
    response = requests.get(i, headers=headers)
    if response.status_code == 404:
        print "DOES NOT EXIST"
        print "/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/"
        pass
    else:
        html = response.text
        doc = SimplifiedDoc(html)
        title = doc.getElementByID("productTitle").text
        if doc.getElementByID('availability') and doc.getElementByID('availability').text.find('unavailable')>0:
            price = "UNAVAILABLE"
        else:
            if doc.getElementByID("priceblock_ourprice"):
                price = doc.getElementByID("priceblock_ourprice").text
            elif doc.getElementByID("priceblock_saleprice"):
                price = doc.getElementByID("priceblock_saleprice").text
            else:
                price = doc.getElementByID("a-offscreen").text

        print "TITLE:%s"%(title)
        print "PRICE:%s"%(price)
        print "/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/"

print "..............................................."
print "FINALLY..."
print "# OF LINKS RETRIEVED:"
print len(all_links)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...