Niestety, web scraping jest ciężki jeśli w dzisiejszych czasach JavaScript ninja. To, co widzisz w przeglądarce, wcale nie równa się temu, co dostałeś w odpowiedzi w requeście. Strona ta ściąga sobie kupę skryptów JavaScript, które następnie pobierają dynamicznie dane z zewnętrznego API i pakuje na stronie. Sam request do https://edition.cnn.com/ zwraca tylko szkielet, który będą wypełniać skrypty. Możesz to sobie sprawdzić próbując zapisać treść strony, co ją właśnie ściągłeś:
source = requests.get('https://edition.cnn.com/').text
with open('/tmp/test.html', 'w') as f:
f.write(source.encode('utf-8'))
Chociaż nie trzeba - od tego maż developer tools i zakładkę networks. Firefox wyświetla mi pogląd tej strony, a jest ona pusta:
Skąd zatem faktyczne dane się biorą? Powiedzmy, że chcę sobie wyszukać te nagłówki "Virus" o tej epidemii w Chinach. Żeby je znaleźć, kliknąłem sobie prawym na tych requestach, wybrałem "Save as HAR', zapisałem w pliku .har (json z danymi requestów) i grepem poszukałem nagłówków - jak się okazuje lecą do API jakieś requesty pokroju https://edition.cnn.com/data/ocs/section/index.html:intl_homepage1-zone-1/views/zones/common/zone-manager.izl
. Prawy klik myszy, copy as curl i można je poprać w konsoli
curl 'https://edition.cnn.com/data/ocs/section/index.html:intl_homepage1-zone-1/views/zones/common/zone-manager.izl' -H 'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:72.0) Gecko/20100101 Firefox/72.0' -H 'Accept: application/json, text/javascript, */*; q=0.01' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Referer: https://edition.cnn.com/' -H 'X-Requested-With: XMLHttpRequest' -H 'Connection: keep-alive' -H 'Cookie: FastAB=0=4293,1=7507,2=4311,3=0945,4=1431,5=2310,6=1345,7=8613,8=1408,9=2452; tryThing01=2130; ajs_user_id=null; ajs_group_id=null; ajs_anonymous_id=%2205f92a2d-c17a-404f-9a13-43b0becaa64b%22; AMCV_7FF852E2556756057F000101%40AdobeOrg=-1303530583%7CMCIDTS%7C18261%7CMCMID%7C91615181573740843924155490946665004935%7CMCAID%7CNONE%7CMCOPTOUT-1577674198s%7CNONE%7CvVersion%7C3.3.0; OptanonConsent=isIABGlobal=true&datestamp=Thu+Jan+23+2020+23%3A09%3A02+GMT%2B0100+(Central+European+Standard+Time)&version=5.11.0&landingPath=NotLandingPage&groups=req%3A1%2Csm%3A1%2Csmv%3A1%2CBG139%3A1%2Cad%3A1%2Cadv%3A1%2CBG137%3A1%2Cpf%3A1%2Cpfv%3A1%2CBG138%3A1%2Cpzv%3A1%2Cpz%3A1%2CBG140%3A1%2Cbb%3A1%2Cbbv%3A1%2CBG141%3A1%2Csa%3A1%2Csav%3A1%2CBG136%3A1&hosts=&consentId=d4affef0-f3d3-45c7-ba2f-369943c45f10&interactionCount=1&AwaitingReconsent=false&geolocation=PL%3B12; countryCode=PL; geoData=krakow|12|31-530|PL|EU|100|broadband; adobeujs-optin=%7B%22aam%22%3Afalse%2C%22adcloud%22%3Afalse%2C%22aa%22%3Atrue%2C%22campaign%22%3Afalse%2C%22ecid%22%3Atrue%2C%22livefyre%22%3Afalse%2C%22target%22%3Afalse%2C%22mediaaa%22%3Afalse%7D; seenBreakingNews=; OptanonAlertBoxClosed=2020-01-23T22:08:57.249Z; OptanonControl=ccc=PL&otvers=5.11.0®=gdpr&vers=1.3.3; AMCV_7FF852E2556756057F000101%40AdobeOrg=1075005958%7CMCIDTS%7C18285%7CMCMID%7C91615181573740843924155490946665004935%7CMCAID%7CNONE%7CMCOPTOUT-1579824544s%7CNONE%7CvVersion%7C4.4.1; AMCVS_7FF852E2556756057F000101%40AdobeOrg=1; cnprevpage_pn=cnn%3Ain%3Aedition%3A%2F; s_cc=true' -H 'Pragma: no-cache' -H 'Cache-Control: no-cache' -H 'TE: Trailers'
Jak widać nasz front nam wpakował w cholerę parametrów. Jakbyśmy musieli się logować na stronie to pewnie trzeba by obsłużyć ciastka. Ale jak się okazuje większość tych parametrów jest nam do niczego potrzebna:
curl 'https://edition.cnn.com/data/ocs/section/index.html:intl_homepage1-zone-1/views/zones/common/zone-manager.izl'
Jak sobie zapisałem do pliku odpowiedź z tego endpointa, to dostałem taką stronę
No! I to już można scrapować.
I tak wygląda właśnie scrapowanie w dzisiejszych czasach, ery ton JavaScriptu i innego dziadostwa. Jak masz szczęście, to request dla endpointu zwraca ci stary, poczciwy HTML z danymi, jakie potrzebujesz. Jak nie to trzeba znaleźć który z requestów lecących w tle zwraca dane, których potrzebujesz, często przy tym dodając odpowiednie nagłówki, zarządzając ciastkami, sesjami, identyfikatorami i innym dziadostwem, parsując JSON-y lub XML-e, czy nawet tłumacząc dane z base64, cały ten stuff które przeglądarka i skrypty robią za ciebie. Zabawa przednia, taki niby reverse erngineering strony, próba zrozumienia jak działa.
Możesz też faktycznie użyć Selenium albo Splash i wyrenderować całą stronę. Dzała to tak, że symuluje prawdziwą przeglądarkę, budując z wspomnianych JavaScriptów normalny output tak jak normalny FF czy Chrome, ale ponieważ musi to wszystko obsłużyć będzie znacznie wolniejszy. Jak chcesz mieć szybkie scrapowanie (bo na przykład zbierasz dane z dziesiątek tysięcy podstron) nie ma to sensu - trzeba wówczas patrząc w Developer Tools dowiedzieć się jakie Requesty i Response'y latają w te i wewte, po czym je ręcznie symulować.