• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Python Scrapper wysyła kilka takich samych linków po porównaniu

Object Storage Arubacloud
+1 głos
168 wizyt
pytanie zadane 6 września 2022 w Python przez AnimaVillis Stary wyjadacz (11,510 p.)

Witam,

Napisałem sobie scrapper bo ten co miałem w php zaczął świrować.

from urllib.request import Request, urlopen
from bs4 import BeautifulSoup as soup
import re
import json
import requests
import time

plik_json = open('')
oferty_weryfikacja = json.loads(plik_json.read())

def send_to_telegram(message):

    apiToken = ''
    chatID = ''
    apiURL = f''
    urlstrony = ''

    try:
        response = requests.post(apiURL, json={'chat_id': chatID, 'text': urlstrony+message})
        print(response.text)
    except Exception as e:
        print(e)


url = ''
req = Request(url , headers={'User-Agent': 'Mozilla/5.0'})
webpage = urlopen(req).read()
page_soup = soup(webpage, "html.parser")
s = page_soup.find('div', id= 'wrapper')
li_ofert = s.find('ul', id='gallery-grid')
oferty = li_ofert.find_all('li')

oferty_tablica = []
z = 0
for oferta in oferty:
    oferta_szczegoly = {}
    oferta_szczegoly['link'] = oferta.get('data-gallery_href')
    oferta_szczegoly['id'] = re.findall(r'_(\d{6})', oferta_szczegoly['link'])
    oferty_tablica.append(oferta_szczegoly)
    z = z + 1
    if z > 4: break

x = 0

while x < 4:
    if oferty_tablica[x]['id'] != oferty_weryfikacja[x]['id']:
         send_to_telegram(oferty_tablica[x]['link'])
    x = x + 1

time.sleep(3)

with open("", "w") as outfile:
    json.dump(oferty_tablica, outfile, indent=2, sort_keys=False)
    time.sleep(3)

Sam scrapper działa idealnie, ale potrafi mi wysłać 2/3 razy taką samą wiadomość z tym samym linkiem, czyli ogłoszenie, które się powtarza, dlaczego?

1 odpowiedź

0 głosów
odpowiedź 6 września 2022 przez VBService Ekspert (253,280 p.)
wybrane 6 września 2022 przez AnimaVillis
 
Najlepsza

Moim zdaniem problem jest w tym miejscu

while x < 4:
    if oferty_tablica[x]['id'] != oferty_weryfikacja[x]['id']:
         send_to_telegram(oferty_tablica[x]['link'])
    x = x + 1

 

z kodu poniżej powinien być tylko "wysłany" link o id555, a tak nie jest
[ on-line ]

oferty_weryfikacja = [
    { "id": 111, "link": "link1" },
    { "id": 222, "link": "link2" },
    { "id": 333, "link": "link3" },
    { "id": 444, "link": "link4" }    
]
oferty_tablica = [
    { "id": 222, "link": "link2" },
    { "id": 111, "link": "link1" },
    { "id": 555, "link": "link5" },
    { "id": 444, "link": "link4" }     
]

def send_to_telegram(message):
    print(message)

x = 0
while x < 4:
    if oferty_tablica[x]['id'] != oferty_weryfikacja[x]['id']:
        send_to_telegram(oferty_tablica[x]['link'])
    x = x + 1

bo sprawdzasz wartości 1 : 1, czyli

index 0 z oferty_tablica i index 0 z oferty_weryfikacja
index 1 z oferty_tablica i index 1 z oferty_weryfikacja itd.

 

musisz wykluczyć te elementy z oferty_tablica, które już znajdują się w oferty_weryfikacja

przykład  [ on-line ]

oferty_weryfikacja = [  # oferty już wcześniej wysłane
    { "id": 111, "link": "link1" },
    { "id": 222, "link": "link2" },
    { "id": 333, "link": "link3" },
    { "id": 444, "link": "link4" }    
]
oferty_tablica = [      # oferty pobrane ze strony
    { "id": 222, "link": "link2" },
    { "id": 111, "link": "link1" },
    { "id": 555, "link": "link5" },
    { "id": 444, "link": "link4" }     
]

def send_to_telegram(message):
    print(message)

oferty_tablica = [ elem for elem in oferty_tablica if elem not in oferty_weryfikacja ]
for i in range(len(oferty_tablica)):
    send_to_telegram(oferty_tablica[i]['link'])

lub  [ on-line ]

oferty_weryfikacja = [
    { "id": 111, "link": "link1" },
    { "id": 222, "link": "link2" },
    { "id": 333, "link": "link3" },
    { "id": 444, "link": "link4" }    
]
oferty_tablica = [
    { "id": 222, "link": "link2" },
    { "id": 111, "link": "link1" },
    { "id": 555, "link": "link5" },
    { "id": 444, "link": "link4" }     
]

def send_to_telegram(message):
    print(message)

def clear_to_unique(list1, list2):
    return list(filter(lambda element: element not in list2, list1))

# lub     
# clear_to_unique = lambda list1, list2: list(filter(lambda element: element not in list2, list1))

for row in clear_to_unique(oferty_tablica, oferty_weryfikacja):
    send_to_telegram(row['link'])

 

