Python BeautifulSoup страница развернуть - PullRequest
0 голосов
/ 12 апреля 2019

У меня есть скрипт Python, который извлекает информацию со страницы Amazon, используя список ключевых слов, хранящихся в файле .txt.У меня есть почти вся информация, которая мне нужна на странице ниже: 'https://www.amazon.co.uk/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords={a}'.format(a=keyword)

Недостающий бит - это информация о продавце (например, ZETA), по которой мне нужно перейти на все страницы продукта, так какодин ниже: https://www.amazon.co.uk/Stroller-Pushchair-Colours-Available-Raincover/dp/B073B2D7CL/ref=sr_1_9?keywords=Pushchair&qid=1555063828&s=gateway&sr=8-9

Я думаю, мне нужен цикл while внутри функции get_data, но я не уверен, как это реализовать.Ниже приведен код:

from bs4 import BeautifulSoup
import time
from selenium import webdriver
import re
import datetime
from collections import deque
import logging
import csv


class AmazonScaper(object):

def __init__(self,keywords, output_file='example.csv',sleep=2):

    self.browser = webdriver.Chrome(executable_path='chromedriver.exe')  #Add path to your Chromedriver
    self.keyword_queue = deque(keywords)  #Add the start URL to our list of URLs to crawl
    self.output_file = output_file
    self.sleep = sleep
    self.results = []


def get_page(self, keyword):
    try:
        self.browser.get('https://www.amazon.co.uk/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords={a}'.format(a=keyword))
        return self.browser.page_source
    except Exception as e:
        logging.exception(e)
        return

def get_soup(self, html):
    if html is not None:
        soup = BeautifulSoup(html, 'lxml')
        return soup
    else:
        return

def get_data(self,soup,keyword):

    try:
        results = soup.select('.s-result-list [data-asin]')
        for a, b in enumerate(results):
            soup = b
            header = soup.find('h5')
            result = a + 1
            title = header.text.strip()
            try:
                link = soup.find('a', attrs={'class': 'a-link-normal a-text-normal'})
                url = link['href']
                url = re.sub(r'/ref=.*', '', str(url))
            except:
                url = "None"

            # Extract the ASIN from the URL - ASIN is the breaking point to filter out if the position is sponsored

            ASIN = re.sub(r'.*/dp/', '', str(url))

            # Extract Score Data using ASIN number to find the span class
            #<span class="a-icon-alt">4.3 out of 5 stars</span>

            try:
                score = soup.select_one('.a-icon-alt')
                score = score.text
                score = score.strip('\n')
                score = re.sub(r' .*', '', str(score))
            except:
                score = "None"

            # Extract Number of Reviews in the same way
            try:
                reviews = soup.select_one("href*='#customerReviews']")
                reviews = reviews.text.strip()
            except:
                reviews = "None"

            # And again for Prime

            try:
                PRIME = soup.select_one('[field-lbr_brands_browse-bin=*"]')
                PRIME = PRIME['field-lbr_brands_browse-bin']
                #<i class="a-icon a-icon-prime" role="img" aria-label="Amazon Prime"></i>
            except:
                PRIME = "None"

            try:
                seller = ""
                seller = ""
            except:
                seller = "None"

            data = {keyword:[keyword,str(result),seller,title,ASIN,score,reviews,PRIME,datetime.datetime.today().strftime("%B %d, %Y")]}
            self.results.append(data)

    except Exception as e:
        print(e)

    return 1

def csv_output(self):
    keys = ['Keyword','Rank','seller','Title','ASIN','Score','Reviews','Prime','Dates']
    print(self.results)
    with open(self.output_file, 'a', encoding='utf-8') as outputfile:
        dict_writer = csv.DictWriter(outputfile, keys)
        dict_writer.writeheader()
        for item in self.results:
            for key,value in item.items():
                print(".".join(value))
                outputfile.write(",".join('"' + item + '"' for item in value)+"\n") # Add "" quote character so the CSV accepts commas

def run_crawler(self):
    while len(self.keyword_queue): #If we have keywords to check
        keyword = self.keyword_queue.popleft() #We grab a keyword from the left of the list
        html = self.get_page(keyword)
        soup = self.get_soup(html)
        time.sleep(self.sleep) # Wait for the specified time
        if soup is not None:  #If we have soup - parse and save data
            self.get_data(soup,keyword)
    #self.browser.quit()
    self.csv_output() # Save the object data to csv


if __name__ == "__main__":
    keywords = [str.replace(line.rstrip('\n'),' ','+') for line in 
open('keywords.txt')] # Use our file of keywords & replaces spaces with +
    ranker = AmazonScaper(keywords) # Create the object
    ranker.run_crawler() # Run the rank checker

Ответы [ 2 ]

0 голосов
/ 12 апреля 2019

Я почти у цели. Переменная URL содержит путь после https://www.amazon.co.uk/ (например, Red-Kite-Baby-Push-Midnight / dp / B01LCSYYJQ). Приведенный ниже код извлекает продавца из одного закодированного URL-адреса. Теперь мне нужно только перебрать все страницы. У меня есть 2 дня опыта в Python, поэтому любая помощь приветствуется!

url = 'https://www.amazon.co.uk/Red-Kite-Baby-Push-Midnight/dp/B01LCSYYJQ'

driver.get(url)
soup = BeautifulSoup(driver.page_source, 'lxml')

try:
    sellers = soup.select("a[id^=bylineInfo]")  # id starts with 'bylineInfo'
except:
    sellers = "None"
print(sellers[0].text.strip())
0 голосов
/ 12 апреля 2019
  1. На странице поиска каждый элемент поиска содержится в тегах, таких как:

    <div data-asin="B0089TV3CS" data-index="1" class="sg-col-4-of-24 sg-col-4-of-12 sg-col-4-of-36 s-result-item sg-col-4-of-28 sg-col-4-of-16 AdHolder sg-col sg-col-4-of-20 sg-col-4-of-32" data-cel-widget="search_result_1">
    

Посмотрите вправо в конец строки выше.Вы можете увидеть шаблон, которому следуют все результаты поиска.Таким образом, вы можете использовать поиск регулярных выражений в тегах div с атрибутами класса, например:

    search_results = soup.findall("div", {"data-cel-widget": re.compile(r"search_result_\d")})

Теперь вы можете просматривать все результаты поиска и извлекать ссылки на отдельные страницы продукта, отмечая, что ссылки содержатся в тегах, таких как:

<a class="a-link-normal a-text-normal" href="/Sterling-Necklace-Infinity-Pendant-Jewellery/dp/B07BPSPD14/ref=sr_1_8?keywords=cross&amp;qid=1555066092&amp;s=gateway&amp;sr=8-8">

Я не знаком с селеном, но если бы я использовал модуль requests, я бы использовал его для загрузки каждой страницы продукта в цикле, создания из него BeautifulSoup, а затем поиска следующего тега, гдеинформация о продавце содержится:

<a id="bylineInfo" class="a-link-normal" href="/ZETA/b/ref=bl_dp_s_web_1658218031?ie=UTF8&amp;node=1658218031&amp;field-lbr_brands_browse-bin=ZETA">ZETA</a>

...