在上一篇爬虫博客中,我们讲述了应对IP访问限制的策略,即爬取代理IP并不断改变代理的方式。但是某些网站不仅在访问时做了限制,而且在返回网页时也做了巧妙的处理,比如在页面加载时调用js动态请求内容等。这种情况就不是简单的发出一个get请求可以爬取的了,这个时候可能就需要调用谷歌浏览器来实现爬取。本篇我们介绍通过C#调用谷歌浏览器来实现动态信息爬取。
普通爬虫遭遇的困境
假如我们要爬取某博客页面的详细信息,如标题,正文,作者,发布时间,阅读数等等。我们的第一思路是对这个页面的url发送一个get请求,对返回的网页报文通过xpath解析我们需要的信息。下面以一个博客详情页面为例:C#攻克反爬虫之代理IP爬取
class Program
{
static void Main(string[] args)
{
BasicalMothed("https://blog.csdn.net/Leaderxin/article/details/102764234"); //调用原始方法
Console.Read();
}
/// <summary>
/// 这个我们普通的爬虫思路,通过请求url返回报文爬取
/// </summary>
static void BasicalMothed(string url)
{
HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest;
if (req == null)
return;
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Encoding bin = Encoding.GetEncoding("UTF-8");
using (StreamReader sr = new StreamReader(resp.GetResponseStream(), bin))
{
string str = sr.ReadToEnd();
Console.WriteLine(str.ToString());
//在这里通过xpath对str的内容进行解析并存储
return ;
}
}
}
我们看一下打印出来的报文内容:
返回内容是乱码,明显某平台做了巧妙的处理,直接请求这个url是无法得到我们想要的报文的。还有一些场景,比如说某些网页里会有类似【更多】这样的按钮,点击后页面才会请求并渲染更多内容,这种也是无法通过直接请求该网页爬取的。
通过chromedriver调用浏览器
下面我们通过C#调用chromedriver来控制浏览器访问我们要爬取的页面并实现爬取。首先通过nuget安装Selenium库:
注意如果安装Selenium时选择的是最新版的,需要将谷歌浏览器更新到最新,不然调用的时候会有异常
然后我们通过F12看下要爬取页面的结构,看看我们要爬取的信息在哪些标签里,结果如下:
标题在class ='title-article’的h1中,发布时间在class='time’的span中,博主在class='follow-nickName’的a标签中,阅读数在class='read-count’的span中,正文在id='article_content’的div中。
然后编码调用谷歌浏览器访问这个页面并取到我们指定元素:
/// <summary>
/// 通过Selenium调用谷歌浏览器来爬取
/// </summary>
/// <param name="url"></param>
static void SeleniumMothed(string url)
{
//启动谷歌浏览器
IWebDriver selenium = new ChromeDriver();
//浏览器跳转到我们要爬取的url
selenium.Navigate().GoToUrl(url);
//确保页面内容已加载完成
while (string.IsNullOrEmpty(selenium.Title))
{
Task.Delay(100).GetAwaiter().GetResult();
}
//取到标题信息,通过css选择器
var title = selenium.FindElement(By.CssSelector("h1.title-article")).Text;
//发布时间
var time = selenium.FindElement(By.CssSelector("span.time")).Text;
//博主名
var name = selenium.FindElement(By.CssSelector("a.follow-nickName")).Text;
//阅读数
var nums = selenium.FindElement(By.CssSelector("span.read-count")).Text;
//正文,由于id固定,我们直接用id选择器获取
var content = selenium.FindElement(By.Id("article_content")).Text;
Console.WriteLine("标题:"+title);
Console.WriteLine("发布时间:"+time);
Console.WriteLine("博主名:"+name);
Console.WriteLine("阅读数:"+nums);
Console.WriteLine("正文:"+content);
}
看下控制台打印结果:
可以看到,已经成功通过调用Chrome爬取到了我们想要的信息。Selenium能做到的事情还远不止如此,有兴趣的可以自己研究下。后面也会继续讲Selenium的一些其它用法。
上一篇:C#攻克反爬虫之代理IP爬取