komentarz 6 września 2022 przez AnimaVillis Stary wyjadacz (11,510 p.)
edycja 6 września 2022 przez AnimaVillis

Już patrzę jak to się zachowa bo w sumie to ma sens

edit: Sprawdziłem, ale jest taki problem, że zawsze z wynikami jest jeden pozytywny mimo, że id z pobieranej strony się nie zmieniło a w pliku json też on jest :(

Wypróbowałem oba sposoby, zawsze jakiś link przejdzie niestety.

Jeżeli to pomoże to tak mi generuje json:

[
  {
    "link": "/volvo-volvo-fm9-4x2-skap-bg-lyft-2005_926389.html",
    "id": [
      "926389"
    ]
  },
  {
    "link": "/40-50-60-cm_925532.html",
    "id": [
      "925532"
    ]
  },
  {
    "link": "/garderob-405060-cm_925531.html",
    "id": [
      "925531"
    ]
  },
  {
    "link": "/gustavsberg-toaletter-och-handfat_925470.html",
    "id": [
      "925470"
    ]
  },
  {
    "link": "/godkanda-100-st_926865.html",
    "id": [
      "926865"
    ]
  }
]

Całość po wklejeniu kodu od Ciebie:

from urllib.request import Request, urlopen
from bs4 import BeautifulSoup as soup
import re
import json
import requests
import time

plik_json = open('oferty.json')
oferty_weryfikacja = json.loads(plik_json.read())

def send_to_telegram(message):

    apiToken = ''
    chatID = '-'
    apiURL = f''
    urlstrony = ''

    try:
        response = requests.post(apiURL, json={'chat_id': chatID, 'text': urlstrony+message})
        print(response.text)
    except Exception as e:
        print(e)


url = ''
req = Request(url , headers={'User-Agent': 'Mozilla/5.0'})
webpage = urlopen(req).read()
page_soup = soup(webpage, "html.parser")
s = page_soup.find('div', id= 'wrapper')
li_ofert = s.find('ul', id='gallery-grid')
oferty = li_ofert.find_all('li')

oferty_tablica = []
z = 0
for oferta in oferty:
    oferta_szczegoly = {}
    oferta_szczegoly['link'] = oferta.get('data-gallery_href')
    oferta_szczegoly['id'] = re.findall(r'_(\d{6})', oferta_szczegoly['link'])
    oferty_tablica.append(oferta_szczegoly)
    z = z + 1
    if z > 4: break
    
def clear_to_unique(list1, list2):
    return list(filter(lambda element: element not in list2, list1))
 
for row in clear_to_unique(oferty_tablica, oferty_weryfikacja):
    send_to_telegram(row['link'])

with open("oferty.json", "w") as outfile:
    json.dump(oferty_tablica, outfile, indent=2, sort_keys=False)
    time.sleep(3)

 

komentarz 6 września 2022 przez VBService Ekspert (253,280 p.)
edycja 6 września 2022 przez VBService

Tu jest "dziwny" zapis, skoro numer id ma być jeden, a zapisywany jest jako 1-no elementowa lista

"id": [
      "926389"
    ]

dobrze by było jakby był w takiej formie

"id": "926389"

taki Mi się wydaje, że to może sprawiać problem, przy usuwaniu duplikatów.

 

Ten kod zwraca id jako listę ( re.findall() )

oferta_szczegoly['id'] = re.findall(r'_(\d{6})', oferta_szczegoly['link'])

 

komentarz 6 września 2022 przez AnimaVillis Stary wyjadacz (11,510 p.)
On wyszukuje z linku ciąg 6 liczb bo to jest id, jakieś konkretne rozwiązanie proponujesz?
komentarz 6 września 2022 przez VBService Ekspert (253,280 p.)

Domyśliłem się, że re (pattern: \d{6} ) to jest coś w stylu regexp, a regexp zwraca grupy pasujące, a że tu występuję jeden pasujący stąd mamy listę 1-no elementową, może tak po prostu

oferta_szczegoly['id'] = re.findall(r'_(\d{6})', oferta_szczegoly['link'])[0]

pierwszy element z listy

1
komentarz 6 września 2022 przez AnimaVillis Stary wyjadacz (11,510 p.)

Okej, wygląda to teraz tak jak napisałeś na przykładach, ale przy 3/4 uruchomieniu dalej to samo, niestety ID, które już jest dalej wyświetla jako nowe, dodałem do ifa i po kilku uruchomieniach jest ok, zobaczę jak na dalszą metę. Dziękuję za pomoc :)

komentarz 7 września 2022 przez AnimaVillis Stary wyjadacz (11,510 p.)

@VBService, niestety efekt ten sam :/ Przychodzą wiadomości o tych samych linkach i id a nowego niet

Podobne pytania

0 głosów
0 odpowiedzi 152 wizyt
pytanie zadane 19 kwietnia 2020 w C i C++ przez amtrax Dyskutant (9,630 p.)
0 głosów
1 odpowiedź 114 wizyt

92,567 zapytań

141,420 odpowiedzi

319,615 komentarzy

61,952 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...