<jupyter_start><jupyter_text>Warsztaty Python w Data Science--- Web Scraping - część 1 z 2  -  Budowa web crawlera -  Anatomia pająka -  Zarządzanie granicą (*Crawling Frontier*) -  Jak scrapować etycznie i bezpiecznie-  Anatomia strony WWW -  HTML jaki jest - każdy widzi -  Parsowanie pobranych danych-  Prosty, praktyczny scraper---  Budowa (web) crawlera*Web crawler, webbot, pająk, spiderm pełzacz, web crawler, web wanderer, scraper* - program zbierający informacje o strukturze i treściach stron WWW. Używany najczęściej do  Anatomia pająka *pająk* - to program który:- odwiedzają linki ze listy określanej jako granica (*the frontier*)- z odwiedzonych stron wyciąga i zapisuje informacje  - w szczególności dalsze linki (web indexing)  - odpowiednie linki uzupełniają *granicę* crawlingu  - informację w sposób trwały zapisuje web scraper   Zarządzanie granicą (*Crawling Frontier*)- Zakres granicy powinien być ZAWSZE na początku określony    - najlepiej z góry zawężony do określonej liczby i typu linków- Granica winna być mocno ograniczana- Granica rozbudowywana powinna być BARDZO selektywnie- Duża granica powoduje problemy skali --- Jak scrapować etycznie i bezpiecznie 1. Po pierwsze - nie szkodzić! Nie obciążaj niepotrzebnie strony scrapowanej2. Przestrzegaj `robots.txt` i warunków korzystania z usługi3. Miej na uwadze, że bazy danych są chronione na podstawie przepisów ustawy o ochronie baz danych 4. Przestrzegaj RODO5. Nie ukrywaj się6. Gdzie to możliwe,  korzystaj z API---  art. 8 ustawy z dnia 27 lipca 2001 r. o ochronie baz danych (Dz.U. Nr 28, poz. 1402 ze zm.) 1. Wolno korzystać z istotnej, co do jakości lub ilości, części rozpowszechnionej bazy danych:  1)   do własnego użytku osobistego, ale tylko z zawartości nieelektronicznej bazy danych,  2)   w charakterze ilustracji, w celach _**dydaktycznych lub badawczych**_ (podkreslenie moje), ze wskazaniem źródła, jeżeli takie korzystanie jest uzasadnione niekomercyjnym celem, dla którego wykorzystano bazę,    3)   do celów bezpieczeństwa wewnętrznego, postępowania sądowego lub administracyjnego.2. Nie jest dozwolone powtarzające się i systematyczne pobieranie lub wtórne wykorzystanie sprzeczne z normalnym korzystaniem i powodujące nieusprawiedliwione naruszenie słusznych interesów producenta.---  Anatomia strony WWW HTML jaki jest - każdy widzi<jupyter_code>html_doc = """
<html>
<head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
    <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
    <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
    <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
    and they lived at the bottom of a well.</p>

<p class="story">...</p>
</body></html>
"""<jupyter_output><empty_output><jupyter_text>--- Parsowanie pobranych danych<jupyter_code>from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, 'html.parser')

