• 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

+1 głos
266 wizyt
pytanie zadane 6 września 2022 w Python przez AnimaVillis Stary wyjadacz (13,410 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 (256,600 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 (13,410 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 (256,600 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 (13,410 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 (256,600 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 (13,410 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 (13,410 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 223 wizyt
pytanie zadane 19 kwietnia 2020 w C i C++ przez amtrax Dyskutant (9,630 p.)
0 głosów
1 odpowiedź 197 wizyt

93,427 zapytań

142,421 odpowiedzi

322,648 komentarzy

62,787 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

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
...