Проблема / Ошибка с очисткой во фрейме данных Pandas с BeautifulSoup - PullRequest
0 голосов
/ 13 июня 2019

Я работаю над этим CSV (https://www.kaggle.com/jtrofe/beer-recipes) и хочу очистить каждый URL во фрейме данных, но не могу, потому что у меня проблема / ошибка, я не могу очистить все URL, если я попробую с 1 URL, все в порядке, но с функцией есть проблема ... кто-то может мне помочь?

Это мой код:

import requests
from bs4 import BeautifulSoup
from time import sleep 


headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36'
}

base = 'https://www.brewersfriend.com'
links = [f'{base}{r}' for r in df['URL']]

while True:
    try:
        r = requests.get(links, headers=headers, stream=False, timeout=8).text
        break
    except:
        if r.status_code == 404:
            print("Client error")
            r.raise_for_status()
        sleep(1)


soup = BeautifulSoup(r, 'html5lib')

rating = soup.find('span', {'itemprop': 'ratingValue'})

DEFAULT_VALUE = 'NaN'

if rating is None:
    rating = DEFAULT_VALUE
    
print(rating.text)

Я уже знаю, что на некоторых страницах нет рейтинга, поэтому я создаю DEFAULT_VALURE с параметром Not a Number, но, возможно, это тоже ошибка.

До этого кода есть фрейм данных, но я тоже не помещаю его.

Я надеюсь, что кто-то может мне помочь!

Большое спасибо

Ответы [ 2 ]

0 голосов
/ 14 июня 2019

Вот способ сделать весь процесс

import requests, re
import pandas as pd
from bs4 import BeautifulSoup as bs

p = re.compile(r'dataviewToken":"(.*?)"')
p1 = re.compile(r'"rowCount":(\d+)')
results = []
i = 0

with requests.Session() as s:
    r = s.get('https://www.kaggle.com/jtrofe/beer-recipes')   
    token = p.findall(r.text)[0]
    rows = int(p1.findall(r.text)[0])
    data = {"jwe":{"encryptedToken": token},"source":{"type":3,"dataset":{"url":"jtrofe/beer-recipes","tableType":1,"csv":{"fileName":"recipeData.csv","delimiter":",","headerRows":1}}},"select":["BeerID","Name","URL","Style","StyleID","Size(L)","OG","FG","ABV","IBU","Color","BoilSize","BoilTime","BoilGravity","Efficiency","MashThickness","SugarScale","BrewMethod","PitchRate","PrimaryTemp"],"skip":0,"take": rows}
    base = 'https://www.brewersfriend.com'
    r = s.post('https://www.kaggleusercontent.com/services/datasets/kaggle.dataview.v1.DataViewer/GetDataView', json = data).json()
    names, links = zip(*[(row['text'][1], base + row['text'][2]) for row in r['dataView']['rows']])

    for link in links:
        r = s.get(link, headers = {'User-Agent' : 'Mozilla/5.0'})
        if r.status_code == 403:
            rating = 'N/A'
        else:
            soup = bs(r.content, 'lxml')
            rating = soup.select_one('[itemprop=ratingValue]')
            if rating is None:
                rating = 'N/A'
            else:
                rating = rating.text
        row = [names[i], rating]
        results.append(row)
        i+=1

df = pd.DataFrame(results, columns = ['Name', 'Rating'])
print(df.head())
df.to_csv(r'C:\Users\User\Desktop\Data.csv', sep=',', encoding='utf-8-sig',index = False )
0 голосов
/ 13 июня 2019

Все виды грязных вещей здесь.Я не буду проходить через все это, но я вижу одно, что вы пытаетесь print (rating.text).Если ваш рейтинг равен 'NaN', одна ошибка состоит в том, что вы не можете сделать rating.text

Это не то, как я бы это написал, а отклонение от вашей первоначальной кодировки:

import pandas as pd
import requests
from bs4 import BeautifulSoup
from time import sleep 


df = pd.read_csv('C:/recipeData/recipeData.csv', encoding = 'ISO-8859-1')
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36'}
base = 'https://www.brewersfriend.com'

links = [f'{base}{r}' for r in df['URL']]
for link in links:
    try:
        r = requests.get(link, headers=headers, stream=False, timeout=8)

        if r.status_code == 404:
            print("Client error")
            r.raise_for_status()
            continue
        else:
            r = r.text     
    except:
        continue


    soup = BeautifulSoup(r, 'html5lib')
    rating = soup.find('span', {'itemprop': 'ratingValue'}).text
    DEFAULT_VALUE = 'NaN'

    if rating is None:
        rating = DEFAULT_VALUE

    print('%s: %s' %(link,rating))
...