print(soup.prettify())<jupyter_output><empty_output><jupyter_text>--- HTML ma- strukturę drzewiastą- znaczniki się zagnieżdzają i mają mieć (w teorii):  - `` - początek  - `` - koniec- pomiędzy początkiem a końcem są tzw. dzieci- znaczniki nie mogą się "zazębiac" np. `` (w teorii ...)- znaczniki mają atrybuty - np. `Tu jest link---<jupyter_code>from bs4 import BeautifulSoup
import lxml
soup = BeautifulSoup(html_doc, 'lxml')
soup.p
soup.p['class']
soup.a<jupyter_output><empty_output><jupyter_text>Szukanie po znaczniku<jupyter_code>soup.find_all('a')<jupyter_output><empty_output><jupyter_text>Szukanie po id<jupyter_code>soup.find(id="link3")<jupyter_output><empty_output><jupyter_text>Wyciąganie atrybutów<jupyter_code>[ link.get('href') for link in soup.find_all('a')]<jupyter_output><empty_output><jupyter_text>Wędrowanie po drzewie<jupyter_code>soup.a
soup.a.find_next_sibling("a")
soup.p
soup.p.find_next_sibling("p")
pn=soup.p.find_next_sibling("p")
children = pn.children
children
lista = [ x for x in children ]
lista
lista[1].get('href')
head_tag = soup.head
head_tag
for child in head_tag.children:
    print(child)
for child in head_tag.descendants:
    print(child)
last_a_tag = soup.find("a", id="link3")
last_a_tag

last_a_tag.next_sibling
last_a_tag.next_element
last_a_tag.parent<jupyter_output><empty_output><jupyter_text>Szukanie przy użyciu predykatu (funckji logicznej)<jupyter_code>def has_class_but_no_id(tag):
    return tag.has_attr('class') and not tag.has_attr('id')

soup.find_all(has_class_but_no_id)
soup.find_all(id='link2')
soup.find_all("a", class_="sister")
soup.find_all("a")
soup("a")<jupyter_output><empty_output><jupyter_text>--- Prosty, praktyczny scraper<jupyter_code>import requests
from bs4 import BeautifulSoup
import pandas as pd
import time


frontier = [ f'https://www.gumtree.pl/s-mieszkania-i-domy-do-wynajecia/warszawa/page-{n}/v1c9008l3200008p{n}' for n in range(3) ]
data = {'title': [], 'link':[]}
    
for url in frontier:
    time.sleep(1)
    page = requests.get(url)
    print (page)

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


frontier = [ f'https://www.gumtree.pl/s-mieszkania-i-domy-do-wynajecia/warszawa/page-{n}/v1c9008l3200008p{n}' for n in range(3) ]
data = {'title': [], 'link':[]}
    
for url in frontier:
    time.sleep(1)
    page = requests.get(url)
    soup = BeautifulSoup(page.content, 'html.parser')
    titles = [flat.next_element for flat in soup.find_all('a', class_ = "href-link tile-title-text")] 
    print(titles)
import requests
from bs4 import BeautifulSoup
import pandas as pd
import time

frontier = [ f'https://www.gumtree.pl/s-mieszkania-i-domy-do-wynajecia/warszawa/page-{n}/v1c9008l3200008p{n}' for n in range(3) ]
data = {'title': [], 'link':[]}
    
for url in frontier:
    time.sleep(1)
    page = requests.get(url)
    soup = BeautifulSoup(page.content, 'html.parser')
    titles = [flat.next_element for flat in soup.find_all('a', class_ = "href-link tile-title-text")] 
    links = ['https://www.gumtree.pl' + link.get('href')
                for link in soup.find_all('a', class_ ="href-link tile-title-text")]
    print(links)

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

frontier = [ f'https://www.gumtree.pl/s-mieszkania-i-domy-do-wynajecia/warszawa/page-{n}/v1c9008l3200008p{n}' for n in range(3) ]
data = {'title': [], 'link':[]}
    
for url in frontier:
    time.sleep(1)
    page = requests.get(url)
    soup = BeautifulSoup(page.content, 'html.parser')
    titles = [flat.next_element for flat in soup.find_all('a', class_ = "href-link tile-title-text")] 
    links = ['https://www.gumtree.pl' + link.get('href')
                for link in soup.find_all('a', class_ ="href-link tile-title-text")]
    data['link'].extend(links)
    data['title'].extend(titles)
print(data)
import pandas as pd
df = pd.DataFrame(data).drop_duplicates()
df.head(100)
df.to_csv("./gumtree_all_pages.csv", sep=';',index=False, encoding = 'utf-8')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12292077812235692, 'fraction_numerical': 0.013955455314350156, 'mean_word_length': 4.87821043910522, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 59, 'https://': 6, 'lorem ipsum': 0, 'www.': 6, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '201098', 'license': 'Unlicense', 'n_tokens_mistral': 2874, 'n_tokens_neox': 2864, 'n_words': 660, 'path': '08.Web_Scraping_1z2.ipynb', 'repo_name': 'MichalKorzycki/PythonDataScience', 'size': '7094'}