一些网站具有反抓取机制,涉及检测浏览器的webdriver 属性。当您为 Chrome 启用 headless 模式时,浏览器不会设置此属性。从而向网站表明请求的来源是通过机器人或程序。
您可以尝试执行可以在无头模式下为您的浏览器设置webdriver 属性的javascript。
不过,请注意,这只是网站用来检测机器人或程序的众多机制之一。
您也可以查看answer
这是我使用 pyppeteer 库编写的示例代码。
导入异步
从 pyppeteer 导入启动
# from pyvirtualdisplay 导入显示
从 argparse 导入 ArgumentParser
HTMLRetriever 类(对象):
_page_source = 无
_title = 无
def __init__(self, url):
self.url = 网址
异步默认加载(自我):
# 使用 Display(backend='xvfb') 作为显示:
等待 self._init_browser()
等待 self._init_webpage()
等待 self._connect_website()
等待 self._take_snapshot()
@classmethod
异步定义_init_display(cls):
cls.disp = 显示(后端='xvfb')
@classmethod
异步定义_init_browser(cls):
cls.browser = 等待启动(headless=True, args=[
“--无沙盒”,
“--单进程”,
“--禁用-开发-shm-使用”,
“--无合子”,
'--user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"'
])
@classmethod
异步定义_init_webpage(cls):
cls.page = 等待 cls.browser.newPage()
等待 asyncio.sleep(1)
等待 cls.page.setJavaScriptEnabled(True)
@classmethod
异步定义_init_webpage_properties(cls):
等待 cls.page.evaluate('''() =>{
Object.defineProperties(导航器,{
网络驱动程序:{
得到:()=>假
}
})
}''')
等待 cls.page.evaluate('''() =>{
Object.defineProperties(窗口,{
铬合金:{
得到:()=>真
}
})
}''')
async def _connect_website(self):
等待 self.page.goto(self.url, {'waitUntil': 'networkidle2', 'timeout': 60000})
等待 asyncio.sleep(6)
self._title = 等待 self.page.evaluate('''() => {
返回文档.title
}''')
self._page_source = 等待 self.page.content()
async def _take_snapshot(self):
await self.page.screenshot({'path': f"snapshots/{self.url.strip('https://').strip('http://').replace('.', '_' ).replace('/','-')}.png"})
@财产
def page_source(self):
返回 self._page_source
@财产
定义标题(自我):
返回自我._title
异步定义关闭(自我):
等待 self.browser.close()
异步定义主():
parser = ArgumentParser(description='获取网页 URL 的 HTMl 的工具')
parser.add_argument('-u', '--url', dest='url', type=str, required=True, metavar='URL',
help='要检索 HTML 的网站的 URL')
args = parser.parse_args()
kwargs = 变量(参数)
如果不是 kwargs.get('url') 为无:
检索器 = HTMLRetriever(url=kwargs.get('url'))
等待检索器.load()
打印(retriever.title)
等待检索器.close()
如果 __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())