2017-09-21 1 views
3

gerade begann Web Scraping in Python und ich habe ein paar Probleme.BeautifulSoup und lxml kann div Element nicht finden

Ich begann Selen mit einer Webseite Quelle herunterzuladen und zu speichern:

from selenium import webdriver 
driver= webdriver.Firefox() 
driver.get("https://www.website.com") 
f=open('output.txt','w') 
f.write(driver.page_source.encode('utf-8')) 
f.close() 
driver.quit() 

Alles funktionierte gut, aber Selen nimmt zu viel Zeit, so wandte ich mich zuerst, mechanisieren der Seite Quelle zu erhalten:

import mechanize 
browser = mechanize.Browser() 
browser.set_handle_robots(False) 
cookies = mechanize.CookieJar() 
browser.set_cookiejar(cookies) 
browser.addheaders = [('User-agent', 'Mozilla/5.0')] 
browser.set_handle_refresh(False) 
browser.open("https://www.website.com") 

Hier kommt das Problem: wenn ich versuche, eine bestimmte div finden, indem es die id, es gibt mir keine:

from bs4 import BeautifulSoup as BS 
soup= BS(browser.response().read(),'lxml') 
print(soup.find(id="div_id")) 

Obwohl, wenn ich den mit mechanize mit einem normalen Texteditor erhaltenen Quellcode inspiziere, kann ich es finden. Es ist so etwas wie:

<div id="div_id" data referrer="div_id"> 

Dieses div viele andere Kind-Elemente hat, ist es etwa 1/5 „in“ der Code befindet ist, und der komplette Quellcode ist über 500kb.If ich stattdessen versuchen, für andere div in der Nähe suchen, auch kein Glück. Während, wenn ich nach einem div nahe dem Anfang des Quellcodes suche, findet es es.Und was noch interessanter ist, wenn ich versuche, nach dem gleichen div (mit BS) zu suchen, im Quellcode, der mit Selenium erhalten wurde, anstelle des erhaltenen mit Mechanize ist es in der Lage, es zu finden, obwohl das Div durch Überprüfung mit einem Texteditor vollständig identisch ist.

Ich versuchte mit allen von BS unterstützten Parsern, ohne Glück. Also dachte ich, es vielleicht etwas mit BS zu tun hatte, und ich versuchte, das gleiche mit lxml zu tun:

from lxml import etree 
parser= etree.HTMLParser() 
tree= etree.parse(open('source.txt'),parser) 
results= tree.xpath('//div[@id="div_id"]') 
print(etree.tostring(results[0])) 

Wie bei BS, es konnte die div in dem Quellcode mit Selen erhalten finden, aber nicht mit mechanisieren. Also dachte ich, es hat etwas mit Mechanize zu tun haben könnte, und wandte sich Anfragen zu verwenden:

import requests 
from fake_useragent import UserAgent 
ua=UserAgent() 
url= 'https://www.website.com' 
headers= {'User-agent': str(ua.chrome)} 
page = requests.get(url, headers=headers) 

Wenn in page.content für die div sah, mit entweder BS oder lxml, wieder kein luck.It geschieht, ob ich analysieren direkt die Antwort oder ob, wenn ich es in einer Datei speichern und dann die Datei analysieren.

Und ich denke das war es ... Ich habe auch versucht, die Mechanize und Requests Antworten zu codieren, als ich sah, dass ich es mit Selenium gemacht hatte, aber keine Änderung. Ich habe auch versucht, andere BS-Version (3.x), keine Änderung zu verwenden.

Zusammengefasst: - Wenn ich nach dem div mit BS oder lxml in den Quellcode, der über Selenium erhalten wird, suche, findet er es. Mit den anderen, nein. - Wenn ich am Anfang des Quellcodes nach anderen divs suche, finden BS und lxml es unabhängig von der Methode, die verwendet wurde, um den Code zu erhalten. - Bei der Inspektion ist das Div in jedem Fall vorhanden.

verwendet Versionen: -python: 2.7.9 -BeautifulSoup: 4.6.0 -Mechanize: 0.3.5 -Requests: 2.18.4 -Selen: 3.5.0 -lxml: 4.0.0 -OS: linux debian

Danke.

+0

anzeigen Es würde helfen, wenn Sie uns die tatsächliche URL gaben. –

+0

url: https://www.facebook.com/groups/1584160618524185/ div id: pagelet_forsale_island Danke – Bleracas

Antwort

0

Das von Ihnen gesuchte div ist in einem HTML-Kommentar versteckt, der wahrscheinlich über das Javascript verarbeitet wird.Sie könnten noch requests verwenden, um zuerst die versteckten HTML zu extrahieren wie folgt:

from bs4 import BeautifulSoup, Comment 
import requests 

id = "pagelet_forsale_island" 

r = requests.get("https://www.facebook.com/groups/1584160618524185/") 
soup = BeautifulSoup(r.content, "html.parser") 

for comment in soup.find_all(string=lambda text:isinstance(text, Comment)): 
    if id in comment: 
     hidden_soup = BeautifulSoup(comment, "html.parser") 

     for div in hidden_soup.find_all('div', id=id): 
      print div 

Diese BeautifulSoup bekommt alle der Kommentar im HTML zu finden und um dann festzustellen, ob Ihre id enthalten. Wenn eine Übereinstimmung gefunden wird, wird der Kommentar selbst zur weiteren Verarbeitung an BeautifulSoup übergeben. Dies würde Ihre <div> als:

<div data-referrer="pagelet_forsale_island" id="pagelet_forsale_island"></div> 
+0

Das war's! Würde es Ihnen etwas ausmachen zu erklären, wie "für einen Kommentar in soup.find_all (string = Lambda-Text: isinstance (Text, Kommentar)):" funktioniert? Ich bin mir nicht sicher. Und denkst du, dass BS für diese Aufgabe am geeignetsten ist, oder würde mir vielleicht ein anderes Tool besser passen? Vielen Dank! – Bleracas

+0

'Kommentare' sind nur spezielle Arten von Text. Dies ist ein Trick, um alle Kommentare in einem Dokument zurückzugeben. Es gibt andere Werkzeuge, tendiere ich dazu, BS zu verwenden. –

Verwandte Themen