用chardect库解决网页乱码问题

优采云 发布时间: 2022-06-18 12:20

  用chardect库解决网页乱码问题

  写爬虫时经常对网址发起请求,结果返回的html数据除了标签能看懂,其他的全部是乱码。大家如果对爬虫感兴趣,请耐心阅读本文,我们就以百度风雨榜爬虫为例学习下乱码处理问题。

  http://top.baidu.com/buzz?b=1

  

  

  百度风云榜一共有50个关键词,我们先任选其中一个打开看看。

  一、实验目的

  我们的目的是学会使用chardect库,对乱码内容进行处理。本文会以一个具体的例子,通过实战的方式获取正确编码的数据。

  二、代码实战2.1 定位关键词及其链接

  F12键盘打开开发者工具,我们定位关键词及其对应的html标签。在这里我们使用pyquery库定位 class属性为'keyword'的td。

  #百度风云榜页面网址(含有50个热门新闻的关键词)<br />fengyunbang_url = 'http://top.baidu.com/buzz?b=1'<br /><br />resp = requests.get(fengyunbang_url)<br /><br />#从html文件中解析出  事件字段和 网址字段<br />doc = PyQuery(resp.text)<br />for item in doc.items('.keyword'):

   keyword = item('a').text().split(' ')[0]<br />

   keyword_link=item('a').attr.href    <br />    print(keyword,keyword_link)

  运行,结果keyword全部为乱码,没有一点中文的痕迹。

  这就是我们今天要克服的问题-html编码问题。

  遇到这种问题问题,我们可能会先在html标签中查找charset字符集。一般charset值有utf-8、gbk、gb2312、ascii等。

  再次运行,汉字正常显示。

  2.2 定位搜索页面新闻链接

  上面我们获取到了关键词及其链接,浏览器点击“46年吃3万个汉堡”对应的链接,跳转到 百度搜索页,如下图。

  我们想获取新闻内容,而要获取新闻内容,我们就要知道新闻对应的链接。首先我们要定位,如下图。这里我们使用另外一种方式定位链接-正则表达式。

  def get_keywords_news_links(keyword_link):

   """

   访问关键词百度网址,得到相关新闻的link

   :param keyword_link:

   :return:

   """

   headers = {'User-Agent': '你的user-agent'}

   

   resp = requests.get(keyword_link, headers=headers)<br />

   bsObj = BeautifulSoup(resp.text, 'html.parser')<br />

   news_items = bsObj.find_all('div', {'class': 'result c-container '})

   

   news_links = []

   for item in news_items:<br />

       links = re.findall('href="(.*?)"', str(item))<br />

       news_links.extend(links)

   

   #防止链接重复

   news_links = set(news_links)

   return news_links

  但是后来发现有的链接是无法访问的,比如运行中居然抽取出含有***这种的网页,经过测试,只要剔除掉这种链接,剩下的都为有效链接。

  2.3 获取新闻文本内容

  有了上文获取到的链接,我们写个简单的代码获取文本内容。由于获取到的网址来源成百上千的网站,如果要精确获取新闻内容,需要对每一个网站*敏*感*词*的进行定位。这样太麻烦,为了快速方便,我们使用正则匹配出所有的中文内容。

  def get_news_content(link):

   """

   根据新闻网址,获取新闻数据

   :return:  新闻内容

   """

   resp = requests.get(link)

   #最终只有汉字保留。

   news_text = ''.join(re.findall('[\u4e00-\u9fa5]+', resp.text))<br />

   return news_text

  但是运行过程中,经常返回空。说明正则匹配中文时候匹配不到。很可能的原因是页面中没有中文,但是我们检测了这些页面都是有中文的,那么很有可能是因为页面乱码,导致正则[\u4e00-\u9fa5]+无法匹配到中文。经过检测,真的是乱码。解决办法resp.encoding='编码'。但是编码是什么值呢?这里我用新的方法,chardect库检测二进制数据中采用的编码方式。

  def get_news_content(link):

   """

   根据新闻网址,获取新闻数据

   :return:  新闻内容

   """

   resp = requests.get(link)

   news_text = ''.join(re.findall('[\u4e00-\u9fa5]+',

   resp.text))

   

   #网页乱码,导致news_text为空

   if not news_text:

       #根据二进制数据检测html的编码。resp.content获取html二进制数据

       encoding = resp.content['encoding']

       chaset = chardet.detect(encoding)

       #解决编码问题

       resp.encoding = chaset

       news_text = ''.join(re.findall('[\u4e00-\u9fa5]+', resp.text))

       <br />        return news_text    <br />    return news_text

  2.4 编写爬虫主函数

  编写爬虫主函数,将数据保存到csv中。

  #主函数,访问并保存所有的新闻数据<br />def FetchAndSave():

   #百度风云榜页面网址(含有50个热门新闻的关键词)

   fengyunbang_url = 'http://top.baidu.com/buzz?b=1'

   resp = requests.get(fengyunbang_url)

   resp.encoding='gb2312'

   #新建excel文件保存数据。

   csvf = open('data.csv', 'a+', encoding='gbk', newline='') as csvf

                           

   writer = csv.writer(csvf)

   writer.writerow(('news_content', 'keyword'))

   #从heml文件中解析出  事件字段和 网址字段

   doc = PyQuery(resp.text)

   for item in doc.items('.keyword'):

       keyword = item('a').text().split(' ')[0]<br />

       keyword_link = item('a').attr.href

       news_links = get_keywords_news_links(keyword_link)<br />

       for news_link in news_links:

           try:

               content = get_news_content(news_link)

               #防止空内容写入csv中

               if content:

                   writer.writerow((content, keyword))

           except:

               print(news_link)<br /><br /><br />#运行爬虫<br />FetchAndSave()

  运行爬虫,采集了50个关键词共388篇新闻内容。

  

  有问题,问大邓

  项目代码链接: 密码: sqfb

  往期文章

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线