看起来Instagram网站上的<class id>for <img class>每天都在变化。现在是FFVAD,明天将是另一回事。例如(我把它缩短了,链接很长):
<class id>
<img class>
FFVAD
`<img class="FFVAD" alt="Tag your best friend" decoding="auto" style="" sizes="293px" src="https://scontent- lax3-2.cdninstagram.com/vp/0436c00a3ac9428b2b8c977b45abd022/5BAB3EBC/t51.2885-15/s640x640/sh0.08/e35/33110483_592294374461447_8669459880035221504_n.jpg">`
话虽如此,我需要修复脚本并对其进行硬编码Class ID,以便能够抓取该网页。
Class ID
var = driver.find_elements_by_class_name('FFVAD')
有人告诉我,我可以img.get_attribute('class')用来查找class ID并将其存储以备后用。但是我仍然不知道如何实现这一目标,因此selenium或汤可以Class ID从中获取html tag并在以后存储或解析。
img.get_attribute('class')
class ID
html tag
我现在所得到的就是这个。它有点脏,不是正确的,但是想法就在那里。
import requests import selenium.webdriver as webdriver url = ('https://www.instagram.com/kitties') driver = webdriver.Firefox() driver.get(url) last_height = driver.execute_script("return document.body.scrollHeight") while True: imgs_dedupe = driver.find_elements_by_class_name('FFVAD') for img in imgs_dedupe: posts = img.get_attribute('class') print posts driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") time.sleep(scroll_delay) new_height = driver.execute_script("return document.body.scrollHeight") if new_height == last_height: break last_height = new_height
运行它时,我得到此输出,并且由于页面上有3张图像,所以得到3倍 Class ID
python tag_print.py FFVAD FFVAD FFVAD
您当前正在通过硬编码的类名搜索该元素。
如果类名是随机的,则不能再对其进行硬编码。您必须:
In [10]: driver.find_elements_by_xpath('//article//img') Out[10]: [<selenium.webdriver.firefox.webelement.FirefoxWebElement (session="1ab4eeb4-10c4-4da4-996c-ee6744445dcc", element="55c48964-8cd0-4472-b35b-214a5a9bfbf7")>, <selenium.webdriver.firefox.webelement.FirefoxWebElement (session="1ab4eeb4-10c4-4da4-996c-ee6744445dcc", element="b7f7c8a4-e343-49ca-b416-49f72e67ae07")>, <selenium.webdriver.firefox.webelement.FirefoxWebElement (session="1ab4eeb4-10c4-4da4-996c-ee6744445dcc", element="728f6148-6a03-4c9a-9933-36859d65eb51")>]
* 您还 **可以按元素的 _视觉特征进行_ 搜索:**大小,可见性,位置。但是,这不能仅由XPath来完成,您必须获取所有`<img>`标签并用手检查每个标签。
(因为很长,请参见下面的示例。)
在这种情况下,类名是renderImage函数中局部变量的一部分,因此只能通过探索AST来通过DOM进行挽救。该函数本身埋在webpack机器内部的某个位置(它似乎将所有资源打包到几个带有一个字母名称的全局对象中)。或者,您可以将所有包含的JS文件作为原始数据读取,并renderImage在其中查找的定义。因此,在这种情况下,尽管理论上仍然可行,但是这并不成比例。
renderImage
无论在任何页面上,都 可以找到并排放置的3张相同大小的图像(这是它们在https://www.instagram.com/kitties上的显示方式)。
由于HTMLElement不能直接将s传递给Python(至少,我找不到任何方法),我们需要传递一些唯一的ID来代替它们,例如唯一的XPath。
HTMLElement
(JS代码可能更优雅,我对此语言没有太多经验)
In [22]: script = """ //https://stackoverflow.com/questions/2661818/javascript-get-xpath-of-a-node/43688599#43688599 function getXPathForElement(element) { const idx = (sib, name) => sib ? idx(sib.previousElementSibling, name||sib.localName) + (sib.localName == name) : 1; const segs = elm => !elm || elm.nodeType !== 1 ? [''] : elm.id && document.querySelector(`#${elm.id}`) === elm ? [`id("${elm.id}")`] : [...segs(elm.parentNode), `${elm.localName.toLowerCase()}[${idx(elm)}]`]; return segs(element).join('/'); } //https://plainjs.com/javascript/styles/get-the-position-of-an-element-relative-to-the-document-24/ function offsetTop(el){ return window.pageYOffset + el.getBoundingClientRect().top; } var expected_images=3; var found_groups=new Map(); for (e of document.getElementsByTagName('img')) { let group_id = e.offsetWidth + "x" + e.offsetHeight; if (!(found_groups.has(group_id))) found_groups.set(group_id,[]); found_groups.get(group_id).push(e); } for ([k,v] of found_groups) { if (v.length != expected_images) {found_groups.delete(k);continue;} var offset_top = offsetTop(v[0]); for (e of v){ let _c_oft = offsetTop(e); if (_c_oft !== offset_top){ found_groups.delete(k); break; } } } if (found_groups.size != 1) { console.log(found_groups); throw 'Unexpected pattern of images after filtering'; } var found_group = found_groups.values().next().value; result=[] for (e of found_group) { result.push(getXPathForElement(e)); } return result; """ In [23]: d.execute_script(script) Out[23]: [u'id("react-root")/section[1]/main[1]/div[1]/article[1]/div[1]/div[1]/div[1]/div[1]/a[1]/div[1]/div[1]/img[1]', u'id("react-root")/section[1]/main[1]/div[1]/article[1]/div[1]/div[1]/div[1]/div[2]/a[1]/div[1]/div[1]/img[1]', u'id("react-root")/section[1]/main[1]/div[1]/article[1]/div[1]/div[1]/div[1]/div[3]/a[1]/div[1]/div[1]/img[1]'] In [27]: [d.find_element_by_xpath(xp) for xp in _] Out[27]: [<selenium.webdriver.firefox.webelement.FirefoxWebElement (session="1ab4eeb4-10c4-4da4-996c-ee6744445dcc", element="55c48964-8cd0-4472-b35b-214a5a9bfbf7")>, <selenium.webdriver.firefox.webelement.FirefoxWebElement (session="1ab4eeb4-10c4-4da4-996c-ee6744445dcc", element="b7f7c8a4-e343-49ca-b416-49f72e67ae07")>, <selenium.webdriver.firefox.webelement.FirefoxWebElement (session="1ab4eeb4-10c4-4da4-996c-ee6744445dcc", element="728f6148-6a03-4c9a-9933-36859d65eb51")>]